From bf4f5d6570c847109378fd4f44e3d89c6ebb3acd Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 6 Jan 2013 15:13:07 +0200 Subject: [PATCH] SAE: Add support for FFC groups that do not use a safe prime This allows DH groups 22, 23, 24 to be used with SAE. Signed-hostap: Jouni Malinen --- src/common/sae.c | 53 +++++++++++++++++++++++------------------------- src/common/sae.h | 2 +- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/src/common/sae.c b/src/common/sae.c index b7da54d38..5d0ff4280 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -49,11 +49,9 @@ int sae_set_group(struct sae_data *sae, int group) } sae->prime = sae->prime_buf; - /* Assume r = (p-1)/2 for this group */ - sae->safe_prime = 1; - sae->order_buf = crypto_bignum_init(); - if (sae->order_buf == NULL || - crypto_bignum_rshift(sae->prime, 1, sae->order_buf) < 0) { + sae->order_buf = crypto_bignum_init_set(sae->dh->order, + sae->dh->order_len); + if (sae->order_buf == NULL) { sae_clear_data(sae); return -1; } @@ -124,20 +122,20 @@ static void buf_shift_right(u8 *buf, size_t len, size_t bits) } -static int sae_get_rand(const u8 *order, size_t prime_len_bits, u8 *val) +static int sae_get_rand(const u8 *order, size_t order_len_bits, u8 *val) { int iter = 0; - size_t prime_len = (prime_len_bits + 7) / 8; + size_t order_len = (order_len_bits + 7) / 8; do { if (iter++ > 100) return -1; - if (random_get_bytes(val, prime_len) < 0) + if (random_get_bytes(val, order_len) < 0) return -1; - if (prime_len_bits % 8) - buf_shift_right(val, prime_len, 8 - prime_len_bits % 8); - } while (os_memcmp(val, order, prime_len) >= 0 || - val_zero_or_one(val, prime_len)); + if (order_len_bits % 8) + buf_shift_right(val, order_len, 8 - order_len_bits % 8); + } while (os_memcmp(val, order, order_len) >= 0 || + val_zero_or_one(val, order_len)); return 0; } @@ -156,8 +154,9 @@ static struct crypto_bignum * sae_get_rand_and_mask(struct sae_data *sae) if (sae_get_rand(order, prime_len_bits, sae->sae_rand) < 0 || sae_get_rand(order, prime_len_bits, mask) < 0) return NULL; + sae->rand_len = sae->prime_len; wpa_hexdump_key(MSG_DEBUG, "SAE: rand", - sae->sae_rand, sae->prime_len); + sae->sae_rand, sae->rand_len); wpa_hexdump_key(MSG_DEBUG, "SAE: mask", mask, sae->prime_len); bn = crypto_bignum_init_set(mask, sae->prime_len); os_memset(mask, 0, sizeof(mask)); @@ -167,20 +166,18 @@ static struct crypto_bignum * sae_get_rand_and_mask(struct sae_data *sae) static struct crypto_bignum * sae_get_rand_and_mask_dh(struct sae_data *sae) { - u8 mask[SAE_MAX_PRIME_LEN], order[SAE_MAX_PRIME_LEN]; + u8 mask[SAE_MAX_PRIME_LEN]; struct crypto_bignum *bn; - size_t prime_len_bits = sae->prime_len * 8; - if (crypto_bignum_to_bin(sae->order, order, sizeof(order), - sae->prime_len) < 0 || - sae_get_rand(order, prime_len_bits, sae->sae_rand) < 0 || - sae_get_rand(order, prime_len_bits, mask) < 0) + if (sae_get_rand(sae->dh->order, sae->dh->order_len * 8, sae->sae_rand) + < 0 || + sae_get_rand(sae->dh->order, sae->dh->order_len * 8, mask) < 0) return NULL; - wpa_hexdump_key(MSG_DEBUG, "SAE: rand", - sae->sae_rand, sae->prime_len); - wpa_hexdump_key(MSG_DEBUG, "SAE: mask", mask, sae->prime_len); - bn = crypto_bignum_init_set(mask, sae->prime_len); + sae->rand_len = sae->dh->order_len; + wpa_hexdump_key(MSG_DEBUG, "SAE: rand", sae->sae_rand, sae->rand_len); + wpa_hexdump_key(MSG_DEBUG, "SAE: mask", mask, sae->dh->order_len); + bn = crypto_bignum_init_set(mask, sae->dh->order_len); os_memset(mask, 0, sizeof(mask)); return bn; } @@ -337,7 +334,7 @@ static int sae_derive_commit(struct sae_data *sae, struct crypto_ec_point *pwe) } x = crypto_bignum_init(); - bn_rand = crypto_bignum_init_set(sae->sae_rand, sae->prime_len); + bn_rand = crypto_bignum_init_set(sae->sae_rand, sae->rand_len); elem = crypto_ec_point_init(sae->ec); if (x == NULL || bn_rand == NULL || elem == NULL) goto fail; @@ -422,7 +419,7 @@ static int sae_test_pwd_seed_dh(struct sae_data *sae, const u8 *pwd_seed, a = crypto_bignum_init_set(pwd_value, sae->prime_len); - if (sae->safe_prime) { + if (sae->dh->safe_prime) { /* * r = (p-1)/2 for the group used here, so this becomes: * PWE = pwd-value^2 modulo p @@ -539,7 +536,7 @@ static int sae_derive_commit_dh(struct sae_data *sae, struct crypto_bignum *pwe) } x = crypto_bignum_init(); - bn_rand = crypto_bignum_init_set(sae->sae_rand, sae->prime_len); + bn_rand = crypto_bignum_init_set(sae->sae_rand, sae->rand_len); elem = crypto_bignum_init(); if (x == NULL || bn_rand == NULL || elem == NULL) goto fail; @@ -664,7 +661,7 @@ static int sae_derive_k_ec(struct sae_data *sae, u8 *k) sae->prime_len); peer_elem = crypto_ec_point_from_bin(sae->ec, sae->peer_commit_element); K = crypto_ec_point_init(sae->ec); - rand_bn = crypto_bignum_init_set(sae->sae_rand, sae->prime_len); + rand_bn = crypto_bignum_init_set(sae->sae_rand, sae->rand_len); if (pwe == NULL || peer_elem == NULL || peer_scalar == NULL || K == NULL || rand_bn == NULL) goto fail; @@ -713,7 +710,7 @@ static int sae_derive_k_dh(struct sae_data *sae, u8 *k) peer_elem = crypto_bignum_init_set(sae->peer_commit_element, sae->prime_len); K = crypto_bignum_init(); - rand_bn = crypto_bignum_init_set(sae->sae_rand, sae->prime_len); + rand_bn = crypto_bignum_init_set(sae->sae_rand, sae->rand_len); if (pwe == NULL || peer_elem == NULL || peer_scalar == NULL || K == NULL || rand_bn == NULL) goto fail; diff --git a/src/common/sae.h b/src/common/sae.h index bcd50a05b..4fe4eed2b 100644 --- a/src/common/sae.h +++ b/src/common/sae.h @@ -28,6 +28,7 @@ struct sae_data { u8 peer_commit_element[2 * SAE_MAX_PRIME_LEN]; u8 pwe[2 * SAE_MAX_PRIME_LEN]; u8 sae_rand[SAE_MAX_PRIME_LEN]; + size_t rand_len; int group; struct crypto_ec *ec; int prime_len; @@ -36,7 +37,6 @@ struct sae_data { const struct crypto_bignum *order; struct crypto_bignum *prime_buf; struct crypto_bignum *order_buf; - int safe_prime; }; int sae_set_group(struct sae_data *sae, int group);