diff options
Diffstat (limited to 'src/rsn_supp')
-rw-r--r-- | src/rsn_supp/pmksa_cache.c | 3 | ||||
-rw-r--r-- | src/rsn_supp/tdls.c | 2 | ||||
-rw-r--r-- | src/rsn_supp/wpa.c | 127 | ||||
-rw-r--r-- | src/rsn_supp/wpa.h | 1 | ||||
-rw-r--r-- | src/rsn_supp/wpa_i.h | 9 |
5 files changed, 127 insertions, 15 deletions
diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c index fdd5220..d720f7b 100644 --- a/src/rsn_supp/pmksa_cache.c +++ b/src/rsn_supp/pmksa_cache.c @@ -263,7 +263,8 @@ pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa, } pmksa->pmksa_count++; wpa_printf(MSG_DEBUG, "RSN: Added PMKSA cache entry for " MACSTR - " network_ctx=%p", MAC2STR(entry->aa), entry->network_ctx); + " network_ctx=%p akmp=0x%x", MAC2STR(entry->aa), + entry->network_ctx, entry->akmp); wpa_sm_add_pmkid(pmksa->sm, entry->network_ctx, entry->aa, entry->pmkid, entry->fils_cache_id_set ? entry->fils_cache_id : NULL, entry->pmk, entry->pmk_len); diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index 345b0c8..704c95e 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -1594,7 +1594,7 @@ static int copy_supp_rates(const struct wpa_eapol_ie_parse *kde, peer->supp_rates, sizeof(peer->supp_rates), kde->supp_rates + 2, kde->supp_rates_len - 2, kde->ext_supp_rates ? kde->ext_supp_rates + 2 : NULL, - kde->ext_supp_rates_len - 2); + kde->ext_supp_rates ? kde->ext_supp_rates_len - 2 : 0); return 0; } diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 18f8c71..9163f61 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -384,6 +384,11 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm, if (!sm->cur_pmksa) sm->cur_pmksa = sa; +#ifdef CONFIG_IEEE80211R + } else if (wpa_key_mgmt_ft(sm->key_mgmt) && sm->ft_protocol) { + wpa_printf(MSG_DEBUG, + "FT: Continue 4-way handshake without PMK/PMKID for association using FT protocol"); +#endif /* CONFIG_IEEE80211R */ } else { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Failed to get master session key from " @@ -534,15 +539,25 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, struct wpa_ptk *ptk) { + const u8 *z = NULL; + size_t z_len = 0; + #ifdef CONFIG_IEEE80211R if (wpa_key_mgmt_ft(sm->key_mgmt)) return wpa_derive_ptk_ft(sm, src_addr, key, ptk); #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_DPP2 + if (sm->key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) { + z = wpabuf_head(sm->dpp_z); + z_len = wpabuf_len(sm->dpp_z); + } +#endif /* CONFIG_DPP2 */ + return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", sm->own_addr, sm->bssid, sm->snonce, key->key_nonce, ptk, sm->key_mgmt, - sm->pairwise_cipher); + sm->pairwise_cipher, z, z_len); } @@ -715,7 +730,9 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, * likelihood of the first preauth EAPOL-Start frame getting to * the target AP. */ - eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL); + if (!dl_list_empty(&sm->pmksa_candidates)) + eloop_register_timeout(1, 0, wpa_sm_start_preauth, + sm, NULL); } if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) { @@ -1009,8 +1026,6 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, } os_memset(&gd, 0, sizeof(gd)); - wpa_supplicant_key_neg_complete(sm, sm->bssid, - key_info & WPA_KEY_INFO_SECURE); return 0; } @@ -1048,9 +1063,27 @@ static int wpa_supplicant_install_igtk(struct wpa_sm *sm, broadcast_ether_addr, keyidx, 0, igtk->pn, sizeof(igtk->pn), igtk->igtk, len) < 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to configure IGTK to the driver"); - return -1; + if (keyidx == 0x0400 || keyidx == 0x0500) { + /* Assume the AP has broken PMF implementation since it + * seems to have swapped the KeyID bytes. The AP cannot + * be trusted to implement BIP correctly or provide a + * valid IGTK, so do not try to configure this key with + * swapped KeyID bytes. Instead, continue without + * configuring the IGTK so that the driver can drop any + * received group-addressed robust management frames due + * to missing keys. + * + * Normally, this error behavior would result in us + * disconnecting, but there are number of deployed APs + * with this broken behavior, so as an interoperability + * workaround, allow the connection to proceed. */ + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Ignore IGTK configuration error due to invalid IGTK KeyID byte order"); + } else { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Failed to configure IGTK to the driver"); + return -1; + } } if (wnm_sleep) { @@ -1491,8 +1524,11 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED) { - wpa_supplicant_key_neg_complete(sm, sm->bssid, - key_info & WPA_KEY_INFO_SECURE); + /* No GTK to be set to the driver */ + } else if (!ie.gtk && sm->proto == WPA_PROTO_RSN) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: No GTK KDE included in EAPOL-Key msg 3/4"); + goto failed; } else if (ie.gtk && wpa_supplicant_pairwise_gtk(sm, key, ie.gtk, ie.gtk_len, key_info) < 0) { @@ -1507,6 +1543,10 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, goto failed; } + if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED || ie.gtk) + wpa_supplicant_key_neg_complete(sm, sm->bssid, + key_info & WPA_KEY_INFO_SECURE); + if (ie.gtk) wpa_sm_set_rekey_offload(sm); @@ -1850,7 +1890,15 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Invalid EAPOL-Key MIC " "when using TPTK - ignoring TPTK"); +#ifdef TEST_FUZZ + wpa_printf(MSG_INFO, + "TEST: Ignore Key MIC failure for fuzz testing"); + goto continue_fuzz; +#endif /* TEST_FUZZ */ } else { +#ifdef TEST_FUZZ + continue_fuzz: +#endif /* TEST_FUZZ */ ok = 1; sm->tptk_set = 0; sm->ptk_set = 1; @@ -1876,8 +1924,16 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Invalid EAPOL-Key MIC - " "dropping packet"); +#ifdef TEST_FUZZ + wpa_printf(MSG_INFO, + "TEST: Ignore Key MIC failure for fuzz testing"); + goto continue_fuzz2; +#endif /* TEST_FUZZ */ return -1; } +#ifdef TEST_FUZZ + continue_fuzz2: +#endif /* TEST_FUZZ */ ok = 1; } @@ -1952,14 +2008,25 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, "WPA: No memory for AES-UNWRAP buffer"); return -1; } +#ifdef TEST_FUZZ + os_memset(buf, 0x11, *key_data_len); +#endif /* TEST_FUZZ */ if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, *key_data_len / 8, key_data, buf)) { +#ifdef TEST_FUZZ + wpa_printf(MSG_INFO, + "TEST: Ignore AES unwrap failure for fuzz testing"); + goto continue_fuzz; +#endif /* TEST_FUZZ */ bin_clear_free(buf, *key_data_len); wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: AES unwrap failed - " "could not decrypt EAPOL-Key key data"); return -1; } +#ifdef TEST_FUZZ + continue_fuzz: +#endif /* TEST_FUZZ */ os_memcpy(key_data, buf, *key_data_len); bin_clear_free(buf, *key_data_len); WPA_PUT_BE16(((u8 *) (key + 1)) + mic_len, *key_data_len); @@ -2608,6 +2675,9 @@ void wpa_sm_deinit(struct wpa_sm *sm) #ifdef CONFIG_OWE crypto_ecdh_deinit(sm->owe_ecdh); #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP2 + wpabuf_clear_free(sm->dpp_z); +#endif /* CONFIG_DPP2 */ os_free(sm); } @@ -2649,6 +2719,9 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) wpa_ft_prepare_auth_request(sm, NULL); clear_keys = 0; + sm->ft_protocol = 1; + } else { + sm->ft_protocol = 0; } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_FILS @@ -2713,6 +2786,7 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm) #endif /* CONFIG_FILS */ #ifdef CONFIG_IEEE80211R sm->ft_reassoc_completed = 0; + sm->ft_protocol = 0; #endif /* CONFIG_IEEE80211R */ /* Keys are not needed in the WPA state machine anymore */ @@ -3959,11 +4033,13 @@ static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf) MAC2STR(sm->r1kh_id)); pos = wpabuf_put(buf, WPA_PMK_NAME_LEN); if (wpa_derive_pmk_r1_name(sm->pmk_r0_name, sm->r1kh_id, sm->own_addr, - pos, use_sha384) < 0) { + sm->pmk_r1_name, use_sha384) < 0) { wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMKR1Name"); return -1; } - wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", pos, WPA_PMK_NAME_LEN); + wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name, + WPA_PMK_NAME_LEN); + os_memcpy(pos, sm->pmk_r1_name, WPA_PMK_NAME_LEN); #ifdef CONFIG_IEEE80211W if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { @@ -4266,6 +4342,24 @@ int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len) } #endif /* CONFIG_OCV */ +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->key_mgmt) && sm->fils_ft_ies) { + struct wpa_ie_data rsn; + + /* Check that PMKR1Name derived by the AP matches */ + if (!elems.rsn_ie || + wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2, + &rsn) < 0 || + !rsn.pmkid || rsn.num_pmkid != 1 || + os_memcmp(rsn.pmkid, sm->pmk_r1_name, + WPA_PMK_NAME_LEN) != 0) { + wpa_printf(MSG_DEBUG, + "FILS+FT: No RSNE[PMKR1Name] match in AssocResp"); + goto fail; + } + } +#endif /* CONFIG_IEEE80211R */ + /* Key Delivery */ if (!elems.key_delivery) { wpa_printf(MSG_DEBUG, "FILS: No Key Delivery element"); @@ -4587,3 +4681,14 @@ void wpa_sm_set_fils_cache_id(struct wpa_sm *sm, const u8 *fils_cache_id) } #endif /* CONFIG_FILS */ } + + +#ifdef CONFIG_DPP2 +void wpa_sm_set_dpp_z(struct wpa_sm *sm, const struct wpabuf *z) +{ + if (sm) { + wpabuf_clear_free(sm->dpp_z); + sm->dpp_z = z ? wpabuf_dup(z) : NULL; + } +} +#endif /* CONFIG_DPP2 */ diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 9eee383..8903f8e 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -465,5 +465,6 @@ int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *bssid, void wpa_sm_set_reset_fils_completed(struct wpa_sm *sm, int set); void wpa_sm_set_fils_cache_id(struct wpa_sm *sm, const u8 *fils_cache_id); +void wpa_sm_set_dpp_z(struct wpa_sm *sm, const struct wpabuf *z); #endif /* WPA_H */ diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index e1a213b..0c5955c 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -126,8 +126,9 @@ struct wpa_sm { u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; size_t r0kh_id_len; u8 r1kh_id[FT_R1KH_ID_LEN]; - int ft_completed; - int ft_reassoc_completed; + unsigned int ft_completed:1; + unsigned int ft_reassoc_completed:1; + unsigned int ft_protocol:1; int over_the_ds_in_progress; u8 target_ap[ETH_ALEN]; /* over-the-DS target AP */ int set_ptk_after_assoc; @@ -168,6 +169,10 @@ struct wpa_sm { struct crypto_ecdh *owe_ecdh; u16 owe_group; #endif /* CONFIG_OWE */ + +#ifdef CONFIG_DPP2 + struct wpabuf *dpp_z; +#endif /* CONFIG_DPP2 */ }; |