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 "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) {

View 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;