diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index c0ea1c78c6..700b098c7b 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit c0ea1c78c6e0f91d310059965e645de460fe70e5 +Subproject commit 700b098c7bccde85aea9e151c37b20fdbff74128 diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_common.c b/components/wpa_supplicant/esp_supplicant/src/esp_common.c index 6d9f9d4b42..7671daa0e0 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_common.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_common.c @@ -153,7 +153,7 @@ static void register_mgmt_frames(struct wpa_supplicant *wpa_s) static int handle_auth_frame(u8 *frame, size_t len, u8 *sender, int8_t rssi, u8 channel) { - if (gWpaSm.key_mgmt == WPA_KEY_MGMT_FT_PSK) { + if (gWpaSm.key_mgmt == WPA_KEY_MGMT_FT_PSK || gWpaSm.key_mgmt == WPA_KEY_MGMT_FT_SAE) { if (gWpaSm.ft_protocol) { if (wpa_ft_process_response(&gWpaSm, frame + 6, len - 6, 0, sender, NULL, 0) < 0) { @@ -168,7 +168,7 @@ static int handle_auth_frame(u8 *frame, size_t len, static int handle_assoc_frame(u8 *frame, size_t len, u8 *sender, int8_t rssi, u8 channel) { - if (gWpaSm.key_mgmt == WPA_KEY_MGMT_FT_PSK) { + if (gWpaSm.key_mgmt == WPA_KEY_MGMT_FT_PSK || gWpaSm.key_mgmt == WPA_KEY_MGMT_FT_SAE) { if (gWpaSm.ft_protocol) { if (wpa_ft_validate_reassoc_resp(&gWpaSm, frame + 6, len - 6, sender)) { wpa_sm_set_ft_params(&gWpaSm, NULL, 0); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h index 348a48c500..2531548174 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -77,6 +77,7 @@ enum { WPA3_AUTH_PSK_EXT_KEY = 0x10, /* this enum is in C2 ROM, do not change before WPA3_AUTH_PSK_EXT_KEY */ WPA3_AUTH_DPP = 0x11, + WPA3_AUTH_FT_SAE = 0x12, WPA2_AUTH_INVALID }; diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index 5e5655cfdd..9e4b350285 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -28,6 +28,7 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, const u8 *mdie, size_t mdie_len, const u8 *ftie, size_t ftie_len, const u8 *rsnie, size_t rsnie_len, + const u8 *rsnxe, size_t rsnxe_len, const u8 *ric, size_t ric_len, u8 *mic) { u8 *buf, *pos; @@ -39,7 +40,7 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, return -1; } - buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len; + buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len + rsnxe_len; buf = os_malloc(buf_len); if (buf == NULL) return -1; @@ -51,38 +52,41 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, pos += ETH_ALEN; *pos++ = transaction_seqnum; if (rsnie) { - os_memcpy(pos, rsnie, rsnie_len); - pos += rsnie_len; + os_memcpy(pos, rsnie, rsnie_len); + pos += rsnie_len; } if (mdie) { - os_memcpy(pos, mdie, mdie_len); - pos += mdie_len; + os_memcpy(pos, mdie, mdie_len); + pos += mdie_len; } if (ftie) { - struct rsn_ftie *_ftie; - os_memcpy(pos, ftie, ftie_len); - if (ftie_len < 2 + sizeof(*_ftie)) { - os_free(buf); - return -1; - } - _ftie = (struct rsn_ftie *) (pos + 2); - os_memset(_ftie->mic, 0, sizeof(_ftie->mic)); - pos += ftie_len; - } - if (ric) { - os_memcpy(pos, ric, ric_len); - pos += ric_len; - } - + struct rsn_ftie *_ftie; + os_memcpy(pos, ftie, ftie_len); + if (ftie_len < 2 + sizeof(*_ftie)) { + os_free(buf); + return -1; + } + _ftie = (struct rsn_ftie *) (pos + 2); + os_memset(_ftie->mic, 0, sizeof(_ftie->mic)); + pos += ftie_len; + } + if (ric) { + os_memcpy(pos, ric, ric_len); + pos += ric_len; + } + if (rsnxe) { + os_memcpy(pos, rsnxe, rsnxe_len); + pos += rsnxe_len; + } wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf); - if (omac1_aes_128(kck, buf, pos - buf, mic)) { - os_free(buf); - return -1; - } + if (omac1_aes_128(kck, buf, pos - buf, mic)) { + os_free(buf); + return -1; + } os_free(buf); - return 0; + return 0; } @@ -151,6 +155,9 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, pos = ies; end = ies + ies_len; while (pos + 2 <= end && pos + 2 + pos[1] <= end) { + u8 len; + + len = pos[1]; switch (pos[0]) { case WLAN_EID_RSN: parse->rsn = pos + 2; @@ -166,6 +173,13 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, if (data.num_pmkid == 1 && data.pmkid) parse->rsn_pmkid = data.pmkid; break; + case WLAN_EID_RSNX: + wpa_hexdump(MSG_DEBUG, "FT: RSNXE", pos, len); + if (len < 1) + break; + parse->rsnxe = pos + 2; + parse->rsnxe_len = pos[1]; + break; case WLAN_EID_MOBILITY_DOMAIN: parse->mdie = pos + 2; parse->mdie_len = pos[1]; @@ -198,16 +212,18 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, * Check that the protected IE count matches with IEs included in the * frame. */ + if (parse->rsnxe) + prot_ie_count--; if (parse->rsn) - prot_ie_count--; + prot_ie_count--; if (parse->mdie) - prot_ie_count--; + prot_ie_count--; if (parse->ftie) - prot_ie_count--; + prot_ie_count--; if (prot_ie_count < 0) { - wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in " - "the protected IE count"); - return -1; + wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in " + "the protected IE count"); + return -1; } if (prot_ie_count == 0 && parse->ric) { @@ -225,9 +241,9 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, } parse->ric_len = pos - parse->ric; if (prot_ie_count) { - wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from " - "frame", (int) prot_ie_count); - return -1; + wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from " + "frame", (int) prot_ie_count); + return -1; } return 0; @@ -326,6 +342,8 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s) return WPA_KEY_MGMT_SAE; if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE_EXT_KEY) return WPA_KEY_MGMT_SAE_EXT_KEY; + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE) + return WPA_KEY_MGMT_FT_SAE; #endif /* CONFIG_WPA3_SAE */ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256) return WPA_KEY_MGMT_IEEE8021X_SHA256; @@ -340,12 +358,6 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s) if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192) return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; #endif -#ifdef CONFIG_WPA3_SAE - if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE) - return WPA_KEY_MGMT_SAE; - if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE_EXT_KEY) - return WPA_KEY_MGMT_SAE_EXT_KEY; -#endif /* CONFIG_WPA3_SAE */ #ifdef CONFIG_OWE_STA if(RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OWE) return WPA_KEY_MGMT_OWE; @@ -943,6 +955,7 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, switch (akmp) { #ifdef CONFIG_WPA3_SAE case WPA_KEY_MGMT_SAE: + case WPA_KEY_MGMT_FT_SAE: return omac1_aes_128(key, buf, len, mic); case WPA_KEY_MGMT_SAE_EXT_KEY: wpa_printf(MSG_DEBUG, @@ -1730,14 +1743,14 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) if (*pos == WLAN_EID_RSN) { ie->rsn_ie = pos; ie->rsn_ie_len = pos[1] + 2; -#ifdef CONFIG_IEEE80211R_AP +#ifdef CONFIG_IEEE80211R } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { ie->mdie = pos; ie->mdie_len = pos[1] + 2; } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { ie->ftie = pos; ie->ftie_len = pos[1] + 2; -#endif /* CONFIG_IEEE80211R_AP */ +#endif /* CONFIG_IEEE80211R */ } else if (*pos == WLAN_EID_RSNX) { ie->rsnxe = pos; ie->rsnxe_len = pos[1] + 2; diff --git a/components/wpa_supplicant/src/common/wpa_common.h b/components/wpa_supplicant/src/common/wpa_common.h index 5069ec7730..c035c2051b 100644 --- a/components/wpa_supplicant/src/common/wpa_common.h +++ b/components/wpa_supplicant/src/common/wpa_common.h @@ -137,6 +137,17 @@ RSN_SELECTOR(0x00, 0x0f, 0xac, 13) #define FT_R1KH_ID_LEN 6 #define WPA_PMK_NAME_LEN 16 +/* FTE - MIC Control - RSNXE Used */ +#define FTE_MIC_CTRL_RSNXE_USED BIT(0) +#define FTE_MIC_CTRL_MIC_LEN_MASK (BIT(1) | BIT(2) | BIT(3)) +#define FTE_MIC_CTRL_MIC_LEN_SHIFT 1 + +/* FTE - MIC Length subfield values */ +enum ft_mic_len_subfield { + FTE_MIC_LEN_16 = 0, + FTE_MIC_LEN_24 = 1, + FTE_MIC_LEN_32 = 2, +}; /* IEEE 802.11, 8.5.2 EAPOL-Key frames */ #define WPA_KEY_INFO_TYPE_MASK ((u16) (BIT(0) | BIT(1) | BIT(2))) @@ -337,6 +348,7 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, const u8 *mdie, size_t mdie_len, const u8 *ftie, size_t ftie_len, const u8 *rsnie, size_t rsnie_len, + const u8 *rsnxe, size_t rsnxe_len, const u8 *ric, size_t ric_len, u8 *mic); void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, const u8 *ssid, size_t ssid_len, @@ -425,6 +437,8 @@ struct wpa_ft_ies { size_t igtk_len; const u8 *ric; size_t ric_len; + const u8 *rsnxe; + size_t rsnxe_len; }; /* WPA3 specification - RSN Selection element */ diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index cbd0a2083b..78ba0f015c 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -422,6 +422,17 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm, //eapol_sm_notify_cached(sm->eapol); #ifdef CONFIG_IEEE80211R sm->xxkey_len = 0; +#ifdef CONFIG_WPA3_SAE + if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE && sm->pmk_len == PMK_LEN) { + /* Need to allow FT key derivation to proceed with + * PMK from SAE being used as the XXKey in cases where + * the PMKID in msg 1/4 matches the PMKSA entry that was + * just added based on SAE authentication for the + * initial mobility domain association. */ + os_memcpy(sm->xxkey, sm->pmk, sm->pmk_len); + sm->xxkey_len = sm->pmk_len; + } +#endif #endif /* CONFIG_IEEE80211R */ } else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) { int res = 0, pmk_len; @@ -1348,6 +1359,133 @@ static void wpa_sm_set_seq(struct wpa_sm *sm, struct wpa_eapol_key *key, u8 ispt memcpy(seq, key_rsc, WPA_KEY_RSC_LEN); } +#ifdef CONFIG_IEEE80211R + +static int ft_validate_mdie(struct wpa_sm *sm, + const unsigned char *src_addr, + struct wpa_eapol_ie_parse *ie, + const u8 *assoc_resp_mdie) +{ + struct rsn_mdie *mdie; + + mdie = (struct rsn_mdie *) (ie->mdie + 2); + if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) || + os_memcmp(mdie->mobility_domain, sm->mobility_domain, + MOBILITY_DOMAIN_ID_LEN) != 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE in msg 3/4 did " + "not match with the current mobility domain"); + return -1; + } + + if (assoc_resp_mdie && + (assoc_resp_mdie[1] != ie->mdie[1] || + os_memcmp(assoc_resp_mdie, ie->mdie, 2 + ie->mdie[1]) != 0)) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE mismatch"); + wpa_hexdump(MSG_DEBUG, "FT: MDIE in EAPOL-Key msg 3/4", + ie->mdie, 2 + ie->mdie[1]); + wpa_hexdump(MSG_DEBUG, "FT: MDIE in (Re)Association Response", + assoc_resp_mdie, 2 + assoc_resp_mdie[1]); + return -1; + } + + return 0; +} + + +static int ft_validate_ftie(struct wpa_sm *sm, + const unsigned char *src_addr, + struct wpa_eapol_ie_parse *ie, + const u8 *assoc_resp_ftie) +{ + if (ie->ftie == NULL) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "FT: No FTIE in EAPOL-Key msg 3/4"); + return -1; + } + + if (assoc_resp_ftie == NULL) + return 0; + + if (assoc_resp_ftie[1] != ie->ftie[1] || + os_memcmp(assoc_resp_ftie, ie->ftie, 2 + ie->ftie[1]) != 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: FTIE mismatch"); + wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 3/4", + ie->ftie, 2 + ie->ftie[1]); + wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)Association Response", + assoc_resp_ftie, 2 + assoc_resp_ftie[1]); + return -1; + } + + return 0; +} + + +static int ft_validate_rsnie(struct wpa_sm *sm, + const unsigned char *src_addr, + struct wpa_eapol_ie_parse *ie) +{ + struct wpa_ie_data rsn; + + if (!ie->rsn_ie) + return 0; + + /* + * Verify that PMKR1Name from EAPOL-Key message 3/4 + * matches with the value we derived. + */ + if (wpa_parse_wpa_ie_rsn(ie->rsn_ie, ie->rsn_ie_len, &rsn) < 0 || + rsn.num_pmkid != 1 || rsn.pmkid == NULL) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: No PMKR1Name in " + "FT 4-way handshake message 3/4"); + return -1; + } + + if (os_memcmp_const(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) + { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "FT: PMKR1Name mismatch in " + "FT 4-way handshake message 3/4"); + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Authenticator", + rsn.pmkid, WPA_PMK_NAME_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", + sm->pmk_r1_name, WPA_PMK_NAME_LEN); + return -1; + } + + return 0; +} + +static int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm, + const unsigned char *src_addr, + struct wpa_eapol_ie_parse *ie) +{ + const u8 *pos, *end, *mdie = NULL, *ftie = NULL; + + if (sm->assoc_resp_ies) { + pos = sm->assoc_resp_ies; + end = pos + sm->assoc_resp_ies_len; + while (end - pos > 2) { + if (2 + pos[1] > end -pos) + break; + switch (*pos) { + case WLAN_EID_MOBILITY_DOMAIN: + mdie = pos; + break; + case WLAN_EID_FAST_BSS_TRANSITION: + ftie = pos; + break; + } + pos += 2 + pos[1]; + } + } + if (ft_validate_mdie(sm, src_addr, ie, mdie) < 0 || + ft_validate_ftie(sm, src_addr, ie, ftie) < 0 || + ft_validate_rsnie(sm, src_addr, ie) < 0) { + return -1; + } + return 0; +} +#endif /* CONFIG_IEEE80211R */ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, struct wpa_eapol_key *key, u16 ver, const u8 *key_data, @@ -1364,6 +1502,11 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) { goto failed; } +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->key_mgmt) && wpa_supplicant_validate_ie_ft(sm, sm->bssid, &ie) < 0) { + goto failed; + } +#endif /* CONFIG_IEEE80211R */ if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) { goto failed; } @@ -2453,6 +2596,8 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode) sm->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY; /* for WPA3 PSK */ } else if (auth_mode == WPA3_AUTH_DPP) { sm->key_mgmt = WPA_KEY_MGMT_DPP; + } else if (auth_mode == WPA3_AUTH_FT_SAE) { + sm->key_mgmt = WPA_KEY_MGMT_FT_SAE; } else { sm->key_mgmt = WPA_KEY_MGMT_PSK; /* fixed to PSK for now */ } @@ -2497,7 +2642,7 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, uint8_t pairwise_cipher, uint8_ * is part of libraries, * TODO Correct this in future during NVS restructuring */ if ((sm->key_mgmt == WPA_KEY_MGMT_SAE || - sm->key_mgmt == WPA_KEY_MGMT_SAE_EXT_KEY) && + sm->key_mgmt == WPA_KEY_MGMT_SAE_EXT_KEY || sm->key_mgmt == WPA_KEY_MGMT_FT_SAE) && (os_memcmp(sm->bssid, bssid, ETH_ALEN) == 0) && (os_memcmp(sm->ssid, ssid, ssid_len) != 0)) { use_pmk_cache = false; @@ -2580,7 +2725,7 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, uint8_t pairwise_cipher, uint8_ } #endif #ifdef CONFIG_IEEE80211R - if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) { + if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK || sm->key_mgmt == WPA_KEY_MGMT_FT_SAE) { const u8 *ie, *md = NULL; struct wpa_bss *bss = wpa_bss_get_bssid(&g_wpa_supp, bssid); if (!bss) { @@ -2709,7 +2854,8 @@ void wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len) if (sm->key_mgmt == WPA_KEY_MGMT_SAE || sm->key_mgmt == WPA_KEY_MGMT_OWE || sm->key_mgmt == WPA_KEY_MGMT_SAE_EXT_KEY || - sm->key_mgmt == WPA_KEY_MGMT_DPP) + sm->key_mgmt == WPA_KEY_MGMT_DPP || + sm->key_mgmt == WPA_KEY_MGMT_FT_SAE) return; /* This is really SLOW, so just re cacl while reset param */ diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ft.c b/components/wpa_supplicant/src/rsn_supp/wpa_ft.c index 0c4bad9d9c..97db4302c9 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ft.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa_ft.c @@ -15,6 +15,7 @@ #include "common/ieee802_11_common.h" #include "wpa.h" #include "wpa_i.h" +#include "wpa_ie.h" #ifdef CONFIG_IEEE80211R @@ -164,11 +165,16 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, struct rsn_ie_hdr *rsnie; int mdie_len; u16 capab; + int rsnxe_used; + size_t rsnxe_len; + u8 mic_control; + int res; + u8 rsnxe[20]; sm->ft_completed = 0; buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) + - 2 + sm->r0kh_id_len + ric_ies_len + 100; + 2 + sm->r0kh_id_len + ric_ies_len + 100 + sizeof(rsnxe); buf = os_zalloc(buf_len); if (buf == NULL) return NULL; @@ -245,10 +251,20 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, pos += WPA_PMK_NAME_LEN; #ifdef CONFIG_IEEE80211W - if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { - /* Management Group Cipher Suite */ - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); - pos += RSN_SELECTOR_LEN; + /* Management Group Cipher Suite */ + switch (sm->mgmt_group_cipher) { + case WPA_CIPHER_AES_128_CMAC: + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); + pos += RSN_SELECTOR_LEN; + break; + case WPA_CIPHER_BIP_GMAC_128: + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_128); + pos += RSN_SELECTOR_LEN; + break; + case WPA_CIPHER_BIP_GMAC_256: + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_256); + pos += RSN_SELECTOR_LEN; + break; } #endif /* CONFIG_IEEE80211W */ @@ -269,6 +285,10 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, ftie_len = pos++; ftie = (struct rsn_ftie *) pos; pos += sizeof(*ftie); + rsnxe_used = wpa_key_mgmt_sae(sm->key_mgmt) && anonce && + (sm->sae_pwe == SAE_PWE_BOTH || + sm->sae_pwe == SAE_PWE_HASH_TO_ELEMENT); + mic_control = rsnxe_used ? FTE_MIC_CTRL_RSNXE_USED : 0; os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN); if (anonce) os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN); @@ -292,6 +312,15 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, pos += ric_ies_len; } + res = wpa_gen_rsnxe(sm, rsnxe, sizeof(rsnxe)); + if (res < 0) { + os_free(buf); + return NULL; + } + rsnxe_len = res; + os_memcpy(pos, rsnxe, rsnxe_len); + pos += rsnxe_len; + if (kck) { /* * IEEE Std 802.11r-2008, 11A.8.4 @@ -303,14 +332,20 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, * MDIE * FTIE (with MIC field set to 0) * RIC-Request (if present) + * RSNXE (if present) */ /* Information element count */ + mic_control |= FTE_MIC_LEN_16 << FTE_MIC_CTRL_MIC_LEN_SHIFT; + ftie->mic_control[0] = mic_control; ftie->mic_control[1] = 3 + ieee802_11_ie_count(ric_ies, ric_ies_len); + if (rsnxe_len) + ftie->mic_control[1] += 1; if (wpa_ft_mic(kck, kck_len, sm->own_addr, target_ap, 5, ((u8 *) mdie) - 2, 2 + sizeof(*mdie), ftie_pos, 2 + *ftie_len, - (u8 *) rsnie, 2 + rsnie->len, ric_ies, + (u8 *) rsnie, 2 + rsnie->len, + rsnxe_len ? rsnxe : NULL, rsnxe_len, ric_ies, ric_ies_len, ftie->mic) < 0) { wpa_printf(MSG_INFO, "FT: Failed to calculate MIC"); os_free(buf); @@ -660,6 +695,7 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem, size_t igtk_elem_len) { u8 igtk[WPA_IGTK_LEN]; + wifi_wpa_igtk_t *_igtk = (wifi_wpa_igtk_t*)igtk_elem; if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) return 0; @@ -692,12 +728,12 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem, /* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */ - wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk, + wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp ", igtk, WPA_IGTK_LEN); #ifdef ESP_SUPPLICANT - if (esp_wifi_set_igtk_internal(WIFI_IF_STA, (wifi_wpa_igtk_t *)igtk) < 0) { + if (esp_wifi_set_igtk_internal(WIFI_IF_STA, (wifi_wpa_igtk_t *)_igtk) < 0) { #else - keyidx = WPA_GET_LE16(igtk_elem); + keyidx = WPA_GET_LE16(igtk_elem); if (wpa_sm_set_key(&(sm->install_gtk), WIFI_WPA_ALG_IGTK, sm->bssid, keyidx, 0, (u8 *)(igtk_elem + 2), 6, igtk, WPA_IGTK_LEN, sm->key_entry_valid) < 0) { #endif @@ -809,6 +845,8 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, count = 3; if (parse.ric) count += ieee802_11_ie_count(parse.ric, parse.ric_len); + if (parse.rsnxe) + count++; if (ftie->mic_control[1] != count) { wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC " "Control: received %u expected %u", @@ -820,6 +858,8 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, parse.mdie - 2, parse.mdie_len + 2, parse.ftie - 2, parse.ftie_len + 2, parse.rsn - 2, parse.rsn_len + 2, + parse.rsnxe ? parse.rsnxe - 2 : NULL, + parse.rsnxe ? parse.rsnxe_len + 2 : 0, parse.ric, parse.ric_len, mic) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c index 8bafca9653..4e0d75ee05 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c @@ -203,6 +203,8 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE); } else if (key_mgmt == WPA_KEY_MGMT_SAE_EXT_KEY) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE_EXT_KEY); + } else if (key_mgmt == WPA_KEY_MGMT_FT_SAE) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE); #endif /* CONFIG_WPA3_SAE */ #ifdef CONFIG_OWE_STA } else if (key_mgmt == WPA_KEY_MGMT_OWE) {