• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
sae_set_group(struct sae_data * sae,int group)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 
sae_clear_temp_data(struct sae_data * sae)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 
sae_clear_data(struct sae_data * sae)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 
buf_shift_right(u8 * buf,size_t len,size_t bits)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 
sae_get_rand(struct sae_data * sae)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 
sae_get_rand_and_mask(struct sae_data * sae)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 
sae_pwd_seed_key(const u8 * addr1,const u8 * addr2,u8 * key)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 
sae_test_pwd_seed_ecc(struct sae_data * sae,const u8 * pwd_seed,struct crypto_ec_point * pwe)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 
sae_test_pwd_seed_ffc(struct sae_data * sae,const u8 * pwd_seed,struct crypto_bignum * pwe)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 
sae_derive_pwe_ecc(struct sae_data * sae,const u8 * addr1,const u8 * addr2,const u8 * password,size_t password_len)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 
sae_derive_pwe_ffc(struct sae_data * sae,const u8 * addr1,const u8 * addr2,const u8 * password,size_t password_len)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 
sae_derive_commit_element_ecc(struct sae_data * sae,struct crypto_bignum * mask)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 
sae_derive_commit_element_ffc(struct sae_data * sae,struct crypto_bignum * mask)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 
sae_derive_commit(struct sae_data * sae)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 
sae_prepare_commit(const u8 * addr1,const u8 * addr2,const u8 * password,size_t password_len,struct sae_data * sae)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 
sae_derive_k_ecc(struct sae_data * sae,u8 * k)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 
sae_derive_k_ffc(struct sae_data * sae,u8 * k)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 
sae_derive_keys(struct sae_data * sae,const u8 * k)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 
sae_process_commit(struct sae_data * sae)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 
sae_write_commit(struct sae_data * sae,struct wpabuf * buf,const struct wpabuf * token)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 
sae_group_allowed(struct sae_data * sae,int * allowed_groups,u16 group)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 
sae_parse_commit_token(struct sae_data * sae,const u8 ** pos,const u8 * end,const u8 ** token,size_t * token_len)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 
sae_parse_commit_scalar(struct sae_data * sae,const u8 ** pos,const u8 * end)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 
sae_parse_commit_element_ecc(struct sae_data * sae,const u8 * pos,const u8 * end)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 
sae_parse_commit_element_ffc(struct sae_data * sae,const u8 * pos,const u8 * end)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 
sae_parse_commit_element(struct sae_data * sae,const u8 * pos,const u8 * end)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 
sae_parse_commit(struct sae_data * sae,const u8 * data,size_t len,const u8 ** token,size_t * token_len,int * allowed_groups)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 
sae_cn_confirm(struct sae_data * sae,const u8 * sc,const struct crypto_bignum * scalar1,const u8 * element1,size_t element1_len,const struct crypto_bignum * scalar2,const u8 * element2,size_t element2_len,u8 * confirm)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 
sae_cn_confirm_ecc(struct sae_data * sae,const u8 * sc,const struct crypto_bignum * scalar1,const struct crypto_ec_point * element1,const struct crypto_bignum * scalar2,const struct crypto_ec_point * element2,u8 * confirm)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 
sae_cn_confirm_ffc(struct sae_data * sae,const u8 * sc,const struct crypto_bignum * scalar1,const struct crypto_bignum * element1,const struct crypto_bignum * scalar2,const struct crypto_bignum * element2,u8 * confirm)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 
sae_write_confirm(struct sae_data * sae,struct wpabuf * buf)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 
sae_check_confirm(struct sae_data * sae,const u8 * data,size_t len)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