Home | History | Annotate | Download | only in common
      1 /*
      2  * Simultaneous authentication of equals
      3  * Copyright (c) 2012-2013, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "includes.h"
     10 
     11 #include "common.h"
     12 #include "crypto/crypto.h"
     13 #include "crypto/sha256.h"
     14 #include "crypto/random.h"
     15 #include "crypto/dh_groups.h"
     16 #include "ieee802_11_defs.h"
     17 #include "sae.h"
     18 
     19 
     20 int sae_set_group(struct sae_data *sae, int group)
     21 {
     22 	struct sae_temporary_data *tmp;
     23 
     24 	sae_clear_data(sae);
     25 	tmp = sae->tmp = os_zalloc(sizeof(*tmp));
     26 	if (tmp == NULL)
     27 		return -1;
     28 
     29 	/* First, check if this is an ECC group */
     30 	tmp->ec = crypto_ec_init(group);
     31 	if (tmp->ec) {
     32 		sae->group = group;
     33 		tmp->prime_len = crypto_ec_prime_len(tmp->ec);
     34 		tmp->prime = crypto_ec_get_prime(tmp->ec);
     35 		tmp->order = crypto_ec_get_order(tmp->ec);
     36 		return 0;
     37 	}
     38 
     39 	/* Not an ECC group, check FFC */
     40 	tmp->dh = dh_groups_get(group);
     41 	if (tmp->dh) {
     42 		sae->group = group;
     43 		tmp->prime_len = tmp->dh->prime_len;
     44 		if (tmp->prime_len > SAE_MAX_PRIME_LEN) {
     45 			sae_clear_data(sae);
     46 			return -1;
     47 		}
     48 
     49 		tmp->prime_buf = crypto_bignum_init_set(tmp->dh->prime,
     50 							tmp->prime_len);
     51 		if (tmp->prime_buf == NULL) {
     52 			sae_clear_data(sae);
     53 			return -1;
     54 		}
     55 		tmp->prime = tmp->prime_buf;
     56 
     57 		tmp->order_buf = crypto_bignum_init_set(tmp->dh->order,
     58 							tmp->dh->order_len);
     59 		if (tmp->order_buf == NULL) {
     60 			sae_clear_data(sae);
     61 			return -1;
     62 		}
     63 		tmp->order = tmp->order_buf;
     64 
     65 		return 0;
     66 	}
     67 
     68 	/* Unsupported group */
     69 	return -1;
     70 }
     71 
     72 
     73 void sae_clear_temp_data(struct sae_data *sae)
     74 {
     75 	struct sae_temporary_data *tmp;
     76 	if (sae == NULL || sae->tmp == NULL)
     77 		return;
     78 	tmp = sae->tmp;
     79 	crypto_ec_deinit(tmp->ec);
     80 	crypto_bignum_deinit(tmp->prime_buf, 0);
     81 	crypto_bignum_deinit(tmp->order_buf, 0);
     82 	crypto_bignum_deinit(tmp->sae_rand, 1);
     83 	crypto_bignum_deinit(tmp->pwe_ffc, 1);
     84 	crypto_bignum_deinit(tmp->own_commit_scalar, 0);
     85 	crypto_bignum_deinit(tmp->own_commit_element_ffc, 0);
     86 	crypto_bignum_deinit(tmp->peer_commit_element_ffc, 0);
     87 	crypto_ec_point_deinit(tmp->pwe_ecc, 1);
     88 	crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0);
     89 	crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0);
     90 	os_free(sae->tmp);
     91 	sae->tmp = NULL;
     92 }
     93 
     94 
     95 void sae_clear_data(struct sae_data *sae)
     96 {
     97 	if (sae == NULL)
     98 		return;
     99 	sae_clear_temp_data(sae);
    100 	crypto_bignum_deinit(sae->peer_commit_scalar, 0);
    101 	os_memset(sae, 0, sizeof(*sae));
    102 }
    103 
    104 
    105 static void buf_shift_right(u8 *buf, size_t len, size_t bits)
    106 {
    107 	size_t i;
    108 	for (i = len - 1; i > 0; i--)
    109 		buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits);
    110 	buf[0] >>= bits;
    111 }
    112 
    113 
    114 static struct crypto_bignum * sae_get_rand(struct sae_data *sae)
    115 {
    116 	u8 val[SAE_MAX_PRIME_LEN];
    117 	int iter = 0;
    118 	struct crypto_bignum *bn = NULL;
    119 	int order_len_bits = crypto_bignum_bits(sae->tmp->order);
    120 	size_t order_len = (order_len_bits + 7) / 8;
    121 
    122 	if (order_len > sizeof(val))
    123 		return NULL;
    124 
    125 	for (;;) {
    126 		if (iter++ > 100)
    127 			return NULL;
    128 		if (random_get_bytes(val, order_len) < 0)
    129 			return NULL;
    130 		if (order_len_bits % 8)
    131 			buf_shift_right(val, order_len, 8 - order_len_bits % 8);
    132 		bn = crypto_bignum_init_set(val, order_len);
    133 		if (bn == NULL)
    134 			return NULL;
    135 		if (crypto_bignum_is_zero(bn) ||
    136 		    crypto_bignum_is_one(bn) ||
    137 		    crypto_bignum_cmp(bn, sae->tmp->order) >= 0) {
    138 			crypto_bignum_deinit(bn, 0);
    139 			continue;
    140 		}
    141 		break;
    142 	}
    143 
    144 	os_memset(val, 0, order_len);
    145 	return bn;
    146 }
    147 
    148 
    149 static struct crypto_bignum * sae_get_rand_and_mask(struct sae_data *sae)
    150 {
    151 	crypto_bignum_deinit(sae->tmp->sae_rand, 1);
    152 	sae->tmp->sae_rand = sae_get_rand(sae);
    153 	if (sae->tmp->sae_rand == NULL)
    154 		return NULL;
    155 	return sae_get_rand(sae);
    156 }
    157 
    158 
    159 static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key)
    160 {
    161 	wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR
    162 		   " addr2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2));
    163 	if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) {
    164 		os_memcpy(key, addr1, ETH_ALEN);
    165 		os_memcpy(key + ETH_ALEN, addr2, ETH_ALEN);
    166 	} else {
    167 		os_memcpy(key, addr2, ETH_ALEN);
    168 		os_memcpy(key + ETH_ALEN, addr1, ETH_ALEN);
    169 	}
    170 }
    171 
    172 
    173 static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
    174 				 struct crypto_ec_point *pwe)
    175 {
    176 	u8 pwd_value[SAE_MAX_ECC_PRIME_LEN], prime[SAE_MAX_ECC_PRIME_LEN];
    177 	struct crypto_bignum *x;
    178 	int y_bit;
    179 	size_t bits;
    180 
    181 	if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
    182 				 sae->tmp->prime_len) < 0)
    183 		return -1;
    184 
    185 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
    186 
    187 	/* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
    188 	bits = crypto_ec_prime_len_bits(sae->tmp->ec);
    189 	sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
    190 			prime, sae->tmp->prime_len, pwd_value, bits);
    191 	if (bits % 8)
    192 		buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
    193 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
    194 			pwd_value, sae->tmp->prime_len);
    195 
    196 	if (os_memcmp(pwd_value, prime, sae->tmp->prime_len) >= 0)
    197 		return 0;
    198 
    199 	y_bit = pwd_seed[SHA256_MAC_LEN - 1] & 0x01;
    200 
    201 	x = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
    202 	if (x == NULL)
    203 		return -1;
    204 	if (crypto_ec_point_solve_y_coord(sae->tmp->ec, pwe, x, y_bit) < 0) {
    205 		crypto_bignum_deinit(x, 0);
    206 		wpa_printf(MSG_DEBUG, "SAE: No solution found");
    207 		return 0;
    208 	}
    209 	crypto_bignum_deinit(x, 0);
    210 
    211 	wpa_printf(MSG_DEBUG, "SAE: PWE found");
    212 
    213 	return 1;
    214 }
    215 
    216 
    217 static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
    218 				 struct crypto_bignum *pwe)
    219 {
    220 	u8 pwd_value[SAE_MAX_PRIME_LEN];
    221 	size_t bits = sae->tmp->prime_len * 8;
    222 	u8 exp[1];
    223 	struct crypto_bignum *a, *b;
    224 	int res;
    225 
    226 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
    227 
    228 	/* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
    229 	sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
    230 			sae->tmp->dh->prime, sae->tmp->prime_len, pwd_value,
    231 			bits);
    232 	if (bits % 8)
    233 		buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
    234 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value,
    235 			sae->tmp->prime_len);
    236 
    237 	if (os_memcmp(pwd_value, sae->tmp->dh->prime, sae->tmp->prime_len) >= 0)
    238 	{
    239 		wpa_printf(MSG_DEBUG, "SAE: pwd-value >= p");
    240 		return 0;
    241 	}
    242 
    243 	/* PWE = pwd-value^((p-1)/r) modulo p */
    244 
    245 	a = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
    246 
    247 	if (sae->tmp->dh->safe_prime) {
    248 		/*
    249 		 * r = (p-1)/2 for the group used here, so this becomes:
    250 		 * PWE = pwd-value^2 modulo p
    251 		 */
    252 		exp[0] = 2;
    253 		b = crypto_bignum_init_set(exp, sizeof(exp));
    254 	} else {
    255 		/* Calculate exponent: (p-1)/r */
    256 		exp[0] = 1;
    257 		b = crypto_bignum_init_set(exp, sizeof(exp));
    258 		if (b == NULL ||
    259 		    crypto_bignum_sub(sae->tmp->prime, b, b) < 0 ||
    260 		    crypto_bignum_div(b, sae->tmp->order, b) < 0) {
    261 			crypto_bignum_deinit(b, 0);
    262 			b = NULL;
    263 		}
    264 	}
    265 
    266 	if (a == NULL || b == NULL)
    267 		res = -1;
    268 	else
    269 		res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe);
    270 
    271 	crypto_bignum_deinit(a, 0);
    272 	crypto_bignum_deinit(b, 0);
    273 
    274 	if (res < 0) {
    275 		wpa_printf(MSG_DEBUG, "SAE: Failed to calculate PWE");
    276 		return -1;
    277 	}
    278 
    279 	/* if (PWE > 1) --> found */
    280 	if (crypto_bignum_is_zero(pwe) || crypto_bignum_is_one(pwe)) {
    281 		wpa_printf(MSG_DEBUG, "SAE: PWE <= 1");
    282 		return 0;
    283 	}
    284 
    285 	wpa_printf(MSG_DEBUG, "SAE: PWE found");
    286 	return 1;
    287 }
    288 
    289 
    290 static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
    291 			      const u8 *addr2, const u8 *password,
    292 			      size_t password_len)
    293 {
    294 	u8 counter, k = 4;
    295 	u8 addrs[2 * ETH_ALEN];
    296 	const u8 *addr[2];
    297 	size_t len[2];
    298 	int found = 0;
    299 	struct crypto_ec_point *pwe_tmp;
    300 
    301 	if (sae->tmp->pwe_ecc == NULL) {
    302 		sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec);
    303 		if (sae->tmp->pwe_ecc == NULL)
    304 			return -1;
    305 	}
    306 	pwe_tmp = crypto_ec_point_init(sae->tmp->ec);
    307 	if (pwe_tmp == NULL)
    308 		return -1;
    309 
    310 	wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
    311 			      password, password_len);
    312 
    313 	/*
    314 	 * H(salt, ikm) = HMAC-SHA256(salt, ikm)
    315 	 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
    316 	 *              password || counter)
    317 	 */
    318 	sae_pwd_seed_key(addr1, addr2, addrs);
    319 
    320 	addr[0] = password;
    321 	len[0] = password_len;
    322 	addr[1] = &counter;
    323 	len[1] = sizeof(counter);
    324 
    325 	/*
    326 	 * Continue for at least k iterations to protect against side-channel
    327 	 * attacks that attempt to determine the number of iterations required
    328 	 * in the loop.
    329 	 */
    330 	for (counter = 1; counter < k || !found; counter++) {
    331 		u8 pwd_seed[SHA256_MAC_LEN];
    332 		int res;
    333 
    334 		if (counter > 200) {
    335 			/* This should not happen in practice */
    336 			wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
    337 			break;
    338 		}
    339 
    340 		wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
    341 		if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len,
    342 				       pwd_seed) < 0)
    343 			break;
    344 		res = sae_test_pwd_seed_ecc(sae, pwd_seed,
    345 					    found ? pwe_tmp :
    346 					    sae->tmp->pwe_ecc);
    347 		if (res < 0)
    348 			break;
    349 		if (res == 0)
    350 			continue;
    351 		if (found) {
    352 			wpa_printf(MSG_DEBUG, "SAE: Ignore this PWE (one was "
    353 				   "already selected)");
    354 		} else {
    355 			wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
    356 			found = 1;
    357 		}
    358 	}
    359 
    360 	crypto_ec_point_deinit(pwe_tmp, 1);
    361 
    362 	return found ? 0 : -1;
    363 }
    364 
    365 
    366 static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
    367 			      const u8 *addr2, const u8 *password,
    368 			      size_t password_len)
    369 {
    370 	u8 counter;
    371 	u8 addrs[2 * ETH_ALEN];
    372 	const u8 *addr[2];
    373 	size_t len[2];
    374 	int found = 0;
    375 
    376 	if (sae->tmp->pwe_ffc == NULL) {
    377 		sae->tmp->pwe_ffc = crypto_bignum_init();
    378 		if (sae->tmp->pwe_ffc == NULL)
    379 			return -1;
    380 	}
    381 
    382 	wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
    383 			      password, password_len);
    384 
    385 	/*
    386 	 * H(salt, ikm) = HMAC-SHA256(salt, ikm)
    387 	 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
    388 	 *              password || counter)
    389 	 */
    390 	sae_pwd_seed_key(addr1, addr2, addrs);
    391 
    392 	addr[0] = password;
    393 	len[0] = password_len;
    394 	addr[1] = &counter;
    395 	len[1] = sizeof(counter);
    396 
    397 	for (counter = 1; !found; counter++) {
    398 		u8 pwd_seed[SHA256_MAC_LEN];
    399 		int res;
    400 
    401 		if (counter > 200) {
    402 			/* This should not happen in practice */
    403 			wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
    404 			break;
    405 		}
    406 
    407 		wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
    408 		if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len,
    409 				       pwd_seed) < 0)
    410 			break;
    411 		res = sae_test_pwd_seed_ffc(sae, pwd_seed, sae->tmp->pwe_ffc);
    412 		if (res < 0)
    413 			break;
    414 		if (res > 0) {
    415 			wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
    416 			found = 1;
    417 		}
    418 	}
    419 
    420 	return found ? 0 : -1;
    421 }
    422 
    423 
    424 static int sae_derive_commit_element_ecc(struct sae_data *sae,
    425 					 struct crypto_bignum *mask)
    426 {
    427 	/* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
    428 	if (!sae->tmp->own_commit_element_ecc) {
    429 		sae->tmp->own_commit_element_ecc =
    430 			crypto_ec_point_init(sae->tmp->ec);
    431 		if (!sae->tmp->own_commit_element_ecc)
    432 			return -1;
    433 	}
    434 
    435 	if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, mask,
    436 				sae->tmp->own_commit_element_ecc) < 0 ||
    437 	    crypto_ec_point_invert(sae->tmp->ec,
    438 				   sae->tmp->own_commit_element_ecc) < 0) {
    439 		wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
    440 		return -1;
    441 	}
    442 
    443 	return 0;
    444 }
    445 
    446 
    447 static int sae_derive_commit_element_ffc(struct sae_data *sae,
    448 					 struct crypto_bignum *mask)
    449 {
    450 	/* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
    451 	if (!sae->tmp->own_commit_element_ffc) {
    452 		sae->tmp->own_commit_element_ffc = crypto_bignum_init();
    453 		if (!sae->tmp->own_commit_element_ffc)
    454 			return -1;
    455 	}
    456 
    457 	if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, mask, sae->tmp->prime,
    458 				  sae->tmp->own_commit_element_ffc) < 0 ||
    459 	    crypto_bignum_inverse(sae->tmp->own_commit_element_ffc,
    460 				  sae->tmp->prime,
    461 				  sae->tmp->own_commit_element_ffc) < 0) {
    462 		wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
    463 		return -1;
    464 	}
    465 
    466 	return 0;
    467 }
    468 
    469 
    470 static int sae_derive_commit(struct sae_data *sae)
    471 {
    472 	struct crypto_bignum *mask;
    473 	int ret = -1;
    474 
    475 	mask = sae_get_rand_and_mask(sae);
    476 	if (mask == NULL) {
    477 		wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask");
    478 		return -1;
    479 	}
    480 
    481 	/* commit-scalar = (rand + mask) modulo r */
    482 	if (!sae->tmp->own_commit_scalar) {
    483 		sae->tmp->own_commit_scalar = crypto_bignum_init();
    484 		if (!sae->tmp->own_commit_scalar)
    485 			goto fail;
    486 	}
    487 	crypto_bignum_add(sae->tmp->sae_rand, mask,
    488 			  sae->tmp->own_commit_scalar);
    489 	crypto_bignum_mod(sae->tmp->own_commit_scalar, sae->tmp->order,
    490 			  sae->tmp->own_commit_scalar);
    491 
    492 	if (sae->tmp->ec && sae_derive_commit_element_ecc(sae, mask) < 0)
    493 		goto fail;
    494 	if (sae->tmp->dh && sae_derive_commit_element_ffc(sae, mask) < 0)
    495 		goto fail;
    496 
    497 	ret = 0;
    498 fail:
    499 	crypto_bignum_deinit(mask, 1);
    500 	return ret;
    501 }
    502 
    503 
    504 int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
    505 		       const u8 *password, size_t password_len,
    506 		       struct sae_data *sae)
    507 {
    508 	if (sae->tmp == NULL)
    509 		return -1;
    510 	if (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
    511 					  password_len) < 0)
    512 		return -1;
    513 	if (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
    514 					  password_len) < 0)
    515 		return -1;
    516 	if (sae_derive_commit(sae) < 0)
    517 		return -1;
    518 	return 0;
    519 }
    520 
    521 
    522 static int sae_derive_k_ecc(struct sae_data *sae, u8 *k)
    523 {
    524 	struct crypto_ec_point *K;
    525 	int ret = -1;
    526 
    527 	K = crypto_ec_point_init(sae->tmp->ec);
    528 	if (K == NULL)
    529 		goto fail;
    530 
    531 	/*
    532 	 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
    533 	 *                                        PEER-COMMIT-ELEMENT)))
    534 	 * If K is identity element (point-at-infinity), reject
    535 	 * k = F(K) (= x coordinate)
    536 	 */
    537 
    538 	if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc,
    539 				sae->peer_commit_scalar, K) < 0 ||
    540 	    crypto_ec_point_add(sae->tmp->ec, K,
    541 				sae->tmp->peer_commit_element_ecc, K) < 0 ||
    542 	    crypto_ec_point_mul(sae->tmp->ec, K, sae->tmp->sae_rand, K) < 0 ||
    543 	    crypto_ec_point_is_at_infinity(sae->tmp->ec, K) ||
    544 	    crypto_ec_point_to_bin(sae->tmp->ec, K, k, NULL) < 0) {
    545 		wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
    546 		goto fail;
    547 	}
    548 
    549 	wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len);
    550 
    551 	ret = 0;
    552 fail:
    553 	crypto_ec_point_deinit(K, 1);
    554 	return ret;
    555 }
    556 
    557 
    558 static int sae_derive_k_ffc(struct sae_data *sae, u8 *k)
    559 {
    560 	struct crypto_bignum *K;
    561 	int ret = -1;
    562 
    563 	K = crypto_bignum_init();
    564 	if (K == NULL)
    565 		goto fail;
    566 
    567 	/*
    568 	 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
    569 	 *                                        PEER-COMMIT-ELEMENT)))
    570 	 * If K is identity element (one), reject.
    571 	 * k = F(K) (= x coordinate)
    572 	 */
    573 
    574 	if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, sae->peer_commit_scalar,
    575 				  sae->tmp->prime, K) < 0 ||
    576 	    crypto_bignum_mulmod(K, sae->tmp->peer_commit_element_ffc,
    577 				 sae->tmp->prime, K) < 0 ||
    578 	    crypto_bignum_exptmod(K, sae->tmp->sae_rand, sae->tmp->prime, K) < 0
    579 	    ||
    580 	    crypto_bignum_is_one(K) ||
    581 	    crypto_bignum_to_bin(K, k, SAE_MAX_PRIME_LEN, sae->tmp->prime_len) <
    582 	    0) {
    583 		wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
    584 		goto fail;
    585 	}
    586 
    587 	wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len);
    588 
    589 	ret = 0;
    590 fail:
    591 	crypto_bignum_deinit(K, 1);
    592 	return ret;
    593 }
    594 
    595 
    596 static int sae_derive_keys(struct sae_data *sae, const u8 *k)
    597 {
    598 	u8 null_key[SAE_KEYSEED_KEY_LEN], val[SAE_MAX_PRIME_LEN];
    599 	u8 keyseed[SHA256_MAC_LEN];
    600 	u8 keys[SAE_KCK_LEN + SAE_PMK_LEN];
    601 	struct crypto_bignum *tmp;
    602 	int ret = -1;
    603 
    604 	tmp = crypto_bignum_init();
    605 	if (tmp == NULL)
    606 		goto fail;
    607 
    608 	/* keyseed = H(<0>32, k)
    609 	 * KCK || PMK = KDF-512(keyseed, "SAE KCK and PMK",
    610 	 *                      (commit-scalar + peer-commit-scalar) modulo r)
    611 	 * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128)
    612 	 */
    613 
    614 	os_memset(null_key, 0, sizeof(null_key));
    615 	hmac_sha256(null_key, sizeof(null_key), k, sae->tmp->prime_len,
    616 		    keyseed);
    617 	wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, sizeof(keyseed));
    618 
    619 	crypto_bignum_add(sae->tmp->own_commit_scalar, sae->peer_commit_scalar,
    620 			  tmp);
    621 	crypto_bignum_mod(tmp, sae->tmp->order, tmp);
    622 	crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->prime_len);
    623 	wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
    624 	sha256_prf(keyseed, sizeof(keyseed), "SAE KCK and PMK",
    625 		   val, sae->tmp->prime_len, keys, sizeof(keys));
    626 	os_memcpy(sae->tmp->kck, keys, SAE_KCK_LEN);
    627 	os_memcpy(sae->pmk, keys + SAE_KCK_LEN, SAE_PMK_LEN);
    628 	wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->tmp->kck, SAE_KCK_LEN);
    629 	wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN);
    630 
    631 	ret = 0;
    632 fail:
    633 	crypto_bignum_deinit(tmp, 0);
    634 	return ret;
    635 }
    636 
    637 
    638 int sae_process_commit(struct sae_data *sae)
    639 {
    640 	u8 k[SAE_MAX_PRIME_LEN];
    641 	if (sae->tmp == NULL ||
    642 	    (sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) ||
    643 	    (sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) ||
    644 	    sae_derive_keys(sae, k) < 0)
    645 		return -1;
    646 	return 0;
    647 }
    648 
    649 
    650 void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
    651 		      const struct wpabuf *token)
    652 {
    653 	u8 *pos;
    654 
    655 	if (sae->tmp == NULL)
    656 		return;
    657 
    658 	wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
    659 	if (token)
    660 		wpabuf_put_buf(buf, token);
    661 	pos = wpabuf_put(buf, sae->tmp->prime_len);
    662 	crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
    663 			     sae->tmp->prime_len, sae->tmp->prime_len);
    664 	wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar",
    665 		    pos, sae->tmp->prime_len);
    666 	if (sae->tmp->ec) {
    667 		pos = wpabuf_put(buf, 2 * sae->tmp->prime_len);
    668 		crypto_ec_point_to_bin(sae->tmp->ec,
    669 				       sae->tmp->own_commit_element_ecc,
    670 				       pos, pos + sae->tmp->prime_len);
    671 		wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)",
    672 			    pos, sae->tmp->prime_len);
    673 		wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)",
    674 			    pos + sae->tmp->prime_len, sae->tmp->prime_len);
    675 	} else {
    676 		pos = wpabuf_put(buf, sae->tmp->prime_len);
    677 		crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos,
    678 				     sae->tmp->prime_len, sae->tmp->prime_len);
    679 		wpa_hexdump(MSG_DEBUG, "SAE: own commit-element",
    680 			    pos, sae->tmp->prime_len);
    681 	}
    682 }
    683 
    684 
    685 static u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups,
    686 			     u16 group)
    687 {
    688 	if (allowed_groups) {
    689 		int i;
    690 		for (i = 0; allowed_groups[i] > 0; i++) {
    691 			if (allowed_groups[i] == group)
    692 				break;
    693 		}
    694 		if (allowed_groups[i] != group) {
    695 			wpa_printf(MSG_DEBUG, "SAE: Proposed group %u not "
    696 				   "enabled in the current configuration",
    697 				   group);
    698 			return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
    699 		}
    700 	}
    701 
    702 	if (sae->state == SAE_COMMITTED && group != sae->group) {
    703 		wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed");
    704 		return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
    705 	}
    706 
    707 	if (group != sae->group && sae_set_group(sae, group) < 0) {
    708 		wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
    709 			   group);
    710 		return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
    711 	}
    712 
    713 	if (sae->tmp == NULL) {
    714 		wpa_printf(MSG_DEBUG, "SAE: Group information not yet initialized");
    715 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    716 	}
    717 
    718 	if (sae->tmp->dh && !allowed_groups) {
    719 		wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without "
    720 			   "explicit configuration enabling it", group);
    721 		return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
    722 	}
    723 
    724 	return WLAN_STATUS_SUCCESS;
    725 }
    726 
    727 
    728 static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
    729 				   const u8 *end, const u8 **token,
    730 				   size_t *token_len)
    731 {
    732 	if (*pos + (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len < end) {
    733 		size_t tlen = end - (*pos + (sae->tmp->ec ? 3 : 2) *
    734 				     sae->tmp->prime_len);
    735 		wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
    736 		if (token)
    737 			*token = *pos;
    738 		if (token_len)
    739 			*token_len = tlen;
    740 		*pos += tlen;
    741 	} else {
    742 		if (token)
    743 			*token = NULL;
    744 		if (token_len)
    745 			*token_len = 0;
    746 	}
    747 }
    748 
    749 
    750 static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos,
    751 				   const u8 *end)
    752 {
    753 	struct crypto_bignum *peer_scalar;
    754 
    755 	if (*pos + sae->tmp->prime_len > end) {
    756 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar");
    757 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    758 	}
    759 
    760 	peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len);
    761 	if (peer_scalar == NULL)
    762 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    763 
    764 	/*
    765 	 * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for
    766 	 * the peer and it is in Authenticated state, the new Commit Message
    767 	 * shall be dropped if the peer-scalar is identical to the one used in
    768 	 * the existing protocol instance.
    769 	 */
    770 	if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar &&
    771 	    crypto_bignum_cmp(sae->peer_commit_scalar, peer_scalar) == 0) {
    772 		wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous "
    773 			   "peer-commit-scalar");
    774 		crypto_bignum_deinit(peer_scalar, 0);
    775 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    776 	}
    777 
    778 	/* 0 < scalar < r */
    779 	if (crypto_bignum_is_zero(peer_scalar) ||
    780 	    crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) {
    781 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar");
    782 		crypto_bignum_deinit(peer_scalar, 0);
    783 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    784 	}
    785 
    786 
    787 	crypto_bignum_deinit(sae->peer_commit_scalar, 0);
    788 	sae->peer_commit_scalar = peer_scalar;
    789 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar",
    790 		    *pos, sae->tmp->prime_len);
    791 	*pos += sae->tmp->prime_len;
    792 
    793 	return WLAN_STATUS_SUCCESS;
    794 }
    795 
    796 
    797 static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 *pos,
    798 					const u8 *end)
    799 {
    800 	u8 prime[SAE_MAX_ECC_PRIME_LEN];
    801 
    802 	if (pos + 2 * sae->tmp->prime_len > end) {
    803 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
    804 			   "commit-element");
    805 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    806 	}
    807 
    808 	if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
    809 				 sae->tmp->prime_len) < 0)
    810 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    811 
    812 	/* element x and y coordinates < p */
    813 	if (os_memcmp(pos, prime, sae->tmp->prime_len) >= 0 ||
    814 	    os_memcmp(pos + sae->tmp->prime_len, prime,
    815 		      sae->tmp->prime_len) >= 0) {
    816 		wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer "
    817 			   "element");
    818 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    819 	}
    820 
    821 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)",
    822 		    pos, sae->tmp->prime_len);
    823 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)",
    824 		    pos + sae->tmp->prime_len, sae->tmp->prime_len);
    825 
    826 	crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0);
    827 	sae->tmp->peer_commit_element_ecc =
    828 		crypto_ec_point_from_bin(sae->tmp->ec, pos);
    829 	if (sae->tmp->peer_commit_element_ecc == NULL)
    830 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    831 
    832 	if (!crypto_ec_point_is_on_curve(sae->tmp->ec,
    833 					 sae->tmp->peer_commit_element_ecc)) {
    834 		wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve");
    835 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    836 	}
    837 
    838 	return WLAN_STATUS_SUCCESS;
    839 }
    840 
    841 
    842 static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 *pos,
    843 					const u8 *end)
    844 {
    845 	struct crypto_bignum *res;
    846 
    847 	if (pos + sae->tmp->prime_len > end) {
    848 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
    849 			   "commit-element");
    850 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    851 	}
    852 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", pos,
    853 		    sae->tmp->prime_len);
    854 
    855 	crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0);
    856 	sae->tmp->peer_commit_element_ffc =
    857 		crypto_bignum_init_set(pos, sae->tmp->prime_len);
    858 	if (sae->tmp->peer_commit_element_ffc == NULL)
    859 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    860 	if (crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) ||
    861 	    crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) ||
    862 	    crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc,
    863 			      sae->tmp->prime) >= 0) {
    864 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer element");
    865 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    866 	}
    867 
    868 	/* scalar-op(r, ELEMENT) = 1 modulo p */
    869 	res = crypto_bignum_init();
    870 	if (res == NULL ||
    871 	    crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc,
    872 				  sae->tmp->order, sae->tmp->prime, res) < 0 ||
    873 	    !crypto_bignum_is_one(res)) {
    874 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer element (scalar-op)");
    875 		crypto_bignum_deinit(res, 0);
    876 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    877 	}
    878 	crypto_bignum_deinit(res, 0);
    879 
    880 	return WLAN_STATUS_SUCCESS;
    881 }
    882 
    883 
    884 static u16 sae_parse_commit_element(struct sae_data *sae, const u8 *pos,
    885 				    const u8 *end)
    886 {
    887 	if (sae->tmp->dh)
    888 		return sae_parse_commit_element_ffc(sae, pos, end);
    889 	return sae_parse_commit_element_ecc(sae, pos, end);
    890 }
    891 
    892 
    893 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
    894 		     const u8 **token, size_t *token_len, int *allowed_groups)
    895 {
    896 	const u8 *pos = data, *end = data + len;
    897 	u16 res;
    898 
    899 	/* Check Finite Cyclic Group */
    900 	if (pos + 2 > end)
    901 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
    902 	res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos));
    903 	if (res != WLAN_STATUS_SUCCESS)
    904 		return res;
    905 	pos += 2;
    906 
    907 	/* Optional Anti-Clogging Token */
    908 	sae_parse_commit_token(sae, &pos, end, token, token_len);
    909 
    910 	/* commit-scalar */
    911 	res = sae_parse_commit_scalar(sae, &pos, end);
    912 	if (res != WLAN_STATUS_SUCCESS)
    913 		return res;
    914 
    915 	/* commit-element */
    916 	return sae_parse_commit_element(sae, pos, end);
    917 }
    918 
    919 
    920 static void sae_cn_confirm(struct sae_data *sae, const u8 *sc,
    921 			   const struct crypto_bignum *scalar1,
    922 			   const u8 *element1, size_t element1_len,
    923 			   const struct crypto_bignum *scalar2,
    924 			   const u8 *element2, size_t element2_len,
    925 			   u8 *confirm)
    926 {
    927 	const u8 *addr[5];
    928 	size_t len[5];
    929 	u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN];
    930 
    931 	/* Confirm
    932 	 * CN(key, X, Y, Z, ...) =
    933 	 *    HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...)
    934 	 * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT,
    935 	 *              peer-commit-scalar, PEER-COMMIT-ELEMENT)
    936 	 * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar,
    937 	 *               PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT)
    938 	 */
    939 	addr[0] = sc;
    940 	len[0] = 2;
    941 	crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1),
    942 			     sae->tmp->prime_len);
    943 	addr[1] = scalar_b1;
    944 	len[1] = sae->tmp->prime_len;
    945 	addr[2] = element1;
    946 	len[2] = element1_len;
    947 	crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2),
    948 			     sae->tmp->prime_len);
    949 	addr[3] = scalar_b2;
    950 	len[3] = sae->tmp->prime_len;
    951 	addr[4] = element2;
    952 	len[4] = element2_len;
    953 	hmac_sha256_vector(sae->tmp->kck, sizeof(sae->tmp->kck), 5, addr, len,
    954 			   confirm);
    955 }
    956 
    957 
    958 static void sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
    959 			       const struct crypto_bignum *scalar1,
    960 			       const struct crypto_ec_point *element1,
    961 			       const struct crypto_bignum *scalar2,
    962 			       const struct crypto_ec_point *element2,
    963 			       u8 *confirm)
    964 {
    965 	u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN];
    966 	u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN];
    967 
    968 	crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1,
    969 			       element_b1 + sae->tmp->prime_len);
    970 	crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2,
    971 			       element_b2 + sae->tmp->prime_len);
    972 
    973 	sae_cn_confirm(sae, sc, scalar1, element_b1, 2 * sae->tmp->prime_len,
    974 		       scalar2, element_b2, 2 * sae->tmp->prime_len, confirm);
    975 }
    976 
    977 
    978 static void sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
    979 			       const struct crypto_bignum *scalar1,
    980 			       const struct crypto_bignum *element1,
    981 			       const struct crypto_bignum *scalar2,
    982 			       const struct crypto_bignum *element2,
    983 			       u8 *confirm)
    984 {
    985 	u8 element_b1[SAE_MAX_PRIME_LEN];
    986 	u8 element_b2[SAE_MAX_PRIME_LEN];
    987 
    988 	crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1),
    989 			     sae->tmp->prime_len);
    990 	crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2),
    991 			     sae->tmp->prime_len);
    992 
    993 	sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len,
    994 		       scalar2, element_b2, sae->tmp->prime_len, confirm);
    995 }
    996 
    997 
    998 void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
    999 {
   1000 	const u8 *sc;
   1001 
   1002 	if (sae->tmp == NULL)
   1003 		return;
   1004 
   1005 	/* Send-Confirm */
   1006 	sc = wpabuf_put(buf, 0);
   1007 	wpabuf_put_le16(buf, sae->send_confirm);
   1008 	sae->send_confirm++;
   1009 
   1010 	if (sae->tmp->ec)
   1011 		sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
   1012 				   sae->tmp->own_commit_element_ecc,
   1013 				   sae->peer_commit_scalar,
   1014 				   sae->tmp->peer_commit_element_ecc,
   1015 				   wpabuf_put(buf, SHA256_MAC_LEN));
   1016 	else
   1017 		sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar,
   1018 				   sae->tmp->own_commit_element_ffc,
   1019 				   sae->peer_commit_scalar,
   1020 				   sae->tmp->peer_commit_element_ffc,
   1021 				   wpabuf_put(buf, SHA256_MAC_LEN));
   1022 }
   1023 
   1024 
   1025 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
   1026 {
   1027 	u8 verifier[SHA256_MAC_LEN];
   1028 
   1029 	if (len < 2 + SHA256_MAC_LEN) {
   1030 		wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
   1031 		return -1;
   1032 	}
   1033 
   1034 	wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data));
   1035 
   1036 	if (sae->tmp == NULL) {
   1037 		wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available");
   1038 		return -1;
   1039 	}
   1040 
   1041 	if (sae->tmp->ec)
   1042 		sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar,
   1043 				   sae->tmp->peer_commit_element_ecc,
   1044 				   sae->tmp->own_commit_scalar,
   1045 				   sae->tmp->own_commit_element_ecc,
   1046 				   verifier);
   1047 	else
   1048 		sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar,
   1049 				   sae->tmp->peer_commit_element_ffc,
   1050 				   sae->tmp->own_commit_scalar,
   1051 				   sae->tmp->own_commit_element_ffc,
   1052 				   verifier);
   1053 
   1054 	if (os_memcmp_const(verifier, data + 2, SHA256_MAC_LEN) != 0) {
   1055 		wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
   1056 		wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
   1057 			    data + 2, SHA256_MAC_LEN);
   1058 		wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
   1059 			    verifier, SHA256_MAC_LEN);
   1060 		return -1;
   1061 	}
   1062 
   1063 	return 0;
   1064 }
   1065