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