summaryrefslogtreecommitdiff
path: root/src/rsn_supp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rsn_supp')
-rw-r--r--src/rsn_supp/pmksa_cache.c3
-rw-r--r--src/rsn_supp/tdls.c2
-rw-r--r--src/rsn_supp/wpa.c127
-rw-r--r--src/rsn_supp/wpa.h1
-rw-r--r--src/rsn_supp/wpa_i.h9
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 */
};