]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
RSNO: Use SNonce cookie to indicate support for RSN overriding
authorJouni Malinen <quic_jouni@quicinc.com>
Mon, 29 Jul 2024 13:43:50 +0000 (16:43 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 30 Jul 2024 09:16:05 +0000 (12:16 +0300)
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>
src/ap/wpa_auth.c
src/common/wpa_common.c
src/common/wpa_common.h
src/rsn_supp/wpa.c

index cf6b07c1fa2b4051f52bb873efa026c1aeb05814..29d17f6845936b126ab0aebb907e75d9d3825c01 100644 (file)
@@ -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",
index bfaca912882a379e38e777ebb84e3a17960585a4..4f58f0737705c3088fbd78e9fca293c3ef50a5c2 100644 (file)
@@ -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;
+}
index c8cdf748d71b9b1afeeb6952f807df7740300e87..4cb5b8c602c50abf85ac4cca7a5d679332bae978 100644 (file)
@@ -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 */
index 9b13b3a8403db1ae6eba0be3e812dccc4bff9545..0a1d4d07f35073c9d72af01bcabfbb22cfaf3e27 100644 (file)
@@ -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);