SAE: Derive a variable length PMK with the new AKM suites

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>
This commit is contained in:
Jouni Malinen 2022-07-24 22:16:40 +03:00 committed by Jouni Malinen
parent 91010e6f67
commit f70db167ab
2 changed files with 19 additions and 7 deletions

View file

@ -9,6 +9,8 @@
#include "includes.h" #include "includes.h"
#include "common.h" #include "common.h"
#include "common/defs.h"
#include "common/wpa_common.h"
#include "utils/const_time.h" #include "utils/const_time.h"
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "crypto/sha256.h" #include "crypto/sha256.h"
@ -1520,10 +1522,11 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k)
const u8 *salt; const u8 *salt;
struct wpabuf *rejected_groups = NULL; struct wpabuf *rejected_groups = NULL;
u8 keyseed[SAE_MAX_HASH_LEN]; 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; struct crypto_bignum *tmp;
int ret = -1; int ret = -1;
size_t hash_len, salt_len, prime_len = sae->tmp->prime_len; size_t hash_len, salt_len, prime_len = sae->tmp->prime_len;
size_t pmk_len;
const u8 *addr[1]; const u8 *addr[1];
size_t len[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); hash_len = sae_ffc_prime_len_2_hash_len(prime_len);
else else
hash_len = sae_ecc_prime_len_2_hash_len(prime_len); 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 || if (sae->h2e && (sae->tmp->own_rejected_groups ||
sae->tmp->peer_rejected_groups)) { sae->tmp->peer_rejected_groups)) {
struct wpabuf *own, *peer; 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->pk) {
if (sae_kdf_hash(hash_len, keyseed, "SAE-PK keys", if (sae_kdf_hash(hash_len, keyseed, "SAE-PK keys",
val, sae->tmp->order_len, val, sae->tmp->order_len,
keys, 2 * hash_len + SAE_PMK_LEN) < 0) keys, 2 * hash_len + pmk_len) < 0)
goto fail; goto fail;
} else { } else {
if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK", if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK",
val, sae->tmp->order_len, val, sae->tmp->order_len,
keys, hash_len + SAE_PMK_LEN) < 0) keys, hash_len + pmk_len) < 0)
goto fail; goto fail;
} }
#else /* CONFIG_SAE_PK */ #else /* CONFIG_SAE_PK */
if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK", if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK",
val, sae->tmp->order_len, val, sae->tmp->order_len,
keys, hash_len + SAE_PMK_LEN) < 0) keys, hash_len + pmk_len) < 0)
goto fail; goto fail;
#endif /* !CONFIG_SAE_PK */ #endif /* !CONFIG_SAE_PK */
forced_memzero(keyseed, sizeof(keyseed)); forced_memzero(keyseed, sizeof(keyseed));
os_memcpy(sae->tmp->kck, keys, hash_len); os_memcpy(sae->tmp->kck, keys, hash_len);
sae->tmp->kck_len = hash_len; sae->tmp->kck_len = hash_len;
os_memcpy(sae->pmk, keys + hash_len, SAE_PMK_LEN); os_memcpy(sae->pmk, keys + hash_len, pmk_len);
sae->pmk_len = SAE_PMK_LEN; sae->pmk_len = pmk_len;
os_memcpy(sae->pmkid, val, SAE_PMKID_LEN); os_memcpy(sae->pmkid, val, SAE_PMKID_LEN);
#ifdef CONFIG_SAE_PK #ifdef CONFIG_SAE_PK
if (sae->pk) { if (sae->pk) {

View file

@ -11,6 +11,7 @@
#define SAE_KCK_LEN 32 #define SAE_KCK_LEN 32
#define SAE_PMK_LEN 32 #define SAE_PMK_LEN 32
#define SAE_PMK_LEN_MAX 64
#define SAE_PMKID_LEN 16 #define SAE_PMKID_LEN 16
#define SAE_MAX_PRIME_LEN 512 #define SAE_MAX_PRIME_LEN 512
#define SAE_MAX_ECC_PRIME_LEN 66 #define SAE_MAX_ECC_PRIME_LEN 66
@ -104,7 +105,7 @@ enum sae_state {
struct sae_data { struct sae_data {
enum sae_state state; enum sae_state state;
u16 send_confirm; u16 send_confirm;
u8 pmk[SAE_PMK_LEN]; u8 pmk[SAE_PMK_LEN_MAX];
size_t pmk_len; size_t pmk_len;
int akmp; /* WPA_KEY_MGMT_* used in key derivation */ int akmp; /* WPA_KEY_MGMT_* used in key derivation */
u32 own_akm_suite_selector; u32 own_akm_suite_selector;