RSNO: Use SNonce cookie to indicate support for RSN overriding

This provides an implicitly protected (SNonce is used as an input to PTK
derivation) mechanism for a STA to indicate support for RSN overriding
in a manner that does not cause interopability issues with deployed APs.

In addition, update sm->SNonce on the Authenticator only based on
message 2/4 since that is the only EAPOL-Key message that is defined to
provide the actual SNonce value. While clearing of this internal buffer
on message 4/4 might not cause issues, it is better to keep the actual
SNonce value here since the SNonce cookie can be used at a later point
in the sequence.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen
2024-07-29 16:43:50 +03:00
committed by Kapil Gupta
parent 7ec6fbd49a
commit 8b8d5ebfc9
4 changed files with 32 additions and 3 deletions

View File

@@ -980,7 +980,8 @@ continue_processing:
sm->EAPOLKeyReceived = TRUE;
sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);
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);
}
@@ -1764,7 +1765,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
}
/* 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 ||
@@ -1772,6 +1775,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",

View File

@@ -1722,4 +1722,23 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
return ret;
}
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;
}
#endif // ESP_SUPPLICANT

View File

@@ -499,4 +499,7 @@ unsigned int wpa_mic_len(int akmp, size_t pmk_len);
int wpa_use_akm_defined(int akmp);
int wpa_use_aes_key_wrap(int akmp);
void rsn_set_snonce_cookie(u8 *snonce);
bool rsn_is_snonce_cookie(const u8 *snonce);
#endif /* WPA_COMMON_H */

View File

@@ -733,7 +733,8 @@ void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
wpa_printf(MSG_DEBUG, "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);