1 /*
2  * Simultaneous authentication of equals
3  * Copyright (c) 2012-2013, Jouni Malinen <j@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 == NULL) {
705 		wpa_printf(MSG_DEBUG, "SAE: Group information not yet initialized");
706 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
707 	}
708 
709 	if (sae->tmp->dh && !allowed_groups) {
710 		wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without "
711 			   "explicit configuration enabling it", group);
712 		return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
713 	}
714 
715 	return WLAN_STATUS_SUCCESS;
716 }
717 
718 
719 static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
720 				   const u8 *end, const u8 **token,
721 				   size_t *token_len)
722 {
723 	if (*pos + (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len < end) {
724 		size_t tlen = end - (*pos + (sae->tmp->ec ? 3 : 2) *
725 				     sae->tmp->prime_len);
726 		wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
727 		if (token)
728 			*token = *pos;
729 		if (token_len)
730 			*token_len = tlen;
731 		*pos += tlen;
732 	} else {
733 		if (token)
734 			*token = NULL;
735 		if (token_len)
736 			*token_len = 0;
737 	}
738 }
739 
740 
741 static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos,
742 				   const u8 *end)
743 {
744 	struct crypto_bignum *peer_scalar;
745 
746 	if (*pos + sae->tmp->prime_len > end) {
747 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar");
748 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
749 	}
750 
751 	peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len);
752 	if (peer_scalar == NULL)
753 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
754 
755 	/*
756 	 * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for
757 	 * the peer and it is in Authenticated state, the new Commit Message
758 	 * shall be dropped if the peer-scalar is identical to the one used in
759 	 * the existing protocol instance.
760 	 */
761 	if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar &&
762 	    crypto_bignum_cmp(sae->peer_commit_scalar, peer_scalar) == 0) {
763 		wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous "
764 			   "peer-commit-scalar");
765 		crypto_bignum_deinit(peer_scalar, 0);
766 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
767 	}
768 
769 	/* 0 < scalar < r */
770 	if (crypto_bignum_is_zero(peer_scalar) ||
771 	    crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) {
772 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar");
773 		crypto_bignum_deinit(peer_scalar, 0);
774 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
775 	}
776 
777 
778 	crypto_bignum_deinit(sae->peer_commit_scalar, 0);
779 	sae->peer_commit_scalar = peer_scalar;
780 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar",
781 		    *pos, sae->tmp->prime_len);
782 	*pos += sae->tmp->prime_len;
783 
784 	return WLAN_STATUS_SUCCESS;
785 }
786 
787 
788 static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 *pos,
789 					const u8 *end)
790 {
791 	u8 prime[SAE_MAX_ECC_PRIME_LEN];
792 
793 	if (pos + 2 * sae->tmp->prime_len > end) {
794 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
795 			   "commit-element");
796 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
797 	}
798 
799 	if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
800 				 sae->tmp->prime_len) < 0)
801 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
802 
803 	/* element x and y coordinates < p */
804 	if (os_memcmp(pos, prime, sae->tmp->prime_len) >= 0 ||
805 	    os_memcmp(pos + sae->tmp->prime_len, prime,
806 		      sae->tmp->prime_len) >= 0) {
807 		wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer "
808 			   "element");
809 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
810 	}
811 
812 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)",
813 		    pos, sae->tmp->prime_len);
814 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)",
815 		    pos + sae->tmp->prime_len, sae->tmp->prime_len);
816 
817 	crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0);
818 	sae->tmp->peer_commit_element_ecc =
819 		crypto_ec_point_from_bin(sae->tmp->ec, pos);
820 	if (sae->tmp->peer_commit_element_ecc == NULL)
821 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
822 
823 	if (!crypto_ec_point_is_on_curve(sae->tmp->ec,
824 					 sae->tmp->peer_commit_element_ecc)) {
825 		wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve");
826 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
827 	}
828 
829 	return WLAN_STATUS_SUCCESS;
830 }
831 
832 
833 static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 *pos,
834 					const u8 *end)
835 {
836 	struct crypto_bignum *res;
837 
838 	if (pos + sae->tmp->prime_len > end) {
839 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
840 			   "commit-element");
841 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
842 	}
843 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", pos,
844 		    sae->tmp->prime_len);
845 
846 	crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0);
847 	sae->tmp->peer_commit_element_ffc =
848 		crypto_bignum_init_set(pos, sae->tmp->prime_len);
849 	if (sae->tmp->peer_commit_element_ffc == NULL)
850 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
851 	if (crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) ||
852 	    crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) ||
853 	    crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc,
854 			      sae->tmp->prime) >= 0) {
855 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer element");
856 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
857 	}
858 
859 	/* scalar-op(r, ELEMENT) = 1 modulo p */
860 	res = crypto_bignum_init();
861 	if (res == NULL ||
862 	    crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc,
863 				  sae->tmp->order, sae->tmp->prime, res) < 0 ||
864 	    !crypto_bignum_is_one(res)) {
865 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer element (scalar-op)");
866 		crypto_bignum_deinit(res, 0);
867 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
868 	}
869 	crypto_bignum_deinit(res, 0);
870 
871 	return WLAN_STATUS_SUCCESS;
872 }
873 
874 
875 static u16 sae_parse_commit_element(struct sae_data *sae, const u8 *pos,
876 				    const u8 *end)
877 {
878 	if (sae->tmp->dh)
879 		return sae_parse_commit_element_ffc(sae, pos, end);
880 	return sae_parse_commit_element_ecc(sae, pos, end);
881 }
882 
883 
884 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
885 		     const u8 **token, size_t *token_len, int *allowed_groups)
886 {
887 	const u8 *pos = data, *end = data + len;
888 	u16 res;
889 
890 	/* Check Finite Cyclic Group */
891 	if (pos + 2 > end)
892 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
893 	res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos));
894 	if (res != WLAN_STATUS_SUCCESS)
895 		return res;
896 	pos += 2;
897 
898 	/* Optional Anti-Clogging Token */
899 	sae_parse_commit_token(sae, &pos, end, token, token_len);
900 
901 	/* commit-scalar */
902 	res = sae_parse_commit_scalar(sae, &pos, end);
903 	if (res != WLAN_STATUS_SUCCESS)
904 		return res;
905 
906 	/* commit-element */
907 	return sae_parse_commit_element(sae, pos, end);
908 }
909 
910 
911 static void sae_cn_confirm(struct sae_data *sae, const u8 *sc,
912 			   const struct crypto_bignum *scalar1,
913 			   const u8 *element1, size_t element1_len,
914 			   const struct crypto_bignum *scalar2,
915 			   const u8 *element2, size_t element2_len,
916 			   u8 *confirm)
917 {
918 	const u8 *addr[5];
919 	size_t len[5];
920 	u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN];
921 
922 	/* Confirm
923 	 * CN(key, X, Y, Z, ...) =
924 	 *    HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...)
925 	 * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT,
926 	 *              peer-commit-scalar, PEER-COMMIT-ELEMENT)
927 	 * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar,
928 	 *               PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT)
929 	 */
930 	addr[0] = sc;
931 	len[0] = 2;
932 	crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1),
933 			     sae->tmp->prime_len);
934 	addr[1] = scalar_b1;
935 	len[1] = sae->tmp->prime_len;
936 	addr[2] = element1;
937 	len[2] = element1_len;
938 	crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2),
939 			     sae->tmp->prime_len);
940 	addr[3] = scalar_b2;
941 	len[3] = sae->tmp->prime_len;
942 	addr[4] = element2;
943 	len[4] = element2_len;
944 	hmac_sha256_vector(sae->tmp->kck, sizeof(sae->tmp->kck), 5, addr, len,
945 			   confirm);
946 }
947 
948 
949 static void sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
950 			       const struct crypto_bignum *scalar1,
951 			       const struct crypto_ec_point *element1,
952 			       const struct crypto_bignum *scalar2,
953 			       const struct crypto_ec_point *element2,
954 			       u8 *confirm)
955 {
956 	u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN];
957 	u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN];
958 
959 	crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1,
960 			       element_b1 + sae->tmp->prime_len);
961 	crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2,
962 			       element_b2 + sae->tmp->prime_len);
963 
964 	sae_cn_confirm(sae, sc, scalar1, element_b1, 2 * sae->tmp->prime_len,
965 		       scalar2, element_b2, 2 * sae->tmp->prime_len, confirm);
966 }
967 
968 
969 static void sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
970 			       const struct crypto_bignum *scalar1,
971 			       const struct crypto_bignum *element1,
972 			       const struct crypto_bignum *scalar2,
973 			       const struct crypto_bignum *element2,
974 			       u8 *confirm)
975 {
976 	u8 element_b1[SAE_MAX_PRIME_LEN];
977 	u8 element_b2[SAE_MAX_PRIME_LEN];
978 
979 	crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1),
980 			     sae->tmp->prime_len);
981 	crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2),
982 			     sae->tmp->prime_len);
983 
984 	sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len,
985 		       scalar2, element_b2, sae->tmp->prime_len, confirm);
986 }
987 
988 
989 void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
990 {
991 	const u8 *sc;
992 
993 	/* Send-Confirm */
994 	sc = wpabuf_put(buf, 0);
995 	wpabuf_put_le16(buf, sae->send_confirm);
996 	sae->send_confirm++;
997 
998 	if (sae->tmp->ec)
999 		sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
1000 				   sae->tmp->own_commit_element_ecc,
1001 				   sae->peer_commit_scalar,
1002 				   sae->tmp->peer_commit_element_ecc,
1003 				   wpabuf_put(buf, SHA256_MAC_LEN));
1004 	else
1005 		sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar,
1006 				   sae->tmp->own_commit_element_ffc,
1007 				   sae->peer_commit_scalar,
1008 				   sae->tmp->peer_commit_element_ffc,
1009 				   wpabuf_put(buf, SHA256_MAC_LEN));
1010 }
1011 
1012 
1013 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
1014 {
1015 	u8 verifier[SHA256_MAC_LEN];
1016 
1017 	if (len < 2 + SHA256_MAC_LEN) {
1018 		wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
1019 		return -1;
1020 	}
1021 
1022 	wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data));
1023 
1024 	if (sae->tmp->ec)
1025 		sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar,
1026 				   sae->tmp->peer_commit_element_ecc,
1027 				   sae->tmp->own_commit_scalar,
1028 				   sae->tmp->own_commit_element_ecc,
1029 				   verifier);
1030 	else
1031 		sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar,
1032 				   sae->tmp->peer_commit_element_ffc,
1033 				   sae->tmp->own_commit_scalar,
1034 				   sae->tmp->own_commit_element_ffc,
1035 				   verifier);
1036 
1037 	if (os_memcmp(verifier, data + 2, SHA256_MAC_LEN) != 0) {
1038 		wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
1039 		wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
1040 			    data + 2, SHA256_MAC_LEN);
1041 		wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
1042 			    verifier, SHA256_MAC_LEN);
1043 		return -1;
1044 	}
1045 
1046 	return 0;
1047 }
1048