]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SAE: Make sme_sae_auth() return IE offset
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>
Tue, 6 Dec 2022 09:46:05 +0000 (11:46 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 17 Dec 2022 15:11:16 +0000 (17:11 +0200)
Authentication frames include several fixed body parts (see Table 9-68
(Authentication frame body) and Table 9-69 (Presence of fields and
elements in Authentication frames) in IEEE P802.11-REVme/D2.0).

To be able to parse the IE part, these fields need to be skipped. Since
SAE logic already implements this parsing, change SAE authentication
handling functions to return the offset to the IE part. This preparation
is needed for future MLD patches that need to parse out the ML related
elements in the Authentication frames.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
src/ap/ieee802_11.c
src/common/common_module_tests.c
src/common/sae.c
src/common/sae.h
src/pasn/pasn_initiator.c
src/pasn/pasn_responder.c
tests/fuzzing/sae/sae.c
wpa_supplicant/sme.c

index 490dbcbe987292e5b530cf0736e24716652dedc6..e53f0dcbe598da4fda743395cd2b37f5f8ffb6e0 100644 (file)
@@ -1373,7 +1373,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                                        mgmt->u.auth.variable, &token,
                                        &token_len, groups, status_code ==
                                        WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
-                                       status_code == WLAN_STATUS_SAE_PK);
+                                       status_code == WLAN_STATUS_SAE_PK,
+                                       NULL);
                if (resp == SAE_SILENTLY_DISCARD) {
                        wpa_printf(MSG_DEBUG,
                                   "SAE: Drop commit message from " MACSTR " due to reflection attack",
@@ -1473,7 +1474,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                                return;
                        }
 
-                       if (sae_check_confirm(sta->sae, var, var_len) < 0) {
+                       if (sae_check_confirm(sta->sae, var, var_len,
+                                             NULL) < 0) {
                                resp = WLAN_STATUS_CHALLENGE_FAIL;
                                goto reply;
                        }
index 8aba713f92bac6262ea4df2fdb12f7597cd02579..a95ae36dc078194039923380da27487e7eae98f7 100644 (file)
@@ -428,7 +428,7 @@ static int sae_tests(void)
        }
 
        if (sae_parse_commit(&sae, peer_commit, sizeof(peer_commit), NULL, NULL,
-                            NULL, 0) != 0 ||
+                            NULL, 0, NULL) != 0 ||
            sae_process_commit(&sae) < 0)
                goto fail;
 
index 8e78c96f372b3c3fdb332a5eb7a4e7ae27237a51..d4a196f153fd27a20db406e2bfdd5eda9ba74243 100644 (file)
@@ -2157,7 +2157,7 @@ static int sae_parse_akm_suite_selector(struct sae_data *sae,
 
 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
                     const u8 **token, size_t *token_len, int *allowed_groups,
-                    int h2e)
+                    int h2e, int *ie_offset)
 {
        const u8 *pos = data, *end = data + len;
        u16 res;
@@ -2183,6 +2183,9 @@ u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
        if (res != WLAN_STATUS_SUCCESS)
                return res;
 
+       if (ie_offset)
+               *ie_offset = pos - data;
+
        /* Optional Password Identifier element */
        res = sae_parse_password_identifier(sae, &pos, end);
        if (res != WLAN_STATUS_SUCCESS)
@@ -2376,7 +2379,8 @@ int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
 }
 
 
-int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
+int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len,
+                     int *ie_offset)
 {
        u8 verifier[SAE_MAX_HASH_LEN];
        size_t hash_len;
@@ -2432,6 +2436,10 @@ int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
                return -1;
 #endif /* CONFIG_SAE_PK */
 
+       /* 2 bytes are for send-confirm, then the hash, followed by IEs */
+       if (ie_offset)
+               *ie_offset = 2 + hash_len;
+
        return 0;
 }
 
index 6a6b0c8241f063895eb1a4c1ac1c5fb815f57bd4..c446da3964a7b1dd2618a3f1501992ac03353e61 100644 (file)
@@ -136,9 +136,10 @@ int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
                     const struct wpabuf *token, const char *identifier);
 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
                     const u8 **token, size_t *token_len, int *allowed_groups,
-                    int h2e);
+                    int h2e, int *ie_offset);
 int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf);
-int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len);
+int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len,
+                     int *ie_offset);
 u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group);
 const char * sae_state_txt(enum sae_state state);
 size_t sae_ecc_prime_len_2_hash_len(size_t prime_len);
index a98eba20cfad0b9f7be9ba9f697a3e4221331ba2..1f9a5083005377d7dd3ab9c1770bfc07ffeec78d 100644 (file)
@@ -108,7 +108,7 @@ static int wpas_pasn_wd_sae_rx(struct pasn_data *pasn, struct wpabuf *wd)
        }
 
        res = sae_parse_commit(&pasn->sae, data + 6, len - 6, NULL, 0, groups,
-                              1);
+                              1, NULL);
        if (res != WLAN_STATUS_SUCCESS) {
                wpa_printf(MSG_DEBUG, "PASN: SAE failed parsing commit");
                return -1;
@@ -151,7 +151,7 @@ static int wpas_pasn_wd_sae_rx(struct pasn_data *pasn, struct wpabuf *wd)
                return -1;
        }
 
-       res = sae_check_confirm(&pasn->sae, data + 6, len - 6);
+       res = sae_check_confirm(&pasn->sae, data + 6, len - 6, NULL);
        if (res != WLAN_STATUS_SUCCESS) {
                wpa_printf(MSG_DEBUG, "PASN: SAE failed checking confirm");
                return -1;
index e36aa39b809673a69af252ebce403b49bb091016..3b1912df3e38d3e1af5941e5dfc2ff29e5539dbf 100644 (file)
@@ -85,7 +85,7 @@ static int pasn_wd_handle_sae_commit(struct pasn_data *pasn,
        }
 
        res = sae_parse_commit(&pasn->sae, data + 6, buf_len - 6, NULL, 0,
-                              groups, 0);
+                              groups, 0, NULL);
        if (res != WLAN_STATUS_SUCCESS) {
                wpa_printf(MSG_DEBUG, "PASN: Failed parsing SAE commit");
                return -1;
@@ -135,7 +135,7 @@ static int pasn_wd_handle_sae_confirm(struct pasn_data *pasn,
                return -1;
        }
 
-       res = sae_check_confirm(&pasn->sae, data + 6, buf_len - 6);
+       res = sae_check_confirm(&pasn->sae, data + 6, buf_len - 6, NULL);
        if (res != WLAN_STATUS_SUCCESS) {
                wpa_printf(MSG_DEBUG, "PASN: SAE failed checking confirm");
                return -1;
index 8819a4abbc8f67276c27101d473bc28a9c25ee0c..738a8f615d0850dd5ef5892a29928908259d96df 100644 (file)
@@ -27,10 +27,12 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
                return 0;
 
        os_memset(&sae, 0, sizeof(sae));
-       res = sae_parse_commit(&sae, data, size, &token, &token_len, groups, 0);
+       res = sae_parse_commit(&sae, data, size, &token, &token_len, groups, 0,
+                              NULL);
        wpa_printf(MSG_DEBUG, "sae_parse_commit(0): %u", res);
        sae_clear_data(&sae);
-       res = sae_parse_commit(&sae, data, size, &token, &token_len, groups, 1);
+       res = sae_parse_commit(&sae, data, size, &token, &token_len, groups, 1,
+                              NULL);
        wpa_printf(MSG_DEBUG, "sae_parse_commit(1): %u", res);
        sae_clear_data(&sae);
        os_program_deinit();
index 7095edbe5d9f382a37f5849656fd3e6e24955f77..dce8a5563273ffa062a9d2f574f22f85f8e543d2 100644 (file)
@@ -1344,7 +1344,7 @@ static int sme_check_sae_rejected_groups(struct wpa_supplicant *wpa_s,
 
 static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
                        u16 status_code, const u8 *data, size_t len,
-                       int external, const u8 *sa)
+                       int external, const u8 *sa, int *ie_offset)
 {
        int *groups;
 
@@ -1408,6 +1408,10 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
                        }
                        token_len = elen - 1;
                }
+
+               if (ie_offset)
+                       *ie_offset = token_pos + token_len - data;
+
                wpa_s->sme.sae_token = wpabuf_alloc_copy(token_pos, token_len);
                if (!wpa_s->sme.sae_token) {
                        wpa_dbg(wpa_s, MSG_ERROR,
@@ -1509,7 +1513,8 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
                res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
                                       groups, status_code ==
                                       WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
-                                      status_code == WLAN_STATUS_SAE_PK);
+                                      status_code == WLAN_STATUS_SAE_PK,
+                                      ie_offset);
                if (res == SAE_SILENTLY_DISCARD) {
                        wpa_printf(MSG_DEBUG,
                                   "SAE: Drop commit message due to reflection attack");
@@ -1544,7 +1549,8 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
                wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
                if (wpa_s->sme.sae.state != SAE_CONFIRMED)
                        return -1;
-               if (sae_check_confirm(&wpa_s->sme.sae, data, len) < 0)
+               if (sae_check_confirm(&wpa_s->sme.sae, data, len,
+                                     ie_offset) < 0)
                        return -1;
                wpa_s->sme.sae.state = SAE_ACCEPTED;
                sae_clear_temp_data(&wpa_s->sme.sae);
@@ -1616,7 +1622,7 @@ void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
                        wpa_s, le_to_host16(header->u.auth.auth_transaction),
                        le_to_host16(header->u.auth.status_code),
                        header->u.auth.variable,
-                       len - auth_length, 1, header->sa);
+                       len - auth_length, 1, header->sa, NULL);
                if (res < 0) {
                        /* Notify failure to the driver */
                        sme_send_external_auth_status(
@@ -1674,7 +1680,8 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
                int res;
                res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
                                   data->auth.status_code, data->auth.ies,
-                                  data->auth.ies_len, 0, data->auth.peer);
+                                  data->auth.ies_len, 0, data->auth.peer,
+                                  NULL);
                if (res < 0) {
                        wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
                        wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);