diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index cf6b07c1f..29d17f684 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -1887,7 +1887,8 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, sm->EAPOLKeyReceived = true; sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST); - os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); + if (msg == PAIRWISE_2) + os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); wpa_sm_step(sm); out: @@ -3922,7 +3923,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) #endif /* CONFIG_IEEE80211R_AP */ /* Verify RSN Selection element for RSN overriding */ - if ((sm->rsn_selection && !kde.rsn_selection) || + if ((rsn_is_snonce_cookie(sm->SNonce) && !kde.rsn_selection) || + (!rsn_is_snonce_cookie(sm->SNonce) && kde.rsn_selection) || + (sm->rsn_selection && !kde.rsn_selection) || (!sm->rsn_selection && kde.rsn_selection) || (sm->rsn_selection && kde.rsn_selection && (sm->rsn_selection_len != kde.rsn_selection_len || @@ -3930,6 +3933,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) sm->rsn_selection_len) != 0))) { wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO, "RSN Selection element from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4"); + wpa_printf(MSG_DEBUG, + "SNonce cookie for RSN overriding %sused", + rsn_is_snonce_cookie(sm->SNonce) ? "" : "not "); wpa_hexdump(MSG_DEBUG, "RSN Selection in AssocReq", sm->rsn_selection, sm->rsn_selection_len); wpa_hexdump(MSG_DEBUG, "RSN Selection in EAPOL-Key msg 2/4", diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index bfaca9128..4f58f0737 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -4274,3 +4274,24 @@ int wpa_pasn_add_extra_ies(struct wpabuf *buf, const u8 *extra_ies, size_t len) } #endif /* CONFIG_PASN */ + + +void rsn_set_snonce_cookie(u8 *snonce) +{ + u8 *pos; + + pos = snonce + WPA_NONCE_LEN - 6; + WPA_PUT_BE24(pos, OUI_WFA); + pos += 3; + WPA_PUT_BE24(pos, 0x000029); +} + + +bool rsn_is_snonce_cookie(const u8 *snonce) +{ + const u8 *pos; + + pos = snonce + WPA_NONCE_LEN - 6; + return WPA_GET_BE24(pos) == OUI_WFA && + WPA_GET_BE24(pos + 3) == 0x000029; +} diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index c8cdf748d..4cb5b8c60 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -797,4 +797,7 @@ int wpa_pasn_parse_parameter_ie(const u8 *data, u8 len, bool from_ap, void wpa_pasn_add_rsnxe(struct wpabuf *buf, u16 capab); int wpa_pasn_add_extra_ies(struct wpabuf *buf, const u8 *extra_ies, size_t len); +void rsn_set_snonce_cookie(u8 *snonce); +bool rsn_is_snonce_cookie(const u8 *snonce); + #endif /* WPA_COMMON_H */ diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 9b13b3a84..0a1d4d07f 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1023,6 +1023,8 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, "WPA: Failed to get random data for SNonce"); goto failed; } + if (sm->rsn_override != RSN_OVERRIDE_NOT_USED) + rsn_set_snonce_cookie(sm->snonce); sm->renew_snonce = 0; wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce", sm->snonce, WPA_NONCE_LEN);