]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SAE: Derive a variable length PMK with the new AKM suites
authorJouni Malinen <quic_jouni@quicinc.com>
Sun, 24 Jul 2022 19:16:40 +0000 (22:16 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 24 Jul 2022 21:31:51 +0000 (00:31 +0300)
Select the PMK length based on the used group (prime length) when using
the new AKM suites for SAE.

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

index 637ca29b5611aa9ead0a76608aaa64b338cf63b1..33c7e5fe177f236ec19cb977c632b807da4f1d14 100644 (file)
@@ -9,6 +9,8 @@
 #include "includes.h"
 
 #include "common.h"
+#include "common/defs.h"
+#include "common/wpa_common.h"
 #include "utils/const_time.h"
 #include "crypto/crypto.h"
 #include "crypto/sha256.h"
@@ -1520,10 +1522,11 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k)
        const u8 *salt;
        struct wpabuf *rejected_groups = NULL;
        u8 keyseed[SAE_MAX_HASH_LEN];
-       u8 keys[2 * SAE_MAX_HASH_LEN + SAE_PMK_LEN];
+       u8 keys[2 * SAE_MAX_HASH_LEN + SAE_PMK_LEN_MAX];
        struct crypto_bignum *tmp;
        int ret = -1;
        size_t hash_len, salt_len, prime_len = sae->tmp->prime_len;
+       size_t pmk_len;
        const u8 *addr[1];
        size_t len[1];
 
@@ -1545,6 +1548,14 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k)
                hash_len = sae_ffc_prime_len_2_hash_len(prime_len);
        else
                hash_len = sae_ecc_prime_len_2_hash_len(prime_len);
+       if (wpa_key_mgmt_sae_ext_key(sae->akmp))
+               pmk_len = hash_len;
+       else
+               pmk_len = SAE_PMK_LEN;
+       wpa_printf(MSG_DEBUG, "SAE: Derive keys - H2E=%d AKMP=0x%x = %08x (%s)",
+                  sae->h2e, sae->akmp,
+                  wpa_akm_to_suite(sae->akmp),
+                  wpa_key_mgmt_txt(sae->akmp, WPA_PROTO_RSN));
        if (sae->h2e && (sae->tmp->own_rejected_groups ||
                         sae->tmp->peer_rejected_groups)) {
                struct wpabuf *own, *peer;
@@ -1602,26 +1613,26 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k)
        if (sae->pk) {
                if (sae_kdf_hash(hash_len, keyseed, "SAE-PK keys",
                                 val, sae->tmp->order_len,
-                                keys, 2 * hash_len + SAE_PMK_LEN) < 0)
+                                keys, 2 * hash_len + pmk_len) < 0)
                        goto fail;
        } else {
                if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK",
                                 val, sae->tmp->order_len,
-                                keys, hash_len + SAE_PMK_LEN) < 0)
+                                keys, hash_len + pmk_len) < 0)
                        goto fail;
        }
 #else /* CONFIG_SAE_PK */
        if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK",
                         val, sae->tmp->order_len,
-                        keys, hash_len + SAE_PMK_LEN) < 0)
+                        keys, hash_len + pmk_len) < 0)
                goto fail;
 #endif /* !CONFIG_SAE_PK */
 
        forced_memzero(keyseed, sizeof(keyseed));
        os_memcpy(sae->tmp->kck, keys, hash_len);
        sae->tmp->kck_len = hash_len;
-       os_memcpy(sae->pmk, keys + hash_len, SAE_PMK_LEN);
-       sae->pmk_len = SAE_PMK_LEN;
+       os_memcpy(sae->pmk, keys + hash_len, pmk_len);
+       sae->pmk_len = pmk_len;
        os_memcpy(sae->pmkid, val, SAE_PMKID_LEN);
 #ifdef CONFIG_SAE_PK
        if (sae->pk) {
index 459117a71852993b86308f2ce6650d4e13f08f58..6a6b0c8241f063895eb1a4c1ac1c5fb815f57bd4 100644 (file)
@@ -11,6 +11,7 @@
 
 #define SAE_KCK_LEN 32
 #define SAE_PMK_LEN 32
+#define SAE_PMK_LEN_MAX 64
 #define SAE_PMKID_LEN 16
 #define SAE_MAX_PRIME_LEN 512
 #define SAE_MAX_ECC_PRIME_LEN 66
@@ -104,7 +105,7 @@ enum sae_state {
 struct sae_data {
        enum sae_state state;
        u16 send_confirm;
-       u8 pmk[SAE_PMK_LEN];
+       u8 pmk[SAE_PMK_LEN_MAX];
        size_t pmk_len;
        int akmp; /* WPA_KEY_MGMT_* used in key derivation */
        u32 own_akm_suite_selector;