]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SAE: Indicate AKM suite selector in commit for new AKM suites
authorJouni Malinen <quic_jouni@quicinc.com>
Sun, 24 Jul 2022 19:24:56 +0000 (22:24 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 24 Jul 2022 21:31:51 +0000 (00:31 +0300)
SAE authentication needs to known which AKM suite is being used to be
able to determine the correct PMK length for the new AKM suite selectors
that use variable length keys.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
src/common/ieee802_11_defs.h
src/common/sae.c
src/common/sae.h

index 1bd57afe5dd1da0819e43b79f6a62f2162d572ae..65e125e8352fe7ba0a2a57aaed761b7ee8a5b150 100644 (file)
 #define WLAN_EID_EXT_EHT_CAPABILITIES 108
 #define WLAN_EID_EXT_TID_TO_LINK_MAPPING 109
 #define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
+#define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
 
 /* Extended Capabilities field */
 #define WLAN_EXT_CAPAB_20_40_COEX 0
index 48e4fb4af0693ba27cacb95593f1fc8c5dea7e52..637ca29b5611aa9ead0a76608aaa64b338cf63b1 100644 (file)
@@ -1727,6 +1727,17 @@ int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
                                token);
        }
 
+       if (wpa_key_mgmt_sae_ext_key(sae->akmp)) {
+               u32 suite = wpa_akm_to_suite(sae->akmp);
+
+               wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
+               wpabuf_put_u8(buf, 1 + RSN_SELECTOR_LEN);
+               wpabuf_put_u8(buf, WLAN_EID_EXT_AKM_SUITE_SELECTOR);
+               RSN_SELECTOR_PUT(wpabuf_put(buf, RSN_SELECTOR_LEN), suite);
+               wpa_printf(MSG_DEBUG, "SAE: AKM Suite Selector: %08x", suite);
+               sae->own_akm_suite_selector = suite;
+       }
+
        return 0;
 }
 
@@ -1803,6 +1814,16 @@ static int sae_is_token_container_elem(const u8 *pos, const u8 *end)
 }
 
 
+static int sae_is_akm_suite_selector_elem(const u8 *pos, const u8 *end)
+{
+       return end - pos >= 2 + 1 + RSN_SELECTOR_LEN &&
+               pos[0] == WLAN_EID_EXTENSION &&
+               pos[1] >= 1 + RSN_SELECTOR_LEN &&
+               end - pos - 2 >= pos[1] &&
+               pos[2] == WLAN_EID_EXT_AKM_SUITE_SELECTOR;
+}
+
+
 static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
                                   const u8 *end, const u8 **token,
                                   size_t *token_len, int h2e)
@@ -2090,6 +2111,35 @@ static int sae_parse_rejected_groups(struct sae_data *sae,
 }
 
 
+static int sae_parse_akm_suite_selector(struct sae_data *sae,
+                                       const u8 **pos, const u8 *end)
+{
+       const u8 *epos;
+       u8 len;
+
+       wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
+                   *pos, end - *pos);
+       if (!sae_is_akm_suite_selector_elem(*pos, end))
+               return WLAN_STATUS_SUCCESS;
+
+       epos = *pos;
+       epos++; /* skip IE type */
+       len = *epos++; /* IE length */
+       if (len > end - epos || len < 1)
+               return WLAN_STATUS_UNSPECIFIED_FAILURE;
+       epos++; /* skip ext ID */
+       len--;
+
+       if (len < RSN_SELECTOR_LEN)
+               return WLAN_STATUS_UNSPECIFIED_FAILURE;
+       sae->peer_akm_suite_selector = RSN_SELECTOR_GET(epos);
+       wpa_printf(MSG_DEBUG, "SAE: Received AKM Suite Selector: %08x",
+                  sae->peer_akm_suite_selector);
+       *pos = epos + len;
+       return WLAN_STATUS_SUCCESS;
+}
+
+
 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)
@@ -2134,6 +2184,31 @@ u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
        if (h2e)
                sae_parse_token_container(sae, pos, end, token, token_len);
 
+       /* Conditional AKM Suite Selector element */
+       if (h2e) {
+               res = sae_parse_akm_suite_selector(sae, &pos, end);
+               if (res != WLAN_STATUS_SUCCESS)
+                       return res;
+       }
+
+       if (sae->own_akm_suite_selector &&
+           sae->own_akm_suite_selector != sae->peer_akm_suite_selector) {
+               wpa_printf(MSG_DEBUG,
+                          "SAE: AKM suite selector mismatch: own=%08x peer=%08x",
+                          sae->own_akm_suite_selector,
+                          sae->peer_akm_suite_selector);
+               return WLAN_STATUS_UNSPECIFIED_FAILURE;
+       }
+
+       if (!sae->akmp) {
+               if (sae->peer_akm_suite_selector ==
+                   RSN_AUTH_KEY_MGMT_SAE_EXT_KEY)
+                       sae->akmp = WPA_KEY_MGMT_SAE_EXT_KEY;
+               else if (sae->peer_akm_suite_selector ==
+                   RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY)
+                       sae->akmp = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
+       }
+
        /*
         * Check whether peer-commit-scalar and PEER-COMMIT-ELEMENT are same as
         * the values we sent which would be evidence of a reflection attack.
index 6eb2b6f4f0c1aea205101b52bf96b74c7dfff411..459117a71852993b86308f2ce6650d4e13f08f58 100644 (file)
@@ -107,6 +107,8 @@ struct sae_data {
        u8 pmk[SAE_PMK_LEN];
        size_t pmk_len;
        int akmp; /* WPA_KEY_MGMT_* used in key derivation */
+       u32 own_akm_suite_selector;
+       u32 peer_akm_suite_selector;
        u8 pmkid[SAE_PMKID_LEN];
        struct crypto_bignum *peer_commit_scalar;
        struct crypto_bignum *peer_commit_scalar_accepted;