SAE: Use const_time selection for PWE in FFC

This is an initial step towards making the FFC case use strictly
constant time operations similarly to the ECC case.
sae_test_pwd_seed_ffc() does not yet have constant time behavior,
though.

This is related to CVE-2019-9494.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2019-03-02 12:45:33 +02:00 committed by Jouni Malinen
parent 90839597cc
commit f8f20717f8

View file

@ -612,17 +612,28 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
const u8 *addr2, const u8 *password,
size_t password_len, const char *identifier)
{
u8 counter, k;
u8 counter, k, sel_counter = 0;
u8 addrs[2 * ETH_ALEN];
const u8 *addr[3];
size_t len[3];
size_t num_elem;
int found = 0;
struct crypto_bignum *pwe = NULL;
u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
* mask */
u8 mask;
struct crypto_bignum *pwe;
size_t prime_len = sae->tmp->prime_len * 8;
u8 *pwe_buf;
crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
sae->tmp->pwe_ffc = NULL;
/* Allocate a buffer to maintain selected and candidate PWE for constant
* time selection. */
pwe_buf = os_zalloc(prime_len * 2);
pwe = crypto_bignum_init();
if (!pwe_buf || !pwe)
goto fail;
wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
password, password_len);
@ -661,27 +672,33 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
addr, len, pwd_seed) < 0)
break;
if (!pwe) {
pwe = crypto_bignum_init();
if (!pwe)
break;
}
res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
/* res is -1 for fatal failure, 0 if a valid PWE was not found,
* or 1 if a valid PWE was found. */
if (res < 0)
break;
if (res > 0) {
found = 1;
if (!sae->tmp->pwe_ffc) {
wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
sae->tmp->pwe_ffc = pwe;
pwe = NULL;
}
}
/* Store the candidate PWE into the second half of pwe_buf and
* the selected PWE in the beginning of pwe_buf using constant
* time selection. */
if (crypto_bignum_to_bin(pwe, pwe_buf + prime_len, prime_len,
prime_len) < 0)
break;
const_time_select_bin(found, pwe_buf, pwe_buf + prime_len,
prime_len, pwe_buf);
sel_counter = const_time_select_u8(found, sel_counter, counter);
mask = const_time_eq_u8(res, 1);
found = const_time_select_u8(found, found, mask);
}
crypto_bignum_deinit(pwe, 1);
if (!found)
goto fail;
return found ? 0 : -1;
wpa_printf(MSG_DEBUG, "SAE: Use PWE from counter = %02u", sel_counter);
sae->tmp->pwe_ffc = crypto_bignum_init_set(pwe_buf, prime_len);
fail:
crypto_bignum_deinit(pwe, 1);
bin_clear_free(pwe_buf, prime_len * 2);
return sae->tmp->pwe_ffc ? 0 : -1;
}