From 567da5bbd027e8318ed0e8af817b73a9285892c3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 17 Jun 2017 23:48:52 +0300 Subject: [PATCH] DPP: Add new AKM This new AKM is used with DPP when using the signed Connector to derive a PMK. Since the KCK, KEK, and MIC lengths are variable within a single AKM, this needs number of additional changes to get the PMK length delivered to places that need to figure out the lengths of the PTK components. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 4 ++ hostapd/ctrl_iface.c | 9 ++++ src/ap/ieee802_11.c | 2 + src/ap/ieee802_1x.c | 6 ++- src/ap/wpa_auth.c | 84 +++++++++++++++++++++---------- src/ap/wpa_auth.h | 2 +- src/ap/wpa_auth_i.h | 1 + src/ap/wpa_auth_ie.c | 23 +++++++++ src/common/defs.h | 4 +- src/common/wpa_common.c | 73 +++++++++++++++++++++++---- src/common/wpa_common.h | 9 ++-- src/drivers/driver.h | 1 + src/drivers/driver_nl80211_capa.c | 3 +- src/rsn_supp/peerkey.c | 2 +- src/rsn_supp/wpa.c | 26 +++++++--- src/rsn_supp/wpa.h | 2 + src/rsn_supp/wpa_ie.c | 4 ++ wlantest/rx_eapol.c | 12 ++--- wpa_supplicant/config.c | 4 ++ wpa_supplicant/ctrl_iface.c | 18 +++++++ wpa_supplicant/events.c | 16 +++++- wpa_supplicant/wpa_supplicant.c | 9 +++- wpa_supplicant/wpas_glue.c | 1 + 23 files changed, 255 insertions(+), 60 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 394658985..0924d41cc 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -715,6 +715,10 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value) else if (os_strcmp(start, "OWE") == 0) val |= WPA_KEY_MGMT_OWE; #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + else if (os_strcmp(start, "DPP") == 0) + val |= WPA_KEY_MGMT_DPP; +#endif /* CONFIG_DPP */ else { wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", line, start); diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 1a7764ab3..4f49b5c4f 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1110,6 +1110,15 @@ static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd, } #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) { + ret = os_snprintf(pos, end - pos, "DPP "); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_DPP */ + if (pos > buf && *(pos - 1) == ' ') { *(pos - 1) = '\0'; pos--; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index b9f819c74..3e0a2dd55 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1012,6 +1012,8 @@ static u16 wpa_res_to_status_code(int res) #endif /* CONFIG_IEEE80211W */ if (res == WPA_INVALID_MDIE) return WLAN_STATUS_INVALID_MDIE; + if (res == WPA_INVALID_PMKID) + return WLAN_STATUS_INVALID_PMKID; if (res != WPA_IE_OK) return WLAN_STATUS_INVALID_IE; return WLAN_STATUS_SUCCESS; diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index ae38f6c7d..6ea1ebe54 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -974,7 +974,8 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm); if (key_mgmt != -1 && - (wpa_key_mgmt_wpa_psk(key_mgmt) || key_mgmt == WPA_KEY_MGMT_OWE)) { + (wpa_key_mgmt_wpa_psk(key_mgmt) || key_mgmt == WPA_KEY_MGMT_OWE || + key_mgmt == WPA_KEY_MGMT_DPP)) { wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - " "STA is using PSK"); return; @@ -1118,7 +1119,8 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm); if (key_mgmt != -1 && - (wpa_key_mgmt_wpa_psk(key_mgmt) || key_mgmt == WPA_KEY_MGMT_OWE)) { + (wpa_key_mgmt_wpa_psk(key_mgmt) || key_mgmt == WPA_KEY_MGMT_OWE || + key_mgmt == WPA_KEY_MGMT_DPP)) { wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - using PSK"); /* * Clear any possible EAPOL authenticator state to support diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 459b56e58..07da33ffc 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -35,8 +35,8 @@ static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx); static int wpa_sm_step(struct wpa_state_machine *sm); -static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data, - size_t data_len); +static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK, + u8 *data, size_t data_len); #ifdef CONFIG_FILS static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk, u8 *buf, size_t buf_len, u16 *_key_data_len); @@ -226,13 +226,13 @@ void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, - const u8 *addr) + const u8 *addr, u16 reason) { if (wpa_auth->cb->disconnect == NULL) return; - wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR, MAC2STR(addr)); - wpa_auth->cb->disconnect(wpa_auth->cb_ctx, addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); + wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)", + MAC2STR(addr), reason); + wpa_auth->cb->disconnect(wpa_auth->cb_ctx, addr, reason); } @@ -866,8 +866,8 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK) < 0) break; - if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK, data, data_len) - == 0) { + if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK, + data, data_len) == 0) { ok = 1; break; } @@ -912,7 +912,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, return; wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len); - mic_len = wpa_mic_len(sm->wpa_key_mgmt); + mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); keyhdrlen = sizeof(*key) + mic_len + 2; if (data_len < sizeof(*hdr) + keyhdrlen) { @@ -1025,6 +1025,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, if (!wpa_use_aes_cmac(sm) && !wpa_key_mgmt_fils(sm->wpa_key_mgmt) && sm->wpa_key_mgmt != WPA_KEY_MGMT_OWE && + sm->wpa_key_mgmt != WPA_KEY_MGMT_DPP && ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, @@ -1036,6 +1037,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, if ((wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) || wpa_key_mgmt_fils(sm->wpa_key_mgmt) || + sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP || sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) && ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, @@ -1160,7 +1162,8 @@ continue_processing: "collect more entropy for random number " "generation"); random_mark_pool_ready(); - wpa_sta_disconnect(wpa_auth, sm->addr); + wpa_sta_disconnect(wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); return; } break; @@ -1238,8 +1241,8 @@ continue_processing: sm->MICVerified = FALSE; if (sm->PTK_valid && !sm->update_snonce) { if (mic_len && - wpa_verify_key_mic(sm->wpa_key_mgmt, &sm->PTK, data, - data_len) && + wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK, + data, data_len) && (msg != PAIRWISE_4 || !sm->alt_snonce_valid || wpa_try_alt_snonce(sm, data, data_len))) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, @@ -1419,7 +1422,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, int i; u8 *key_mic, *key_data; - mic_len = wpa_mic_len(sm->wpa_key_mgmt); + mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); keyhdrlen = sizeof(*key) + mic_len + 2; len = sizeof(struct ieee802_1x_hdr) + keyhdrlen; @@ -1428,6 +1431,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, version = force_version; else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE || + sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP || wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) || wpa_key_mgmt_fils(sm->wpa_key_mgmt)) version = WPA_KEY_INFO_TYPE_AKM_DEFINED; @@ -1454,6 +1458,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE || + sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) || version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) { @@ -1557,6 +1562,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, buf, key_data_len); if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE || + sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) || version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { @@ -1656,15 +1662,15 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth, } -static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data, - size_t data_len) +static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK, + u8 *data, size_t data_len) { struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; u16 key_info; int ret = 0; u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos; - size_t mic_len = wpa_mic_len(akmp); + size_t mic_len = wpa_mic_len(akmp, pmk_len); if (data_len < sizeof(*hdr) + sizeof(*key)) return -1; @@ -1837,6 +1843,7 @@ SM_STATE(WPA_PTK, INITIALIZE) wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0); sm->TimeoutCtr = 0; if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || + sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP || sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) { wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_authorized, 0); @@ -1846,9 +1853,14 @@ SM_STATE(WPA_PTK, INITIALIZE) SM_STATE(WPA_PTK, DISCONNECT) { + u16 reason = sm->disconnect_reason; + SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk); sm->Disconnect = FALSE; - wpa_sta_disconnect(sm->wpa_auth, sm->addr); + sm->disconnect_reason = 0; + if (!reason) + reason = WLAN_REASON_PREV_AUTH_NOT_VALID; + wpa_sta_disconnect(sm->wpa_auth, sm->addr, reason); } @@ -1949,6 +1961,14 @@ SM_STATE(WPA_PTK, INITPMK) wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache"); os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len); sm->pmk_len = sm->pmksa->pmk_len; +#ifdef CONFIG_DPP + } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) { + wpa_printf(MSG_DEBUG, + "DPP: No PMKSA cache entry for STA - reject connection"); + sm->Disconnect = TRUE; + sm->disconnect_reason = WLAN_REASON_INVALID_PMKID; + return; +#endif /* CONFIG_DPP */ } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) { unsigned int pmk_len; @@ -2596,7 +2616,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) sm->update_snonce = FALSE; os_memset(&PTK, 0, sizeof(PTK)); - mic_len = wpa_mic_len(sm->wpa_key_mgmt); + mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); /* WPA with IEEE 802.1X: use the derived PMK from EAP * WPA-PSK: iterate through possible PSKs and select the one matching @@ -2618,7 +2638,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) break; if (mic_len && - wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK, + wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK, sm->last_rx_eapol_key, sm->last_rx_eapol_key_len) == 0) { ok = 1; @@ -2687,12 +2707,14 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4", eapol_key_ie, eapol_key_ie_len); /* MLME-DEAUTHENTICATE.request */ - wpa_sta_disconnect(wpa_auth, sm->addr); + wpa_sta_disconnect(wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); return; } #ifdef CONFIG_IEEE80211R_AP if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) { - wpa_sta_disconnect(wpa_auth, sm->addr); + wpa_sta_disconnect(wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); return; } #endif /* CONFIG_IEEE80211R_AP */ @@ -3002,7 +3024,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_send_eapol(sm->wpa_auth, sm, (secure ? WPA_KEY_INFO_SECURE : 0) | - (wpa_mic_len(sm->wpa_key_mgmt) ? WPA_KEY_INFO_MIC : 0) | + (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? + WPA_KEY_INFO_MIC : 0) | WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_KEY_TYPE, _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); @@ -3019,7 +3042,8 @@ SM_STATE(WPA_PTK, PTKINITDONE) int klen = wpa_cipher_key_len(sm->pairwise); if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, sm->PTK.tk, klen)) { - wpa_sta_disconnect(sm->wpa_auth, sm->addr); + wpa_sta_disconnect(sm->wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); return; } /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ @@ -3033,6 +3057,7 @@ SM_STATE(WPA_PTK, PTKINITDONE) } if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || + sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP || sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) { wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_authorized, 1); @@ -3106,12 +3131,18 @@ SM_STEP(WPA_PTK) sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE /* FIX: && 802.1X::keyRun */) SM_ENTER(WPA_PTK, INITPSK); + else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) + SM_ENTER(WPA_PTK, INITPMK); break; case WPA_PTK_INITPMK: if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr, - WPA_EAPOL_keyAvailable) > 0) + WPA_EAPOL_keyAvailable) > 0) { SM_ENTER(WPA_PTK, PTKSTART); - else { +#ifdef CONFIG_DPP + } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) { + SM_ENTER(WPA_PTK, PTKSTART); +#endif /* CONFIG_DPP */ + } else { wpa_auth->dot11RSNA4WayHandshakeFailures++; wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, "INITPMK - keyAvailable = false"); @@ -3250,7 +3281,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) wpa_send_eapol(sm->wpa_auth, sm, WPA_KEY_INFO_SECURE | - (wpa_mic_len(sm->wpa_key_mgmt) ? WPA_KEY_INFO_MIC : 0) | + (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? + WPA_KEY_INFO_MIC : 0) | WPA_KEY_INFO_ACK | (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), rsc, NULL, kde, kde_len, gsm->GN, 1); diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index c1aeb87bf..7d6e01594 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -276,7 +276,7 @@ enum { WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE, WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL, WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER, - WPA_INVALID_MDIE, WPA_INVALID_PROTO + WPA_INVALID_MDIE, WPA_INVALID_PROTO, WPA_INVALID_PMKID }; int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index e7d699ee5..23d2af307 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -43,6 +43,7 @@ struct wpa_state_machine { Boolean AuthenticationRequest; Boolean ReAuthenticationRequest; Boolean Disconnect; + u16 disconnect_reason; /* specific reason code to use with Disconnect */ u32 TimeoutCtr; u32 GTimeoutCtr; Boolean TimeoutEvt; diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index b1444d922..ff7b97ae1 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -241,6 +241,13 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, num_suites++; } #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_DPP); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_DPP */ #ifdef CONFIG_RSN_TESTING if (rsn_testing) { @@ -579,6 +586,10 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, else if (data.key_mgmt & WPA_KEY_MGMT_OWE) selector = RSN_AUTH_KEY_MGMT_OWE; #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + else if (data.key_mgmt & WPA_KEY_MGMT_DPP) + selector = RSN_AUTH_KEY_MGMT_DPP; +#endif /* CONFIG_DPP */ wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; selector = wpa_cipher_to_suite(WPA_PROTO_RSN, @@ -675,6 +686,10 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, else if (key_mgmt & WPA_KEY_MGMT_OWE) sm->wpa_key_mgmt = WPA_KEY_MGMT_OWE; #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + else if (key_mgmt & WPA_KEY_MGMT_DPP) + sm->wpa_key_mgmt = WPA_KEY_MGMT_DPP; +#endif /* CONFIG_DPP */ else sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK; @@ -804,6 +819,14 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN); } +#ifdef CONFIG_DPP + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && !sm->pmksa) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "No PMKSA cache entry found for DPP"); + return WPA_INVALID_PMKID; + } +#endif /* CONFIG_DPP */ + if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) { os_free(sm->wpa_ie); sm->wpa_ie = os_malloc(wpa_ie_len); diff --git a/src/common/defs.h b/src/common/defs.h index 023fe200a..ffe4fecf7 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -56,6 +56,7 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean; #define WPA_KEY_MGMT_FT_FILS_SHA256 BIT(20) #define WPA_KEY_MGMT_FT_FILS_SHA384 BIT(21) #define WPA_KEY_MGMT_OWE BIT(22) +#define WPA_KEY_MGMT_DPP BIT(23) static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) { @@ -138,7 +139,8 @@ static inline int wpa_key_mgmt_wpa(int akm) wpa_key_mgmt_wpa_psk(akm) || wpa_key_mgmt_fils(akm) || wpa_key_mgmt_sae(akm) || - akm == WPA_KEY_MGMT_OWE; + akm == WPA_KEY_MGMT_OWE || + akm == WPA_KEY_MGMT_DPP; } static inline int wpa_key_mgmt_wpa_any(int akm) diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 8eabf5435..47b0d425b 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -13,6 +13,7 @@ #include "crypto/sha1.h" #include "crypto/sha256.h" #include "crypto/sha384.h" +#include "crypto/sha512.h" #include "crypto/aes_wrap.h" #include "crypto/crypto.h" #include "ieee802_11_defs.h" @@ -20,7 +21,7 @@ #include "wpa_common.h" -static unsigned int wpa_kck_len(int akmp) +static unsigned int wpa_kck_len(int akmp, size_t pmk_len) { switch (akmp) { case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: @@ -30,13 +31,15 @@ static unsigned int wpa_kck_len(int akmp) case WPA_KEY_MGMT_FILS_SHA384: case WPA_KEY_MGMT_FT_FILS_SHA384: return 0; + case WPA_KEY_MGMT_DPP: + return pmk_len / 2; default: return 16; } } -static unsigned int wpa_kek_len(int akmp) +static unsigned int wpa_kek_len(int akmp, size_t pmk_len) { switch (akmp) { case WPA_KEY_MGMT_FILS_SHA384: @@ -46,13 +49,15 @@ static unsigned int wpa_kek_len(int akmp) case WPA_KEY_MGMT_FILS_SHA256: case WPA_KEY_MGMT_FT_FILS_SHA256: return 32; + case WPA_KEY_MGMT_DPP: + return pmk_len <= 32 ? 16 : 32; default: return 16; } } -unsigned int wpa_mic_len(int akmp) +unsigned int wpa_mic_len(int akmp, size_t pmk_len) { switch (akmp) { case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: @@ -62,6 +67,8 @@ unsigned int wpa_mic_len(int akmp) case WPA_KEY_MGMT_FT_FILS_SHA256: case WPA_KEY_MGMT_FT_FILS_SHA384: return 0; + case WPA_KEY_MGMT_DPP: + return pmk_len / 2; default: return 16; } @@ -91,7 +98,7 @@ unsigned int wpa_mic_len(int akmp) int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, const u8 *buf, size_t len, u8 *mic) { - u8 hash[SHA384_MAC_LEN]; + u8 hash[SHA512_MAC_LEN]; switch (ver) { #ifndef CONFIG_FIPS @@ -145,6 +152,29 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, os_memcpy(mic, hash, MD5_MAC_LEN); break; #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + case WPA_KEY_MGMT_DPP: + wpa_printf(MSG_DEBUG, + "WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - DPP)", + (unsigned int) key_len * 8 * 2); + if (key_len == 128 / 8) { + if (hmac_sha256(key, key_len, buf, len, hash)) + return -1; + } else if (key_len == 192 / 8) { + if (hmac_sha384(key, key_len, buf, len, hash)) + return -1; + } else if (key_len == 256 / 8) { + if (hmac_sha256(key, key_len, buf, len, hash)) + return -1; + } else { + wpa_printf(MSG_INFO, + "DPP: Unsupported KCK length: %u", + (unsigned int) key_len); + return -1; + } + os_memcpy(mic, hash, key_len / 8); + break; +#endif /* CONFIG_DPP */ default: wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC algorithm not known (AKM-defined - akmp=0x%x)", @@ -213,8 +243,8 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, WPA_NONCE_LEN); } - ptk->kck_len = wpa_kck_len(akmp); - ptk->kek_len = wpa_kek_len(akmp); + ptk->kck_len = wpa_kck_len(akmp, pmk_len); + ptk->kek_len = wpa_kek_len(akmp, pmk_len); ptk->tk_len = wpa_cipher_key_len(cipher); ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len; @@ -236,6 +266,27 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, #else /* CONFIG_IEEE80211W */ return -1; #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_DPP + } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 32) { + wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)"); + if (sha256_prf(pmk, pmk_len, label, data, sizeof(data), + tmp, ptk_len) < 0) + return -1; + } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 48) { + wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA384)"); + if (sha384_prf(pmk, pmk_len, label, data, sizeof(data), + tmp, ptk_len) < 0) + return -1; + } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 64) { + wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA512)"); + if (sha512_prf(pmk, pmk_len, label, data, sizeof(data), + tmp, ptk_len) < 0) + return -1; + } else if (akmp == WPA_KEY_MGMT_DPP) { + wpa_printf(MSG_INFO, "DPP: Unknown PMK length %u", + (unsigned int) pmk_len); + return -1; +#endif /* CONFIG_DPP */ } else { wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA1)"); if (sha1_prf(pmk, pmk_len, label, data, sizeof(data), tmp, @@ -364,7 +415,7 @@ int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa, os_memcpy(data + 2 * ETH_ALEN + FILS_NONCE_LEN, anonce, FILS_NONCE_LEN); ptk->kck_len = 0; - ptk->kek_len = wpa_kek_len(akmp); + ptk->kek_len = wpa_kek_len(akmp, pmk_len); ptk->tk_len = wpa_cipher_key_len(cipher); if (wpa_key_mgmt_sha384(akmp)) *ick_len = 48; @@ -836,6 +887,10 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s) if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OWE) return WPA_KEY_MGMT_OWE; #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_DPP) + return WPA_KEY_MGMT_DPP; +#endif /* CONFIG_DPP */ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OSEN) return WPA_KEY_MGMT_OSEN; return 0; @@ -1319,8 +1374,8 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, os_memcpy(pos, sta_addr, ETH_ALEN); pos += ETH_ALEN; - ptk->kck_len = wpa_kck_len(akmp); - ptk->kek_len = wpa_kek_len(akmp); + ptk->kck_len = wpa_kck_len(akmp, PMK_LEN); + ptk->kek_len = wpa_kek_len(akmp, PMK_LEN); ptk->tk_len = wpa_cipher_key_len(cipher); ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len; diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index c0773e8b2..f96eaa8be 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -13,7 +13,7 @@ #define PMKID_LEN 16 #define PMK_LEN 32 #define PMK_LEN_SUITE_B_192 48 -#define PMK_LEN_MAX 48 +#define PMK_LEN_MAX 64 #define WPA_REPLAY_COUNTER_LEN 8 #define WPA_NONCE_LEN 32 #define WPA_KEY_RSC_LEN 8 @@ -68,6 +68,7 @@ RSN_SELECTOR(0x00, 0x0f, 0xac, 13) #define RSN_AUTH_KEY_MGMT_OWE RSN_SELECTOR(0x00, 0x0f, 0xac, 18) #define RSN_AUTH_KEY_MGMT_CCKM RSN_SELECTOR(0x00, 0x40, 0x96, 0x00) #define RSN_AUTH_KEY_MGMT_OSEN RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x01) +#define RSN_AUTH_KEY_MGMT_DPP RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x02) #define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0) #define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1) @@ -197,8 +198,8 @@ struct wpa_eapol_key { /* followed by Key Data Length bytes of Key Data */ } STRUCT_PACKED; -#define WPA_EAPOL_KEY_MIC_MAX_LEN 24 -#define WPA_KCK_MAX_LEN 24 +#define WPA_EAPOL_KEY_MIC_MAX_LEN 32 +#define WPA_KCK_MAX_LEN 32 #define WPA_KEK_MAX_LEN 64 #define WPA_TK_MAX_LEN 32 #define FILS_ICK_MAX_LEN 48 @@ -465,7 +466,7 @@ int wpa_pick_group_cipher(int ciphers); int wpa_parse_cipher(const char *value); int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim); int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise); -unsigned int wpa_mic_len(int akmp); +unsigned int wpa_mic_len(int akmp, size_t pmk_len); int fils_domain_name_hash(const char *domain, u8 *hash); #endif /* WPA_COMMON_H */ diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 9587d063e..aee0cf60d 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1437,6 +1437,7 @@ struct wpa_driver_capa { #define WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B 0x00000100 #define WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192 0x00000200 #define WPA_DRIVER_CAPA_KEY_MGMT_OWE 0x00000400 +#define WPA_DRIVER_CAPA_KEY_MGMT_DPP 0x00000800 /** Bitfield of supported key management suites */ unsigned int key_mgmt; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 9aa4e14e6..3d747ce0f 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -1133,7 +1133,8 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK | WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B | WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192 | - WPA_DRIVER_CAPA_KEY_MGMT_OWE; + WPA_DRIVER_CAPA_KEY_MGMT_OWE | + WPA_DRIVER_CAPA_KEY_MGMT_DPP; drv->capa.auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED | WPA_DRIVER_AUTH_LEAP; diff --git a/src/rsn_supp/peerkey.c b/src/rsn_supp/peerkey.c index ce338f8fd..415afc90b 100644 --- a/src/rsn_supp/peerkey.c +++ b/src/rsn_supp/peerkey.c @@ -1005,7 +1005,7 @@ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) return -1; } - mic_len = wpa_mic_len(sm->key_mgmt); + mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); if (sm->pairwise_cipher != WPA_CIPHER_TKIP) ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; else diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 4e5b0a4f7..183823ff4 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -49,7 +49,7 @@ int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk, u8 *msg, size_t msg_len, u8 *key_mic) { int ret = -1; - size_t mic_len = wpa_mic_len(sm->key_mgmt); + size_t mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); wpa_printf(MSG_DEBUG, "WPA: Send EAPOL-Key frame to " MACSTR " ver=%d mic_len=%d key_mgmt=0x%x", @@ -197,7 +197,7 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) return; } - mic_len = wpa_mic_len(sm->key_mgmt); + mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); hdrlen = sizeof(*reply) + mic_len + 2; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, hdrlen, &rlen, (void *) &reply); @@ -469,7 +469,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len); - mic_len = wpa_mic_len(sm->key_mgmt); + mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); hdrlen = sizeof(*reply) + mic_len + 2; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, hdrlen + wpa_ie_len, @@ -657,6 +657,7 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); eapol_sm_notify_portValid(sm->eapol, TRUE); if (wpa_key_mgmt_wpa_psk(sm->key_mgmt) || + sm->key_mgmt == WPA_KEY_MGMT_DPP || sm->key_mgmt == WPA_KEY_MGMT_OWE) eapol_sm_notify_eap_success(sm->eapol, TRUE); /* @@ -1234,7 +1235,7 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, struct wpa_eapol_key *reply; u8 *rbuf, *key_mic; - mic_len = wpa_mic_len(sm->key_mgmt); + mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); hdrlen = sizeof(*reply) + mic_len + 2; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, hdrlen, &rlen, (void *) &reply); @@ -1543,7 +1544,7 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, struct wpa_eapol_key *reply; u8 *rbuf, *key_mic; - mic_len = wpa_mic_len(sm->key_mgmt); + mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); hdrlen = sizeof(*reply) + mic_len + 2; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, hdrlen, &rlen, (void *) &reply); @@ -1654,7 +1655,7 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, { u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; int ok = 0; - size_t mic_len = wpa_mic_len(sm->key_mgmt); + size_t mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); os_memcpy(mic, key + 1, mic_len); if (sm->tptk_set) { @@ -1740,6 +1741,7 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || ver == WPA_KEY_INFO_TYPE_AES_128_CMAC || sm->key_mgmt == WPA_KEY_MGMT_OWE || + sm->key_mgmt == WPA_KEY_MGMT_DPP || sm->key_mgmt == WPA_KEY_MGMT_OSEN || wpa_key_mgmt_suite_b(sm->key_mgmt)) { u8 *buf; @@ -1936,7 +1938,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, sm->ft_completed = 0; #endif /* CONFIG_IEEE80211R */ - mic_len = wpa_mic_len(sm->key_mgmt); + mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); keyhdrlen = sizeof(*key) + mic_len + 2; if (len < sizeof(*hdr) + keyhdrlen) { @@ -2022,6 +2024,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, !wpa_key_mgmt_suite_b(sm->key_mgmt) && !wpa_key_mgmt_fils(sm->key_mgmt) && sm->key_mgmt != WPA_KEY_MGMT_OWE && + sm->key_mgmt != WPA_KEY_MGMT_DPP && sm->key_mgmt != WPA_KEY_MGMT_OSEN) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Unsupported EAPOL-Key descriptor version %d", @@ -2039,6 +2042,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, if ((wpa_key_mgmt_suite_b(sm->key_mgmt) || wpa_key_mgmt_fils(sm->key_mgmt) || + sm->key_mgmt == WPA_KEY_MGMT_DPP || sm->key_mgmt == WPA_KEY_MGMT_OWE) && ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, @@ -2074,6 +2078,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, !wpa_key_mgmt_suite_b(sm->key_mgmt) && !wpa_key_mgmt_fils(sm->key_mgmt) && sm->key_mgmt != WPA_KEY_MGMT_OWE && + sm->key_mgmt != WPA_KEY_MGMT_DPP && ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: CCMP is used, but EAPOL-Key " @@ -3094,6 +3099,13 @@ void wpa_sm_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, } +int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid, + const void *network_ctx) +{ + return pmksa_cache_get(sm->pmksa, bssid, NULL, network_ctx) != NULL; +} + + void wpa_sm_drop_sa(struct wpa_sm *sm) { wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK"); diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index bee1c9221..37c5d62f1 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -160,6 +160,8 @@ wpa_sm_pmksa_cache_add_entry(struct wpa_sm *sm, void wpa_sm_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, const u8 *pmkid, const u8 *bssid, const u8 *fils_cache_id); +int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid, + const void *network_ctx); void wpa_sm_drop_sa(struct wpa_sm *sm); int wpa_sm_has_ptk(struct wpa_sm *sm); diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index cd7f14e21..627bfeb42 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -196,6 +196,10 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, } else if (key_mgmt & WPA_KEY_MGMT_OWE) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE); #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + } else if (key_mgmt & WPA_KEY_MGMT_DPP) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_DPP); +#endif /* CONFIG_DPP */ } else { wpa_printf(MSG_WARNING, "Invalid key management type (%d).", key_mgmt); diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index c4f5e8da5..a0c6845b6 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -39,7 +39,7 @@ static int check_mic(const u8 *kck, size_t kck_len, int akmp, int ver, struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; u8 rx_mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; - size_t mic_len = wpa_mic_len(akmp); + size_t mic_len = wpa_mic_len(akmp, PMK_LEN); buf = os_memdup(data, len); if (buf == NULL) @@ -244,7 +244,7 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, eapol = (const struct ieee802_1x_hdr *) data; hdr = (const struct wpa_eapol_key *) (eapol + 1); - mic_len = wpa_mic_len(sta->key_mgmt); + mic_len = wpa_mic_len(sta->key_mgmt, PMK_LEN); mic = (const u8 *) (hdr + 1); if (is_zero(hdr->key_nonce, WPA_NONCE_LEN)) { add_note(wt, MSG_INFO, "EAPOL-Key 2/4 from " MACSTR @@ -413,7 +413,7 @@ static u8 * decrypt_eapol_key_data(struct wlantest *wt, int akmp, const u8 *kek, return NULL; mic = (const u8 *) (hdr + 1); - mic_len = wpa_mic_len(akmp); + mic_len = wpa_mic_len(akmp, PMK_LEN); keydata = mic + mic_len + 2; keydatalen = WPA_GET_BE16(mic + mic_len); @@ -574,7 +574,7 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, sta = sta_get(bss, dst); if (sta == NULL) return; - mic_len = wpa_mic_len(sta->key_mgmt); + mic_len = wpa_mic_len(sta->key_mgmt, PMK_LEN); eapol = (const struct ieee802_1x_hdr *) data; hdr = (const struct wpa_eapol_key *) (eapol + 1); @@ -805,7 +805,7 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst, sta = sta_get(bss, dst); if (sta == NULL) return; - mic_len = wpa_mic_len(sta->key_mgmt); + mic_len = wpa_mic_len(sta->key_mgmt, PMK_LEN); eapol = (const struct ieee802_1x_hdr *) data; hdr = (const struct wpa_eapol_key *) (eapol + 1); @@ -974,7 +974,7 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *bssid, if (bss) { sta = sta_get(bss, sta_addr); if (sta) - mic_len = wpa_mic_len(sta->key_mgmt); + mic_len = wpa_mic_len(sta->key_mgmt, PMK_LEN); } eapol = (const struct ieee802_1x_hdr *) data; diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 0248d7981..0be77ff22 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -780,6 +780,10 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data, else if (os_strcmp(start, "OWE") == 0) val |= WPA_KEY_MGMT_OWE; #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + else if (os_strcmp(start, "DPP") == 0) + val |= WPA_KEY_MGMT_DPP; +#endif /* CONFIG_DPP */ else { wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", line, start); diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index d8363a48c..61ea6392e 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -2610,6 +2610,16 @@ static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, } #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + if (data.key_mgmt & WPA_KEY_MGMT_DPP) { + ret = os_snprintf(pos, end - pos, "%sDPP", + pos == start ? "" : "+"); + if (os_snprintf_error(end - pos, ret)) + return pos; + pos += ret; + } +#endif /* CONFIG_DPP */ + if (data.key_mgmt & WPA_KEY_MGMT_OSEN) { ret = os_snprintf(pos, end - pos, "%sOSEN", pos == start ? "" : "+"); @@ -3836,6 +3846,14 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, pos += ret; } #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) { + ret = os_snprintf(pos, end - pos, " DPP"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_DPP */ return pos - buf; } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 648ffdc86..d16108faa 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -305,7 +305,8 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || - wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) + wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || + wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); wpa_s->ap_ies_from_associnfo = 0; wpa_s->current_ssid = NULL; @@ -1212,6 +1213,18 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, #endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_MBO */ +#ifdef CONFIG_DPP + if ((ssid->key_mgmt & WPA_KEY_MGMT_DPP) && + !wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid)) { + /* TODO: Go through DPP network introduction to generate + * PMKSA entry. */ + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - no PMKSA entry for DPP"); + continue; + } +#endif /* CONFIG_DPP */ + /* Matching configuration found */ return ssid; } @@ -2541,6 +2554,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, eapol_sm_notify_portValid(wpa_s->eapol, FALSE); } if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || + wpa_s->key_mgmt == WPA_KEY_MGMT_DPP || wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || ft_completed || already_authorized) eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 0a107b085..ca6f179a1 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1018,7 +1018,8 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers. */ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || - wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) { + wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || + wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) { /* * Clear forced success to clear EAP state for next * authentication. @@ -1359,6 +1360,11 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_s->key_mgmt = WPA_KEY_MGMT_OWE; wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE"); #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + } else if (sel & WPA_KEY_MGMT_DPP) { + wpa_s->key_mgmt = WPA_KEY_MGMT_DPP; + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP"); +#endif /* CONFIG_DPP */ } else { wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select " "authenticated key management type"); @@ -3751,6 +3757,7 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN); if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) && wpa_s->key_mgmt != WPA_KEY_MGMT_OWE && + wpa_s->key_mgmt != WPA_KEY_MGMT_DPP && eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0) return; wpa_drv_poll(wpa_s); diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index ae246f99c..8b4a883e4 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -147,6 +147,7 @@ static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf, if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || + wpa_s->key_mgmt == WPA_KEY_MGMT_DPP || wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { /* Current SSID is not using IEEE 802.1X/EAP, so drop possible * EAPOL frames (mainly, EAPOL-Start) from EAPOL state