From 91010e6f67e049e3133d78d12dda3d5129d17acf Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 24 Jul 2022 22:24:56 +0300 Subject: [PATCH] SAE: Indicate AKM suite selector in commit for new AKM suites 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 --- src/common/ieee802_11_defs.h | 1 + src/common/sae.c | 75 ++++++++++++++++++++++++++++++++++++ src/common/sae.h | 2 + 3 files changed, 78 insertions(+) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 1bd57afe5..65e125e83 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -495,6 +495,7 @@ #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 diff --git a/src/common/sae.c b/src/common/sae.c index 48e4fb4af..637ca29b5 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -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. diff --git a/src/common/sae.h b/src/common/sae.h index 6eb2b6f4f..459117a71 100644 --- a/src/common/sae.h +++ b/src/common/sae.h @@ -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;