xref: /freebsd/contrib/wpa/src/common/sae.c (revision 71e72c9e91c4b8007a4292e09669e8b549c29e97)
1 /*
2  * Simultaneous authentication of equals
3  * Copyright (c) 2012-2016, 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 "common/defs.h"
13 #include "common/wpa_common.h"
14 #include "utils/const_time.h"
15 #include "crypto/crypto.h"
16 #include "crypto/sha256.h"
17 #include "crypto/sha384.h"
18 #include "crypto/sha512.h"
19 #include "crypto/random.h"
20 #include "crypto/dh_groups.h"
21 #include "ieee802_11_defs.h"
22 #include "dragonfly.h"
23 #include "sae.h"
24 
25 
sae_set_group(struct sae_data * sae,int group)26 int sae_set_group(struct sae_data *sae, int group)
27 {
28 	struct sae_temporary_data *tmp;
29 
30 #ifdef CONFIG_TESTING_OPTIONS
31 	/* Allow all groups for testing purposes in non-production builds. */
32 #else /* CONFIG_TESTING_OPTIONS */
33 	if (!dragonfly_suitable_group(group, 0)) {
34 		wpa_printf(MSG_DEBUG, "SAE: Reject unsuitable group %d", group);
35 		return -1;
36 	}
37 #endif /* CONFIG_TESTING_OPTIONS */
38 
39 	sae_clear_data(sae);
40 	tmp = sae->tmp = os_zalloc(sizeof(*tmp));
41 	if (tmp == NULL)
42 		return -1;
43 
44 	/* First, check if this is an ECC group */
45 	tmp->ec = crypto_ec_init(group);
46 	if (tmp->ec) {
47 		wpa_printf(MSG_DEBUG, "SAE: Selecting supported ECC group %d",
48 			   group);
49 		sae->group = group;
50 		tmp->prime_len = crypto_ec_prime_len(tmp->ec);
51 		tmp->prime = crypto_ec_get_prime(tmp->ec);
52 		tmp->order_len = crypto_ec_order_len(tmp->ec);
53 		tmp->order = crypto_ec_get_order(tmp->ec);
54 		return 0;
55 	}
56 
57 	/* Not an ECC group, check FFC */
58 	tmp->dh = dh_groups_get(group);
59 	if (tmp->dh) {
60 		wpa_printf(MSG_DEBUG, "SAE: Selecting supported FFC group %d",
61 			   group);
62 		sae->group = group;
63 		tmp->prime_len = tmp->dh->prime_len;
64 		if (tmp->prime_len > SAE_MAX_PRIME_LEN) {
65 			sae_clear_data(sae);
66 			return -1;
67 		}
68 
69 		tmp->prime_buf = crypto_bignum_init_set(tmp->dh->prime,
70 							tmp->prime_len);
71 		if (tmp->prime_buf == NULL) {
72 			sae_clear_data(sae);
73 			return -1;
74 		}
75 		tmp->prime = tmp->prime_buf;
76 
77 		tmp->order_len = tmp->dh->order_len;
78 		tmp->order_buf = crypto_bignum_init_set(tmp->dh->order,
79 							tmp->dh->order_len);
80 		if (tmp->order_buf == NULL) {
81 			sae_clear_data(sae);
82 			return -1;
83 		}
84 		tmp->order = tmp->order_buf;
85 
86 		return 0;
87 	}
88 
89 	/* Unsupported group */
90 	wpa_printf(MSG_DEBUG,
91 		   "SAE: Group %d not supported by the crypto library", group);
92 	return -1;
93 }
94 
95 
sae_clear_temp_data(struct sae_data * sae)96 void sae_clear_temp_data(struct sae_data *sae)
97 {
98 	struct sae_temporary_data *tmp;
99 	if (sae == NULL || sae->tmp == NULL)
100 		return;
101 	tmp = sae->tmp;
102 	crypto_ec_deinit(tmp->ec);
103 	crypto_bignum_deinit(tmp->prime_buf, 0);
104 	crypto_bignum_deinit(tmp->order_buf, 0);
105 	crypto_bignum_deinit(tmp->sae_rand, 1);
106 	crypto_bignum_deinit(tmp->pwe_ffc, 1);
107 	crypto_bignum_deinit(tmp->own_commit_scalar, 0);
108 	crypto_bignum_deinit(tmp->own_commit_element_ffc, 0);
109 	crypto_bignum_deinit(tmp->peer_commit_element_ffc, 0);
110 	crypto_ec_point_deinit(tmp->pwe_ecc, 1);
111 	crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0);
112 	crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0);
113 	wpabuf_free(tmp->anti_clogging_token);
114 	wpabuf_free(tmp->own_rejected_groups);
115 	wpabuf_free(tmp->peer_rejected_groups);
116 	os_free(tmp->pw_id);
117 	os_free(tmp->parsed_pw_id);
118 	os_free(tmp->dec_pw_id);
119 	bin_clear_free(tmp, sizeof(*tmp));
120 	sae->tmp = NULL;
121 }
122 
123 
sae_clear_data(struct sae_data * sae)124 void sae_clear_data(struct sae_data *sae)
125 {
126 	unsigned int no_pw_id;
127 
128 	if (sae == NULL)
129 		return;
130 	sae_clear_temp_data(sae);
131 	crypto_bignum_deinit(sae->peer_commit_scalar, 0);
132 	crypto_bignum_deinit(sae->peer_commit_scalar_accepted, 0);
133 	no_pw_id = sae->no_pw_id;
134 	os_memset(sae, 0, sizeof(*sae));
135 	sae->no_pw_id = no_pw_id;
136 }
137 
138 
sae_pwd_seed_key(const u8 * addr1,const u8 * addr2,u8 * key)139 static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key)
140 {
141 	wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR
142 		   " addr2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2));
143 	if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) {
144 		os_memcpy(key, addr1, ETH_ALEN);
145 		os_memcpy(key + ETH_ALEN, addr2, ETH_ALEN);
146 	} else {
147 		os_memcpy(key, addr2, ETH_ALEN);
148 		os_memcpy(key + ETH_ALEN, addr1, ETH_ALEN);
149 	}
150 }
151 
152 
sae_test_pwd_seed_ecc(struct sae_data * sae,const u8 * pwd_seed,const u8 * prime,const u8 * qr,const u8 * qnr,u8 * pwd_value)153 static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
154 				 const u8 *prime, const u8 *qr, const u8 *qnr,
155 				 u8 *pwd_value)
156 {
157 	struct crypto_bignum *y_sqr, *x_cand;
158 	int res;
159 	size_t bits;
160 	int cmp_prime;
161 	unsigned int in_range;
162 
163 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
164 
165 	/* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
166 	bits = crypto_ec_prime_len_bits(sae->tmp->ec);
167 	if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
168 			    prime, sae->tmp->prime_len, pwd_value, bits) < 0)
169 		return -1;
170 	if (bits % 8)
171 		buf_shift_right(pwd_value, sae->tmp->prime_len, 8 - bits % 8);
172 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
173 			pwd_value, sae->tmp->prime_len);
174 
175 	cmp_prime = const_time_memcmp(pwd_value, prime, sae->tmp->prime_len);
176 	/* Create a const_time mask for selection based on prf result
177 	 * being smaller than prime. */
178 	in_range = const_time_fill_msb((unsigned int) cmp_prime);
179 	/* The algorithm description would skip the next steps if
180 	 * cmp_prime >= 0 (return 0 here), but go through them regardless to
181 	 * minimize externally observable differences in behavior. */
182 
183 	x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
184 	if (!x_cand)
185 		return -1;
186 	y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand);
187 	crypto_bignum_deinit(x_cand, 1);
188 	if (!y_sqr)
189 		return -1;
190 
191 	res = dragonfly_is_quadratic_residue_blind(sae->tmp->ec, qr, qnr,
192 						   y_sqr);
193 	crypto_bignum_deinit(y_sqr, 1);
194 	if (res < 0)
195 		return res;
196 	return const_time_select_int(in_range, res, 0);
197 }
198 
199 
200 /* Returns -1 on fatal failure, 0 if PWE cannot be derived from the provided
201  * pwd-seed, or 1 if a valid PWE was derived from pwd-seed. */
sae_test_pwd_seed_ffc(struct sae_data * sae,const u8 * pwd_seed,struct crypto_bignum * pwe)202 static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
203 				 struct crypto_bignum *pwe)
204 {
205 	u8 pwd_value[SAE_MAX_PRIME_LEN];
206 	size_t bits = sae->tmp->prime_len * 8;
207 	u8 exp[1];
208 	struct crypto_bignum *a, *b = NULL;
209 	int res, is_val;
210 	u8 pwd_value_valid;
211 
212 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
213 
214 	/* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
215 	if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
216 			    sae->tmp->dh->prime, sae->tmp->prime_len, pwd_value,
217 			    bits) < 0)
218 		return -1;
219 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value,
220 			sae->tmp->prime_len);
221 
222 	/* Check whether pwd-value < p */
223 	res = const_time_memcmp(pwd_value, sae->tmp->dh->prime,
224 				sae->tmp->prime_len);
225 	/* pwd-value >= p is invalid, so res is < 0 for the valid cases and
226 	 * the negative sign can be used to fill the mask for constant time
227 	 * selection */
228 	pwd_value_valid = const_time_fill_msb(res);
229 
230 	/* If pwd-value >= p, force pwd-value to be < p and perform the
231 	 * calculations anyway to hide timing difference. The derived PWE will
232 	 * be ignored in that case. */
233 	pwd_value[0] = const_time_select_u8(pwd_value_valid, pwd_value[0], 0);
234 
235 	/* PWE = pwd-value^((p-1)/r) modulo p */
236 
237 	res = -1;
238 	a = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
239 	if (!a)
240 		goto fail;
241 
242 	/* This is an optimization based on the used group that does not depend
243 	 * on the password in any way, so it is fine to use separate branches
244 	 * for this step without constant time operations. */
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 			goto fail;
260 	}
261 
262 	if (!b)
263 		goto fail;
264 
265 	res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe);
266 	if (res < 0)
267 		goto fail;
268 
269 	/* There were no fatal errors in calculations, so determine the return
270 	 * value using constant time operations. We get here for number of
271 	 * invalid cases which are cleared here after having performed all the
272 	 * computation. PWE is valid if pwd-value was less than prime and
273 	 * PWE > 1. Start with pwd-value check first and then use constant time
274 	 * operations to clear res to 0 if PWE is 0 or 1.
275 	 */
276 	res = const_time_select_u8(pwd_value_valid, 1, 0);
277 	is_val = crypto_bignum_is_zero(pwe);
278 	res = const_time_select_u8(const_time_is_zero(is_val), res, 0);
279 	is_val = crypto_bignum_is_one(pwe);
280 	res = const_time_select_u8(const_time_is_zero(is_val), res, 0);
281 
282 fail:
283 	crypto_bignum_deinit(a, 1);
284 	crypto_bignum_deinit(b, 1);
285 	return res;
286 }
287 
288 
sae_derive_pwe_ecc(struct sae_data * sae,const u8 * addr1,const u8 * addr2,const u8 * password,size_t password_len)289 static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
290 			      const u8 *addr2, const u8 *password,
291 			      size_t password_len)
292 {
293 	u8 counter, k;
294 	u8 addrs[2 * ETH_ALEN];
295 	const u8 *addr[2];
296 	size_t len[2];
297 	u8 *stub_password, *tmp_password;
298 	int pwd_seed_odd = 0;
299 	u8 prime[SAE_MAX_ECC_PRIME_LEN];
300 	size_t prime_len;
301 	struct crypto_bignum *x = NULL, *y = NULL, *qr = NULL, *qnr = NULL;
302 	u8 x_bin[SAE_MAX_ECC_PRIME_LEN];
303 	u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN];
304 	u8 qr_bin[SAE_MAX_ECC_PRIME_LEN];
305 	u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN];
306 	u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN];
307 	int res = -1;
308 	u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
309 		       * mask */
310 	unsigned int is_eq;
311 
312 	os_memset(x_bin, 0, sizeof(x_bin));
313 
314 	stub_password = os_malloc(password_len);
315 	tmp_password = os_malloc(password_len);
316 	if (!stub_password || !tmp_password ||
317 	    random_get_bytes(stub_password, password_len) < 0)
318 		goto fail;
319 
320 	prime_len = sae->tmp->prime_len;
321 	if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
322 				 prime_len) < 0)
323 		goto fail;
324 
325 	/*
326 	 * Create a random quadratic residue (qr) and quadratic non-residue
327 	 * (qnr) modulo p for blinding purposes during the loop.
328 	 */
329 	if (dragonfly_get_random_qr_qnr(sae->tmp->prime, &qr, &qnr) < 0 ||
330 	    crypto_bignum_to_bin(qr, qr_bin, sizeof(qr_bin), prime_len) < 0 ||
331 	    crypto_bignum_to_bin(qnr, qnr_bin, sizeof(qnr_bin), prime_len) < 0)
332 		goto fail;
333 
334 	wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
335 			      password, password_len);
336 
337 	/*
338 	 * H(salt, ikm) = HMAC-SHA256(salt, ikm)
339 	 * base = password
340 	 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
341 	 *              base || counter)
342 	 */
343 	sae_pwd_seed_key(addr1, addr2, addrs);
344 
345 	addr[0] = tmp_password;
346 	len[0] = password_len;
347 	addr[1] = &counter;
348 	len[1] = sizeof(counter);
349 
350 	/*
351 	 * Continue for at least k iterations to protect against side-channel
352 	 * attacks that attempt to determine the number of iterations required
353 	 * in the loop.
354 	 */
355 	k = dragonfly_min_pwe_loop_iter(sae->group);
356 
357 	for (counter = 1; counter <= k || !found; counter++) {
358 		u8 pwd_seed[SHA256_MAC_LEN];
359 
360 		if (counter > 200) {
361 			/* This should not happen in practice */
362 			wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
363 			break;
364 		}
365 
366 		wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter);
367 		const_time_select_bin(found, stub_password, password,
368 				      password_len, tmp_password);
369 		if (hmac_sha256_vector(addrs, sizeof(addrs), 2,
370 				       addr, len, pwd_seed) < 0) {
371 			wpa_printf(MSG_INFO,
372 				   "SAE: hmac_sha256_vector() failed - cannot derive PWE");
373 			break;
374 		}
375 
376 		res = sae_test_pwd_seed_ecc(sae, pwd_seed,
377 					    prime, qr_bin, qnr_bin, x_cand_bin);
378 		const_time_select_bin(found, x_bin, x_cand_bin, prime_len,
379 				      x_bin);
380 		pwd_seed_odd = const_time_select_u8(
381 			found, pwd_seed_odd,
382 			pwd_seed[SHA256_MAC_LEN - 1] & 0x01);
383 		os_memset(pwd_seed, 0, sizeof(pwd_seed));
384 		if (res < 0)
385 			goto fail;
386 		/* Need to minimize differences in handling res == 0 and 1 here
387 		 * to avoid differences in timing and instruction cache access,
388 		 * so use const_time_select_*() to make local copies of the
389 		 * values based on whether this loop iteration was the one that
390 		 * found the pwd-seed/x. */
391 
392 		/* found is 0 or 0xff here and res is 0 or 1. Bitwise OR of them
393 		 * (with res converted to 0/0xff) handles this in constant time.
394 		 */
395 		found |= res * 0xff;
396 		wpa_printf(MSG_DEBUG, "SAE: pwd-seed result %d found=0x%02x",
397 			   res, found);
398 	}
399 
400 	if (!found) {
401 		wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
402 		res = -1;
403 		goto fail;
404 	}
405 
406 	x = crypto_bignum_init_set(x_bin, prime_len);
407 	if (!x) {
408 		res = -1;
409 		goto fail;
410 	}
411 
412 	/* y = sqrt(x^3 + ax + b) mod p
413 	 * if LSB(save) == LSB(y): PWE = (x, y)
414 	 * else: PWE = (x, p - y)
415 	 *
416 	 * Calculate y and the two possible values for PWE and after that,
417 	 * use constant time selection to copy the correct alternative.
418 	 */
419 	y = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x);
420 	if (!y ||
421 	    dragonfly_sqrt(sae->tmp->ec, y, y) < 0 ||
422 	    crypto_bignum_to_bin(y, x_y, SAE_MAX_ECC_PRIME_LEN,
423 				 prime_len) < 0 ||
424 	    crypto_bignum_sub(sae->tmp->prime, y, y) < 0 ||
425 	    crypto_bignum_to_bin(y, x_y + SAE_MAX_ECC_PRIME_LEN,
426 				 SAE_MAX_ECC_PRIME_LEN, prime_len) < 0) {
427 		wpa_printf(MSG_DEBUG, "SAE: Could not solve y");
428 		goto fail;
429 	}
430 
431 	is_eq = const_time_eq(pwd_seed_odd, x_y[prime_len - 1] & 0x01);
432 	const_time_select_bin(is_eq, x_y, x_y + SAE_MAX_ECC_PRIME_LEN,
433 			      prime_len, x_y + prime_len);
434 	os_memcpy(x_y, x_bin, prime_len);
435 	wpa_hexdump_key(MSG_DEBUG, "SAE: PWE", x_y, 2 * prime_len);
436 	crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1);
437 	sae->tmp->pwe_ecc = crypto_ec_point_from_bin(sae->tmp->ec, x_y);
438 	if (!sae->tmp->pwe_ecc) {
439 		wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
440 		res = -1;
441 	}
442 
443 fail:
444 	forced_memzero(x_y, sizeof(x_y));
445 	crypto_bignum_deinit(qr, 0);
446 	crypto_bignum_deinit(qnr, 0);
447 	crypto_bignum_deinit(y, 1);
448 	os_free(stub_password);
449 	bin_clear_free(tmp_password, password_len);
450 	crypto_bignum_deinit(x, 1);
451 	os_memset(x_bin, 0, sizeof(x_bin));
452 	os_memset(x_cand_bin, 0, sizeof(x_cand_bin));
453 
454 	return res;
455 }
456 
457 
sae_derive_pwe_ffc(struct sae_data * sae,const u8 * addr1,const u8 * addr2,const u8 * password,size_t password_len)458 static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
459 			      const u8 *addr2, const u8 *password,
460 			      size_t password_len)
461 {
462 	u8 counter, k, sel_counter = 0;
463 	u8 addrs[2 * ETH_ALEN];
464 	const u8 *addr[2];
465 	size_t len[2];
466 	u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
467 		       * mask */
468 	u8 mask;
469 	struct crypto_bignum *pwe;
470 	size_t prime_len = sae->tmp->prime_len;
471 	u8 *pwe_buf;
472 
473 	crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
474 	sae->tmp->pwe_ffc = NULL;
475 
476 	/* Allocate a buffer to maintain selected and candidate PWE for constant
477 	 * time selection. */
478 	pwe_buf = os_zalloc(prime_len * 2);
479 	pwe = crypto_bignum_init();
480 	if (!pwe_buf || !pwe)
481 		goto fail;
482 
483 	wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
484 			      password, password_len);
485 
486 	/*
487 	 * H(salt, ikm) = HMAC-SHA256(salt, ikm)
488 	 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
489 	 *              password || counter)
490 	 */
491 	sae_pwd_seed_key(addr1, addr2, addrs);
492 
493 	addr[0] = password;
494 	len[0] = password_len;
495 	addr[1] = &counter;
496 	len[1] = sizeof(counter);
497 
498 	k = dragonfly_min_pwe_loop_iter(sae->group);
499 
500 	for (counter = 1; counter <= k || !found; counter++) {
501 		u8 pwd_seed[SHA256_MAC_LEN];
502 		int res;
503 
504 		if (counter > 200) {
505 			/* This should not happen in practice */
506 			wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
507 			break;
508 		}
509 
510 		wpa_printf(MSG_DEBUG, "SAE: counter = %02u", counter);
511 		if (hmac_sha256_vector(addrs, sizeof(addrs), 2,
512 				       addr, len, pwd_seed) < 0)
513 			break;
514 		res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
515 		/* res is -1 for fatal failure, 0 if a valid PWE was not found,
516 		 * or 1 if a valid PWE was found. */
517 		if (res < 0)
518 			break;
519 		/* Store the candidate PWE into the second half of pwe_buf and
520 		 * the selected PWE in the beginning of pwe_buf using constant
521 		 * time selection. */
522 		if (crypto_bignum_to_bin(pwe, pwe_buf + prime_len, prime_len,
523 					 prime_len) < 0)
524 			break;
525 		const_time_select_bin(found, pwe_buf, pwe_buf + prime_len,
526 				      prime_len, pwe_buf);
527 		sel_counter = const_time_select_u8(found, sel_counter, counter);
528 		mask = const_time_eq_u8(res, 1);
529 		found = const_time_select_u8(found, found, mask);
530 	}
531 
532 	if (!found)
533 		goto fail;
534 
535 	wpa_printf(MSG_DEBUG, "SAE: Use PWE from counter = %02u", sel_counter);
536 	sae->tmp->pwe_ffc = crypto_bignum_init_set(pwe_buf, prime_len);
537 fail:
538 	crypto_bignum_deinit(pwe, 1);
539 	bin_clear_free(pwe_buf, prime_len * 2);
540 	return sae->tmp->pwe_ffc ? 0 : -1;
541 }
542 
543 
hkdf_extract(size_t hash_len,const u8 * salt,size_t salt_len,size_t num_elem,const u8 * addr[],const size_t len[],u8 * prk)544 static int hkdf_extract(size_t hash_len, const u8 *salt, size_t salt_len,
545 			size_t num_elem, const u8 *addr[], const size_t len[],
546 			u8 *prk)
547 {
548 	if (hash_len == 32)
549 		return hmac_sha256_vector(salt, salt_len, num_elem, addr, len,
550 					  prk);
551 #ifdef CONFIG_SHA384
552 	if (hash_len == 48)
553 		return hmac_sha384_vector(salt, salt_len, num_elem, addr, len,
554 					  prk);
555 #endif /* CONFIG_SHA384 */
556 #ifdef CONFIG_SHA512
557 	if (hash_len == 64)
558 		return hmac_sha512_vector(salt, salt_len, num_elem, addr, len,
559 					  prk);
560 #endif /* CONFIG_SHA512 */
561 	return -1;
562 }
563 
564 
hkdf_expand(size_t hash_len,const u8 * prk,size_t prk_len,const char * info,u8 * okm,size_t okm_len)565 static int hkdf_expand(size_t hash_len, const u8 *prk, size_t prk_len,
566 		       const char *info, u8 *okm, size_t okm_len)
567 {
568 	size_t info_len = os_strlen(info);
569 
570 	if (hash_len == 32)
571 		return hmac_sha256_kdf(prk, prk_len, NULL,
572 				       (const u8 *) info, info_len,
573 				       okm, okm_len);
574 #ifdef CONFIG_SHA384
575 	if (hash_len == 48)
576 		return hmac_sha384_kdf(prk, prk_len, NULL,
577 				       (const u8 *) info, info_len,
578 				       okm, okm_len);
579 #endif /* CONFIG_SHA384 */
580 #ifdef CONFIG_SHA512
581 	if (hash_len == 64)
582 		return hmac_sha512_kdf(prk, prk_len, NULL,
583 				       (const u8 *) info, info_len,
584 				       okm, okm_len);
585 #endif /* CONFIG_SHA512 */
586 	return -1;
587 }
588 
589 
sswu_curve_param(int group,int * z)590 static int sswu_curve_param(int group, int *z)
591 {
592 	switch (group) {
593 	case 19:
594 		*z = -10;
595 		return 0;
596 	case 20:
597 		*z = -12;
598 		return 0;
599 	case 21:
600 		*z = -4;
601 		return 0;
602 	case 25:
603 	case 29:
604 		*z = -5;
605 		return 0;
606 	case 26:
607 		*z = 31;
608 		return 0;
609 	case 28:
610 		*z = -2;
611 		return 0;
612 	case 30:
613 		*z = 7;
614 		return 0;
615 	default:
616 		return -1;
617 	}
618 }
619 
620 
debug_print_bignum(const char * title,const struct crypto_bignum * a,size_t prime_len)621 static void debug_print_bignum(const char *title, const struct crypto_bignum *a,
622 			       size_t prime_len)
623 {
624 	u8 *bin;
625 
626 	bin = os_malloc(prime_len);
627 	if (bin && crypto_bignum_to_bin(a, bin, prime_len, prime_len) >= 0)
628 		wpa_hexdump_key(MSG_DEBUG, title, bin, prime_len);
629 	else
630 		wpa_printf(MSG_DEBUG, "Could not print bignum (%s)", title);
631 	bin_clear_free(bin, prime_len);
632 }
633 
634 
sswu(struct crypto_ec * ec,int group,const struct crypto_bignum * u)635 static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group,
636 				     const struct crypto_bignum *u)
637 {
638 	int z_int;
639 	const struct crypto_bignum *a, *b, *prime;
640 	struct crypto_bignum *u2, *t1, *t2, *z, *t, *zero, *one, *two, *three,
641 		*x1a, *x1b, *y = NULL;
642 	struct crypto_bignum *x1 = NULL, *x2, *gx1, *gx2, *v = NULL;
643 	unsigned int m_is_zero, is_qr, is_eq;
644 	size_t prime_len;
645 	u8 bin[SAE_MAX_ECC_PRIME_LEN];
646 	u8 bin1[SAE_MAX_ECC_PRIME_LEN];
647 	u8 bin2[SAE_MAX_ECC_PRIME_LEN];
648 	u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN];
649 	struct crypto_ec_point *p = NULL;
650 
651 	if (sswu_curve_param(group, &z_int) < 0)
652 		return NULL;
653 
654 	prime = crypto_ec_get_prime(ec);
655 	prime_len = crypto_ec_prime_len(ec);
656 	a = crypto_ec_get_a(ec);
657 	b = crypto_ec_get_b(ec);
658 
659 	u2 = crypto_bignum_init();
660 	t1 = crypto_bignum_init();
661 	t2 = crypto_bignum_init();
662 	z = crypto_bignum_init_uint(abs(z_int));
663 	t = crypto_bignum_init();
664 	zero = crypto_bignum_init_uint(0);
665 	one = crypto_bignum_init_uint(1);
666 	two = crypto_bignum_init_uint(2);
667 	three = crypto_bignum_init_uint(3);
668 	x1a = crypto_bignum_init();
669 	x1b = crypto_bignum_init();
670 	x2 = crypto_bignum_init();
671 	gx1 = crypto_bignum_init();
672 	gx2 = crypto_bignum_init();
673 	if (!u2 || !t1 || !t2 || !z || !t || !zero || !one || !two || !three ||
674 	    !x1a || !x1b || !x2 || !gx1 || !gx2)
675 		goto fail;
676 
677 	if (z_int < 0 && crypto_bignum_sub(prime, z, z) < 0)
678 		goto fail;
679 
680 	/* m = z^2 * u^4 + z * u^2 */
681 	/* --> tmp = z * u^2, m = tmp^2 + tmp */
682 
683 	/* u2 = u^2
684 	 * t1 = z * u2
685 	 * t2 = t1^2
686 	 * m = t1 = t1 + t2 */
687 	if (crypto_bignum_sqrmod(u, prime, u2) < 0 ||
688 	    crypto_bignum_mulmod(z, u2, prime, t1) < 0 ||
689 	    crypto_bignum_sqrmod(t1, prime, t2) < 0 ||
690 	    crypto_bignum_addmod(t1, t2, prime, t1) < 0)
691 		goto fail;
692 	debug_print_bignum("SSWU: m", t1, prime_len);
693 
694 	/* l = CEQ(m, 0)
695 	 * t = CSEL(l, 0, inverse(m); where inverse(x) is calculated as
696 	 * x^(p-2) modulo p which will handle m == 0 case correctly */
697 	/* TODO: Make sure crypto_bignum_is_zero() is constant time */
698 	m_is_zero = const_time_eq(crypto_bignum_is_zero(t1), 1);
699 	/* t = m^(p-2) modulo p */
700 	if (crypto_bignum_sub(prime, two, t2) < 0 ||
701 	    crypto_bignum_exptmod(t1, t2, prime, t) < 0)
702 		goto fail;
703 	debug_print_bignum("SSWU: t", t, prime_len);
704 
705 	/* b / (z * a) */
706 	if (crypto_bignum_mulmod(z, a, prime, t1) < 0 ||
707 	    crypto_bignum_inverse(t1, prime, t1) < 0 ||
708 	    crypto_bignum_mulmod(b, t1, prime, x1a) < 0)
709 		goto fail;
710 	debug_print_bignum("SSWU: x1a = b / (z * a)", x1a, prime_len);
711 
712 	/* (-b/a) * (1 + t) */
713 	if (crypto_bignum_sub(prime, b, t1) < 0 ||
714 	    crypto_bignum_inverse(a, prime, t2) < 0 ||
715 	    crypto_bignum_mulmod(t1, t2, prime, t1) < 0 ||
716 	    crypto_bignum_addmod(one, t, prime, t2) < 0 ||
717 	    crypto_bignum_mulmod(t1, t2, prime, x1b) < 0)
718 		goto fail;
719 	debug_print_bignum("SSWU: x1b = (-b/a) * (1 + t)", x1b, prime_len);
720 
721 	/* x1 = CSEL(CEQ(m, 0), x1a, x1b) */
722 	if (crypto_bignum_to_bin(x1a, bin1, sizeof(bin1), prime_len) < 0 ||
723 	    crypto_bignum_to_bin(x1b, bin2, sizeof(bin2), prime_len) < 0)
724 		goto fail;
725 	const_time_select_bin(m_is_zero, bin1, bin2, prime_len, bin);
726 	x1 = crypto_bignum_init_set(bin, prime_len);
727 	if (!x1)
728 		goto fail;
729 	debug_print_bignum("SSWU: x1 = CSEL(l, x1a, x1b)", x1, prime_len);
730 
731 	/* gx1 = x1^3 + a * x1 + b */
732 	if (crypto_bignum_exptmod(x1, three, prime, t1) < 0 ||
733 	    crypto_bignum_mulmod(a, x1, prime, t2) < 0 ||
734 	    crypto_bignum_addmod(t1, t2, prime, t1) < 0 ||
735 	    crypto_bignum_addmod(t1, b, prime, gx1) < 0)
736 		goto fail;
737 	debug_print_bignum("SSWU: gx1 = x1^3 + a * x1 + b", gx1, prime_len);
738 
739 	/* x2 = z * u^2 * x1 */
740 	if (crypto_bignum_mulmod(z, u2, prime, t1) < 0 ||
741 	    crypto_bignum_mulmod(t1, x1, prime, x2) < 0)
742 		goto fail;
743 	debug_print_bignum("SSWU: x2 = z * u^2 * x1", x2, prime_len);
744 
745 	/* gx2 = x2^3 + a * x2 + b */
746 	if (crypto_bignum_exptmod(x2, three, prime, t1) < 0 ||
747 	    crypto_bignum_mulmod(a, x2, prime, t2) < 0 ||
748 	    crypto_bignum_addmod(t1, t2, prime, t1) < 0 ||
749 	    crypto_bignum_addmod(t1, b, prime, gx2) < 0)
750 		goto fail;
751 	debug_print_bignum("SSWU: gx2 = x2^3 + a * x2 + b", gx2, prime_len);
752 
753 	/* l = gx1 is a quadratic residue modulo p
754 	 * --> gx1^((p-1)/2) modulo p is zero or one */
755 	if (crypto_bignum_sub(prime, one, t1) < 0 ||
756 	    crypto_bignum_rshift(t1, 1, t1) < 0 ||
757 	    crypto_bignum_exptmod(gx1, t1, prime, t1) < 0)
758 		goto fail;
759 	debug_print_bignum("SSWU: gx1^((p-1)/2) modulo p", t1, prime_len);
760 	is_qr = const_time_eq(crypto_bignum_is_zero(t1) |
761 			      crypto_bignum_is_one(t1), 1);
762 
763 	/* v = CSEL(l, gx1, gx2) */
764 	if (crypto_bignum_to_bin(gx1, bin1, sizeof(bin1), prime_len) < 0 ||
765 	    crypto_bignum_to_bin(gx2, bin2, sizeof(bin2), prime_len) < 0)
766 		goto fail;
767 	const_time_select_bin(is_qr, bin1, bin2, prime_len, bin);
768 	v = crypto_bignum_init_set(bin, prime_len);
769 	if (!v)
770 		goto fail;
771 	debug_print_bignum("SSWU: v = CSEL(l, gx1, gx2)", v, prime_len);
772 
773 	/* x = CSEL(l, x1, x2) */
774 	if (crypto_bignum_to_bin(x1, bin1, sizeof(bin1), prime_len) < 0 ||
775 	    crypto_bignum_to_bin(x2, bin2, sizeof(bin2), prime_len) < 0)
776 		goto fail;
777 	const_time_select_bin(is_qr, bin1, bin2, prime_len, x_y);
778 	wpa_hexdump_key(MSG_DEBUG, "SSWU: x = CSEL(l, x1, x2)", x_y, prime_len);
779 
780 	/* y = sqrt(v) */
781 	y = crypto_bignum_init();
782 	if (!y || dragonfly_sqrt(ec, v, y) < 0)
783 		goto fail;
784 	debug_print_bignum("SSWU: y = sqrt(v)", y, prime_len);
785 
786 	/* l = CEQ(LSB(u), LSB(y)) */
787 	if (crypto_bignum_to_bin(u, bin1, sizeof(bin1), prime_len) < 0 ||
788 	    crypto_bignum_to_bin(y, bin2, sizeof(bin2), prime_len) < 0)
789 		goto fail;
790 	is_eq = const_time_eq(bin1[prime_len - 1] & 0x01,
791 			      bin2[prime_len - 1] & 0x01);
792 
793 	/* P = CSEL(l, (x,y), (x, p-y)) */
794 	if (crypto_bignum_sub(prime, y, t1) < 0)
795 		goto fail;
796 	debug_print_bignum("SSWU: p - y", t1, prime_len);
797 	if (crypto_bignum_to_bin(y, bin1, sizeof(bin1), prime_len) < 0 ||
798 	    crypto_bignum_to_bin(t1, bin2, sizeof(bin2), prime_len) < 0)
799 		goto fail;
800 	const_time_select_bin(is_eq, bin1, bin2, prime_len, &x_y[prime_len]);
801 
802 	/* output P */
803 	wpa_hexdump_key(MSG_DEBUG, "SSWU: P.x", x_y, prime_len);
804 	wpa_hexdump_key(MSG_DEBUG, "SSWU: P.y", &x_y[prime_len], prime_len);
805 	p = crypto_ec_point_from_bin(ec, x_y);
806 
807 fail:
808 	crypto_bignum_deinit(u2, 1);
809 	crypto_bignum_deinit(t1, 1);
810 	crypto_bignum_deinit(t2, 1);
811 	crypto_bignum_deinit(z, 0);
812 	crypto_bignum_deinit(t, 1);
813 	crypto_bignum_deinit(x1a, 1);
814 	crypto_bignum_deinit(x1b, 1);
815 	crypto_bignum_deinit(x1, 1);
816 	crypto_bignum_deinit(x2, 1);
817 	crypto_bignum_deinit(gx1, 1);
818 	crypto_bignum_deinit(gx2, 1);
819 	crypto_bignum_deinit(y, 1);
820 	crypto_bignum_deinit(v, 1);
821 	crypto_bignum_deinit(zero, 0);
822 	crypto_bignum_deinit(one, 0);
823 	crypto_bignum_deinit(two, 0);
824 	crypto_bignum_deinit(three, 0);
825 	forced_memzero(bin, sizeof(bin));
826 	forced_memzero(bin1, sizeof(bin1));
827 	forced_memzero(bin2, sizeof(bin2));
828 	forced_memzero(x_y, sizeof(x_y));
829 	return p;
830 }
831 
832 
sae_pwd_seed(size_t hash_len,const u8 * ssid,size_t ssid_len,const u8 * password,size_t password_len,const u8 * identifier,size_t identifier_len,u8 * pwd_seed)833 static int sae_pwd_seed(size_t hash_len, const u8 *ssid, size_t ssid_len,
834 			const u8 *password, size_t password_len,
835 			const u8 *identifier, size_t identifier_len,
836 			u8 *pwd_seed)
837 {
838 	const u8 *addr[2];
839 	size_t len[2];
840 	size_t num_elem;
841 
842 	/* pwd-seed = HKDF-Extract(ssid, password [ || identifier ]) */
843 	addr[0] = password;
844 	len[0] = password_len;
845 	num_elem = 1;
846 	wpa_hexdump_ascii(MSG_DEBUG, "SAE: SSID", ssid, ssid_len);
847 	wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
848 			      password, password_len);
849 	if (identifier) {
850 		wpa_hexdump_ascii(MSG_DEBUG, "SAE: password identifier",
851 				  identifier, identifier_len);
852 		addr[num_elem] = (const u8 *) identifier;
853 		len[num_elem] = identifier_len;
854 		num_elem++;
855 	}
856 	if (hkdf_extract(hash_len, ssid, ssid_len, num_elem, addr, len,
857 			 pwd_seed) < 0)
858 		return -1;
859 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, hash_len);
860 	return 0;
861 }
862 
863 
sae_ecc_prime_len_2_hash_len(size_t prime_len)864 size_t sae_ecc_prime_len_2_hash_len(size_t prime_len)
865 {
866 	if (prime_len <= 256 / 8)
867 		return 32;
868 	if (prime_len <= 384 / 8)
869 		return 48;
870 	return 64;
871 }
872 
873 
874 static struct crypto_ec_point *
sae_derive_pt_ecc(struct crypto_ec * ec,int group,const u8 * ssid,size_t ssid_len,const u8 * password,size_t password_len,const u8 * identifier,size_t identifier_len)875 sae_derive_pt_ecc(struct crypto_ec *ec, int group,
876 		  const u8 *ssid, size_t ssid_len,
877 		  const u8 *password, size_t password_len,
878 		  const u8 *identifier, size_t identifier_len)
879 {
880 	u8 pwd_seed[64];
881 	u8 pwd_value[SAE_MAX_ECC_PRIME_LEN * 2];
882 	size_t pwd_value_len, hash_len, prime_len;
883 	const struct crypto_bignum *prime;
884 	struct crypto_bignum *bn = NULL;
885 	struct crypto_ec_point *p1 = NULL, *p2 = NULL, *pt = NULL;
886 
887 	prime = crypto_ec_get_prime(ec);
888 	prime_len = crypto_ec_prime_len(ec);
889 	if (prime_len > SAE_MAX_ECC_PRIME_LEN)
890 		goto fail;
891 	hash_len = sae_ecc_prime_len_2_hash_len(prime_len);
892 
893 	/* len = olen(p) + ceil(olen(p)/2) */
894 	pwd_value_len = prime_len + (prime_len + 1) / 2;
895 
896 	if (sae_pwd_seed(hash_len, ssid, ssid_len, password, password_len,
897 			 identifier, identifier_len, pwd_seed) < 0)
898 		goto fail;
899 
900 	/* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element u1 P1", len)
901 	 */
902 	if (hkdf_expand(hash_len, pwd_seed, hash_len,
903 			"SAE Hash to Element u1 P1", pwd_value, pwd_value_len) <
904 	    0)
905 		goto fail;
906 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value (u1 P1)",
907 			pwd_value, pwd_value_len);
908 
909 	/* u1 = pwd-value modulo p */
910 	bn = crypto_bignum_init_set(pwd_value, pwd_value_len);
911 	if (!bn || crypto_bignum_mod(bn, prime, bn) < 0 ||
912 	    crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value),
913 				 prime_len) < 0)
914 		goto fail;
915 	wpa_hexdump_key(MSG_DEBUG, "SAE: u1", pwd_value, prime_len);
916 
917 	/* P1 = SSWU(u1) */
918 	p1 = sswu(ec, group, bn);
919 	if (!p1)
920 		goto fail;
921 
922 	/* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element u2 P2", len)
923 	 */
924 	if (hkdf_expand(hash_len, pwd_seed, hash_len,
925 			"SAE Hash to Element u2 P2", pwd_value,
926 			pwd_value_len) < 0)
927 		goto fail;
928 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value (u2 P2)",
929 			pwd_value, pwd_value_len);
930 
931 	/* u2 = pwd-value modulo p */
932 	crypto_bignum_deinit(bn, 1);
933 	bn = crypto_bignum_init_set(pwd_value, pwd_value_len);
934 	if (!bn || crypto_bignum_mod(bn, prime, bn) < 0 ||
935 	    crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value),
936 				 prime_len) < 0)
937 		goto fail;
938 	wpa_hexdump_key(MSG_DEBUG, "SAE: u2", pwd_value, prime_len);
939 
940 	/* P2 = SSWU(u2) */
941 	p2 = sswu(ec, group, bn);
942 	if (!p2)
943 		goto fail;
944 
945 	/* PT = elem-op(P1, P2) */
946 	pt = crypto_ec_point_init(ec);
947 	if (!pt)
948 		goto fail;
949 	if (crypto_ec_point_add(ec, p1, p2, pt) < 0) {
950 		crypto_ec_point_deinit(pt, 1);
951 		pt = NULL;
952 	}
953 
954 fail:
955 	forced_memzero(pwd_seed, sizeof(pwd_seed));
956 	forced_memzero(pwd_value, sizeof(pwd_value));
957 	crypto_bignum_deinit(bn, 1);
958 	crypto_ec_point_deinit(p1, 1);
959 	crypto_ec_point_deinit(p2, 1);
960 	return pt;
961 }
962 
963 
sae_ffc_prime_len_2_hash_len(size_t prime_len)964 size_t sae_ffc_prime_len_2_hash_len(size_t prime_len)
965 {
966 	if (prime_len <= 2048 / 8)
967 		return 32;
968 	if (prime_len <= 3072 / 8)
969 		return 48;
970 	return 64;
971 }
972 
973 
974 static struct crypto_bignum *
sae_derive_pt_ffc(const struct dh_group * dh,int group,const u8 * ssid,size_t ssid_len,const u8 * password,size_t password_len,const u8 * identifier,size_t identifier_len)975 sae_derive_pt_ffc(const struct dh_group *dh, int group,
976 		  const u8 *ssid, size_t ssid_len,
977 		  const u8 *password, size_t password_len,
978 		  const u8 *identifier, size_t identifier_len)
979 {
980 	size_t hash_len, prime_len, pwd_value_len;
981 	struct crypto_bignum *prime, *order;
982 	struct crypto_bignum *one = NULL, *two = NULL, *bn = NULL, *tmp = NULL,
983 		*pt = NULL;
984 	u8 pwd_seed[64];
985 	u8 pwd_value[SAE_MAX_PRIME_LEN + SAE_MAX_PRIME_LEN / 2];
986 
987 	prime = crypto_bignum_init_set(dh->prime, dh->prime_len);
988 	order = crypto_bignum_init_set(dh->order, dh->order_len);
989 	if (!prime || !order)
990 		goto fail;
991 	prime_len = dh->prime_len;
992 	if (prime_len > SAE_MAX_PRIME_LEN)
993 		goto fail;
994 	hash_len = sae_ffc_prime_len_2_hash_len(prime_len);
995 
996 	/* len = olen(p) + ceil(olen(p)/2) */
997 	pwd_value_len = prime_len + (prime_len + 1) / 2;
998 	if (pwd_value_len > sizeof(pwd_value))
999 		goto fail;
1000 
1001 	if (sae_pwd_seed(hash_len, ssid, ssid_len, password, password_len,
1002 			 identifier, identifier_len, pwd_seed) < 0)
1003 		goto fail;
1004 
1005 	/* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element", len) */
1006 	if (hkdf_expand(hash_len, pwd_seed, hash_len,
1007 			"SAE Hash to Element", pwd_value, pwd_value_len) < 0)
1008 		goto fail;
1009 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
1010 			pwd_value, pwd_value_len);
1011 
1012 	/* pwd-value = (pwd-value modulo (p-2)) + 2 */
1013 	bn = crypto_bignum_init_set(pwd_value, pwd_value_len);
1014 	one = crypto_bignum_init_uint(1);
1015 	two = crypto_bignum_init_uint(2);
1016 	tmp = crypto_bignum_init();
1017 	if (!bn || !one || !two || !tmp ||
1018 	    crypto_bignum_sub(prime, two, tmp) < 0 ||
1019 	    crypto_bignum_mod(bn, tmp, bn) < 0 ||
1020 	    crypto_bignum_add(bn, two, bn) < 0 ||
1021 	    crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value),
1022 				 prime_len) < 0)
1023 		goto fail;
1024 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value(reduced)",
1025 			pwd_value, prime_len);
1026 
1027 	/* PT = pwd-value^((p-1)/q) modulo p */
1028 	pt = crypto_bignum_init();
1029 	if (!pt ||
1030 	    crypto_bignum_sub(prime, one, tmp) < 0 ||
1031 	    crypto_bignum_div(tmp, order, tmp) < 0 ||
1032 	    crypto_bignum_exptmod(bn, tmp, prime, pt) < 0) {
1033 		crypto_bignum_deinit(pt, 1);
1034 		pt = NULL;
1035 		goto fail;
1036 	}
1037 	debug_print_bignum("SAE: PT", pt, prime_len);
1038 
1039 fail:
1040 	forced_memzero(pwd_seed, sizeof(pwd_seed));
1041 	forced_memzero(pwd_value, sizeof(pwd_value));
1042 	crypto_bignum_deinit(bn, 1);
1043 	crypto_bignum_deinit(tmp, 1);
1044 	crypto_bignum_deinit(one, 0);
1045 	crypto_bignum_deinit(two, 0);
1046 	crypto_bignum_deinit(prime, 0);
1047 	crypto_bignum_deinit(order, 0);
1048 	return pt;
1049 }
1050 
1051 
1052 static struct sae_pt *
sae_derive_pt_group(int group,const u8 * ssid,size_t ssid_len,const u8 * password,size_t password_len,const u8 * identifier,size_t identifier_len)1053 sae_derive_pt_group(int group, const u8 *ssid, size_t ssid_len,
1054 		    const u8 *password, size_t password_len,
1055 		    const u8 *identifier, size_t identifier_len)
1056 {
1057 	struct sae_pt *pt;
1058 
1059 	wpa_printf(MSG_DEBUG, "SAE: Derive PT - group %d", group);
1060 
1061 	if (ssid_len > 32)
1062 		return NULL;
1063 
1064 	pt = os_zalloc(sizeof(*pt));
1065 	if (!pt)
1066 		return NULL;
1067 
1068 	if (identifier) {
1069 		pt->password_id = wpabuf_alloc_copy(identifier, identifier_len);
1070 		if (!pt->password_id)
1071 			goto fail;
1072 	}
1073 
1074 #ifdef CONFIG_SAE_PK
1075 	os_memcpy(pt->ssid, ssid, ssid_len);
1076 	pt->ssid_len = ssid_len;
1077 #endif /* CONFIG_SAE_PK */
1078 	pt->group = group;
1079 	pt->ec = crypto_ec_init(group);
1080 	if (pt->ec) {
1081 		pt->ecc_pt = sae_derive_pt_ecc(pt->ec, group, ssid, ssid_len,
1082 					       password, password_len,
1083 					       identifier, identifier_len);
1084 		if (!pt->ecc_pt) {
1085 			wpa_printf(MSG_DEBUG, "SAE: Failed to derive PT");
1086 			goto fail;
1087 		}
1088 
1089 		return pt;
1090 	}
1091 
1092 	pt->dh = dh_groups_get(group);
1093 	if (!pt->dh) {
1094 		wpa_printf(MSG_DEBUG, "SAE: Unsupported group %d", group);
1095 		goto fail;
1096 	}
1097 
1098 	pt->ffc_pt = sae_derive_pt_ffc(pt->dh, group, ssid, ssid_len,
1099 				       password, password_len, identifier,
1100 				       identifier_len);
1101 	if (!pt->ffc_pt) {
1102 		wpa_printf(MSG_DEBUG, "SAE: Failed to derive PT");
1103 		goto fail;
1104 	}
1105 
1106 	return pt;
1107 fail:
1108 	sae_deinit_pt(pt);
1109 	return NULL;
1110 }
1111 
1112 
sae_derive_pt(const int * groups,const u8 * ssid,size_t ssid_len,const u8 * password,size_t password_len,const u8 * identifier,size_t identifier_len)1113 struct sae_pt * sae_derive_pt(const int *groups,
1114 			      const u8 *ssid, size_t ssid_len,
1115 			      const u8 *password, size_t password_len,
1116 			      const u8 *identifier, size_t identifier_len)
1117 {
1118 	struct sae_pt *pt = NULL, *last = NULL, *tmp;
1119 	const int default_groups[] = { 19, 0 };
1120 	int i;
1121 
1122 	if (!groups)
1123 		groups = default_groups;
1124 	for (i = 0; groups[i] > 0; i++) {
1125 		tmp = sae_derive_pt_group(groups[i], ssid, ssid_len, password,
1126 					  password_len, identifier,
1127 					  identifier_len);
1128 		if (!tmp)
1129 			continue;
1130 
1131 		if (last)
1132 			last->next = tmp;
1133 		else
1134 			pt = tmp;
1135 		last = tmp;
1136 	}
1137 
1138 	return pt;
1139 }
1140 
1141 
sae_max_min_addr(const u8 * addr[],size_t len[],const u8 * addr1,const u8 * addr2)1142 static void sae_max_min_addr(const u8 *addr[], size_t len[],
1143 			     const u8 *addr1, const u8 *addr2)
1144 {
1145 	len[0] = ETH_ALEN;
1146 	len[1] = ETH_ALEN;
1147 	if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) {
1148 		addr[0] = addr1;
1149 		addr[1] = addr2;
1150 	} else {
1151 		addr[0] = addr2;
1152 		addr[1] = addr1;
1153 	}
1154 }
1155 
1156 
1157 struct crypto_ec_point *
sae_derive_pwe_from_pt_ecc(const struct sae_pt * pt,const u8 * addr1,const u8 * addr2)1158 sae_derive_pwe_from_pt_ecc(const struct sae_pt *pt,
1159 			   const u8 *addr1, const u8 *addr2)
1160 {
1161 	u8 bin[SAE_MAX_ECC_PRIME_LEN * 2];
1162 	size_t prime_len;
1163 	const u8 *addr[2];
1164 	size_t len[2];
1165 	u8 salt[64], hash[64];
1166 	size_t hash_len;
1167 	const struct crypto_bignum *order;
1168 	struct crypto_bignum *tmp = NULL, *val = NULL, *one = NULL;
1169 	struct crypto_ec_point *pwe = NULL;
1170 
1171 	wpa_printf(MSG_DEBUG, "SAE: Derive PWE from PT");
1172 	prime_len = crypto_ec_prime_len(pt->ec);
1173 	if (crypto_ec_point_to_bin(pt->ec, pt->ecc_pt,
1174 				   bin, bin + prime_len) < 0)
1175 		return NULL;
1176 	wpa_hexdump_key(MSG_DEBUG, "SAE: PT.x", bin, prime_len);
1177 	wpa_hexdump_key(MSG_DEBUG, "SAE: PT.y", bin + prime_len, prime_len);
1178 
1179 	sae_max_min_addr(addr, len, addr1, addr2);
1180 
1181 	/* val = H(0^n,
1182 	 *         MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC)) */
1183 	wpa_printf(MSG_DEBUG, "SAE: val = H(0^n, MAX(addrs) || MIN(addrs))");
1184 	hash_len = sae_ecc_prime_len_2_hash_len(prime_len);
1185 	os_memset(salt, 0, hash_len);
1186 	if (hkdf_extract(hash_len, salt, hash_len, 2, addr, len, hash) < 0)
1187 		goto fail;
1188 	wpa_hexdump(MSG_DEBUG, "SAE: val", hash, hash_len);
1189 
1190 	/* val = val modulo (q - 1) + 1 */
1191 	order = crypto_ec_get_order(pt->ec);
1192 	tmp = crypto_bignum_init();
1193 	val = crypto_bignum_init_set(hash, hash_len);
1194 	one = crypto_bignum_init_uint(1);
1195 	if (!tmp || !val || !one ||
1196 	    crypto_bignum_sub(order, one, tmp) < 0 ||
1197 	    crypto_bignum_mod(val, tmp, val) < 0 ||
1198 	    crypto_bignum_add(val, one, val) < 0)
1199 		goto fail;
1200 	debug_print_bignum("SAE: val(reduced to 1..q-1)", val, prime_len);
1201 
1202 	/* PWE = scalar-op(val, PT) */
1203 	pwe = crypto_ec_point_init(pt->ec);
1204 	if (!pwe ||
1205 	    crypto_ec_point_mul(pt->ec, pt->ecc_pt, val, pwe) < 0 ||
1206 	    crypto_ec_point_to_bin(pt->ec, pwe, bin, bin + prime_len) < 0) {
1207 		crypto_ec_point_deinit(pwe, 1);
1208 		pwe = NULL;
1209 		goto fail;
1210 	}
1211 	wpa_hexdump_key(MSG_DEBUG, "SAE: PWE.x", bin, prime_len);
1212 	wpa_hexdump_key(MSG_DEBUG, "SAE: PWE.y", bin + prime_len, prime_len);
1213 
1214 fail:
1215 	crypto_bignum_deinit(tmp, 1);
1216 	crypto_bignum_deinit(val, 1);
1217 	crypto_bignum_deinit(one, 0);
1218 	return pwe;
1219 }
1220 
1221 
1222 struct crypto_bignum *
sae_derive_pwe_from_pt_ffc(const struct sae_pt * pt,const u8 * addr1,const u8 * addr2)1223 sae_derive_pwe_from_pt_ffc(const struct sae_pt *pt,
1224 			   const u8 *addr1, const u8 *addr2)
1225 {
1226 	size_t prime_len;
1227 	const u8 *addr[2];
1228 	size_t len[2];
1229 	u8 salt[64], hash[64];
1230 	size_t hash_len;
1231 	struct crypto_bignum *tmp = NULL, *val = NULL, *one = NULL;
1232 	struct crypto_bignum *pwe = NULL, *order = NULL, *prime = NULL;
1233 
1234 	wpa_printf(MSG_DEBUG, "SAE: Derive PWE from PT");
1235 	prime = crypto_bignum_init_set(pt->dh->prime, pt->dh->prime_len);
1236 	order = crypto_bignum_init_set(pt->dh->order, pt->dh->order_len);
1237 	if (!prime || !order)
1238 		goto fail;
1239 	prime_len = pt->dh->prime_len;
1240 
1241 	sae_max_min_addr(addr, len, addr1, addr2);
1242 
1243 	/* val = H(0^n,
1244 	 *         MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC)) */
1245 	wpa_printf(MSG_DEBUG, "SAE: val = H(0^n, MAX(addrs) || MIN(addrs))");
1246 	hash_len = sae_ffc_prime_len_2_hash_len(prime_len);
1247 	os_memset(salt, 0, hash_len);
1248 	if (hkdf_extract(hash_len, salt, hash_len, 2, addr, len, hash) < 0)
1249 		goto fail;
1250 	wpa_hexdump(MSG_DEBUG, "SAE: val", hash, hash_len);
1251 
1252 	/* val = val modulo (q - 1) + 1 */
1253 	tmp = crypto_bignum_init();
1254 	val = crypto_bignum_init_set(hash, hash_len);
1255 	one = crypto_bignum_init_uint(1);
1256 	if (!tmp || !val || !one ||
1257 	    crypto_bignum_sub(order, one, tmp) < 0 ||
1258 	    crypto_bignum_mod(val, tmp, val) < 0 ||
1259 	    crypto_bignum_add(val, one, val) < 0)
1260 		goto fail;
1261 	debug_print_bignum("SAE: val(reduced to 1..q-1)", val, prime_len);
1262 
1263 	/* PWE = scalar-op(val, PT) */
1264 	pwe = crypto_bignum_init();
1265 	if (!pwe || crypto_bignum_exptmod(pt->ffc_pt, val, prime, pwe) < 0) {
1266 		crypto_bignum_deinit(pwe, 1);
1267 		pwe = NULL;
1268 		goto fail;
1269 	}
1270 	debug_print_bignum("SAE: PWE", pwe, prime_len);
1271 
1272 fail:
1273 	crypto_bignum_deinit(tmp, 1);
1274 	crypto_bignum_deinit(val, 1);
1275 	crypto_bignum_deinit(one, 0);
1276 	crypto_bignum_deinit(prime, 0);
1277 	crypto_bignum_deinit(order, 0);
1278 	return pwe;
1279 }
1280 
1281 
sae_deinit_pt(struct sae_pt * pt)1282 void sae_deinit_pt(struct sae_pt *pt)
1283 {
1284 	struct sae_pt *prev;
1285 
1286 	while (pt) {
1287 		crypto_ec_point_deinit(pt->ecc_pt, 1);
1288 		crypto_bignum_deinit(pt->ffc_pt, 1);
1289 		crypto_ec_deinit(pt->ec);
1290 		wpabuf_free(pt->password_id);
1291 		prev = pt;
1292 		pt = pt->next;
1293 		os_free(prev);
1294 	}
1295 }
1296 
1297 
sae_derive_commit_element_ecc(struct sae_data * sae,struct crypto_bignum * mask)1298 static int sae_derive_commit_element_ecc(struct sae_data *sae,
1299 					 struct crypto_bignum *mask)
1300 {
1301 	/* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
1302 	if (!sae->tmp->own_commit_element_ecc) {
1303 		sae->tmp->own_commit_element_ecc =
1304 			crypto_ec_point_init(sae->tmp->ec);
1305 		if (!sae->tmp->own_commit_element_ecc)
1306 			return -1;
1307 	}
1308 
1309 	if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, mask,
1310 				sae->tmp->own_commit_element_ecc) < 0 ||
1311 	    crypto_ec_point_invert(sae->tmp->ec,
1312 				   sae->tmp->own_commit_element_ecc) < 0) {
1313 		wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
1314 		return -1;
1315 	}
1316 
1317 	return 0;
1318 }
1319 
1320 
sae_derive_commit_element_ffc(struct sae_data * sae,struct crypto_bignum * mask)1321 static int sae_derive_commit_element_ffc(struct sae_data *sae,
1322 					 struct crypto_bignum *mask)
1323 {
1324 	/* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
1325 	if (!sae->tmp->own_commit_element_ffc) {
1326 		sae->tmp->own_commit_element_ffc = crypto_bignum_init();
1327 		if (!sae->tmp->own_commit_element_ffc)
1328 			return -1;
1329 	}
1330 
1331 	if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, mask, sae->tmp->prime,
1332 				  sae->tmp->own_commit_element_ffc) < 0 ||
1333 	    crypto_bignum_inverse(sae->tmp->own_commit_element_ffc,
1334 				  sae->tmp->prime,
1335 				  sae->tmp->own_commit_element_ffc) < 0) {
1336 		wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
1337 		return -1;
1338 	}
1339 
1340 	return 0;
1341 }
1342 
1343 
sae_derive_commit(struct sae_data * sae)1344 static int sae_derive_commit(struct sae_data *sae)
1345 {
1346 	struct crypto_bignum *mask;
1347 	int ret;
1348 
1349 	mask = crypto_bignum_init();
1350 	if (!sae->tmp->sae_rand)
1351 		sae->tmp->sae_rand = crypto_bignum_init();
1352 	if (!sae->tmp->own_commit_scalar)
1353 		sae->tmp->own_commit_scalar = crypto_bignum_init();
1354 	ret = !mask || !sae->tmp->sae_rand || !sae->tmp->own_commit_scalar ||
1355 		dragonfly_generate_scalar(sae->tmp->order, sae->tmp->sae_rand,
1356 					  mask,
1357 					  sae->tmp->own_commit_scalar) < 0 ||
1358 		(sae->tmp->ec &&
1359 		 sae_derive_commit_element_ecc(sae, mask) < 0) ||
1360 		(sae->tmp->dh &&
1361 		 sae_derive_commit_element_ffc(sae, mask) < 0);
1362 	crypto_bignum_deinit(mask, 1);
1363 	return ret ? -1 : 0;
1364 }
1365 
1366 
sae_prepare_commit(const u8 * addr1,const u8 * addr2,const u8 * password,size_t password_len,struct sae_data * sae)1367 int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
1368 		       const u8 *password, size_t password_len,
1369 		       struct sae_data *sae)
1370 {
1371 	if (sae->tmp == NULL ||
1372 	    (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
1373 						password_len) < 0) ||
1374 	    (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
1375 						password_len) < 0))
1376 		return -1;
1377 
1378 	sae->h2e = 0;
1379 	sae->pk = 0;
1380 	return sae_derive_commit(sae);
1381 }
1382 
1383 
sae_prepare_commit_pt(struct sae_data * sae,const struct sae_pt * pt,const u8 * addr1,const u8 * addr2,int * rejected_groups,const struct sae_pk * pk)1384 int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
1385 			  const u8 *addr1, const u8 *addr2,
1386 			  int *rejected_groups, const struct sae_pk *pk)
1387 {
1388 	if (!sae->tmp)
1389 		return -1;
1390 
1391 	while (pt) {
1392 		if (pt->group == sae->group)
1393 			break;
1394 		pt = pt->next;
1395 	}
1396 	if (!pt) {
1397 		wpa_printf(MSG_INFO, "SAE: Could not find PT for group %u",
1398 			   sae->group);
1399 		return -1;
1400 	}
1401 
1402 #ifdef CONFIG_SAE_PK
1403 	os_memcpy(sae->tmp->ssid, pt->ssid, pt->ssid_len);
1404 	sae->tmp->ssid_len = pt->ssid_len;
1405 	sae->tmp->ap_pk = pk;
1406 #endif /* CONFIG_SAE_PK */
1407 	sae->tmp->own_addr_higher = os_memcmp(addr1, addr2, ETH_ALEN) > 0;
1408 	wpabuf_free(sae->tmp->own_rejected_groups);
1409 	sae->tmp->own_rejected_groups = NULL;
1410 	if (rejected_groups) {
1411 		int count, i;
1412 		struct wpabuf *groups;
1413 
1414 		count = int_array_len(rejected_groups);
1415 		groups = wpabuf_alloc(count * 2);
1416 		if (!groups)
1417 			return -1;
1418 		for (i = 0; i < count; i++)
1419 			wpabuf_put_le16(groups, rejected_groups[i]);
1420 		sae->tmp->own_rejected_groups = groups;
1421 	}
1422 
1423 	if (pt->ec) {
1424 		crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1);
1425 		sae->tmp->pwe_ecc = sae_derive_pwe_from_pt_ecc(pt, addr1,
1426 							       addr2);
1427 		if (!sae->tmp->pwe_ecc)
1428 			return -1;
1429 	}
1430 
1431 	if (pt->dh) {
1432 		crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
1433 		sae->tmp->pwe_ffc = sae_derive_pwe_from_pt_ffc(pt, addr1,
1434 							       addr2);
1435 		if (!sae->tmp->pwe_ffc)
1436 			return -1;
1437 	}
1438 
1439 	sae->h2e = 1;
1440 	return sae_derive_commit(sae);
1441 }
1442 
1443 
sae_derive_k_ecc(struct sae_data * sae,u8 * k)1444 static int sae_derive_k_ecc(struct sae_data *sae, u8 *k)
1445 {
1446 	struct crypto_ec_point *K;
1447 	int ret = -1;
1448 
1449 	K = crypto_ec_point_init(sae->tmp->ec);
1450 	if (K == NULL)
1451 		goto fail;
1452 
1453 	/*
1454 	 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
1455 	 *                                        PEER-COMMIT-ELEMENT)))
1456 	 * If K is identity element (point-at-infinity), reject
1457 	 * k = F(K) (= x coordinate)
1458 	 */
1459 
1460 	if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc,
1461 				sae->peer_commit_scalar, K) < 0 ||
1462 	    crypto_ec_point_add(sae->tmp->ec, K,
1463 				sae->tmp->peer_commit_element_ecc, K) < 0 ||
1464 	    crypto_ec_point_mul(sae->tmp->ec, K, sae->tmp->sae_rand, K) < 0 ||
1465 	    crypto_ec_point_is_at_infinity(sae->tmp->ec, K) ||
1466 	    crypto_ec_point_to_bin(sae->tmp->ec, K, k, NULL) < 0) {
1467 		wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
1468 		goto fail;
1469 	}
1470 
1471 	wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len);
1472 
1473 	ret = 0;
1474 fail:
1475 	crypto_ec_point_deinit(K, 1);
1476 	return ret;
1477 }
1478 
1479 
sae_derive_k_ffc(struct sae_data * sae,u8 * k)1480 static int sae_derive_k_ffc(struct sae_data *sae, u8 *k)
1481 {
1482 	struct crypto_bignum *K;
1483 	int ret = -1;
1484 
1485 	K = crypto_bignum_init();
1486 	if (K == NULL)
1487 		goto fail;
1488 
1489 	/*
1490 	 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
1491 	 *                                        PEER-COMMIT-ELEMENT)))
1492 	 * If K is identity element (one), reject.
1493 	 * k = F(K) (= x coordinate)
1494 	 */
1495 
1496 	if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, sae->peer_commit_scalar,
1497 				  sae->tmp->prime, K) < 0 ||
1498 	    crypto_bignum_mulmod(K, sae->tmp->peer_commit_element_ffc,
1499 				 sae->tmp->prime, K) < 0 ||
1500 	    crypto_bignum_exptmod(K, sae->tmp->sae_rand, sae->tmp->prime, K) < 0
1501 	    ||
1502 	    crypto_bignum_is_one(K) ||
1503 	    crypto_bignum_to_bin(K, k, SAE_MAX_PRIME_LEN, sae->tmp->prime_len) <
1504 	    0) {
1505 		wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
1506 		goto fail;
1507 	}
1508 
1509 	wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len);
1510 
1511 	ret = 0;
1512 fail:
1513 	crypto_bignum_deinit(K, 1);
1514 	return ret;
1515 }
1516 
1517 
sae_kdf_hash(size_t hash_len,const u8 * k,const char * label,const u8 * context,size_t context_len,u8 * out,size_t out_len)1518 static int sae_kdf_hash(size_t hash_len, const u8 *k, const char *label,
1519 			const u8 *context, size_t context_len,
1520 			u8 *out, size_t out_len)
1521 {
1522 	if (hash_len == 32)
1523 		return sha256_prf(k, hash_len, label,
1524 				  context, context_len, out, out_len);
1525 #ifdef CONFIG_SHA384
1526 	if (hash_len == 48)
1527 		return sha384_prf(k, hash_len, label,
1528 				  context, context_len, out, out_len);
1529 #endif /* CONFIG_SHA384 */
1530 #ifdef CONFIG_SHA512
1531 	if (hash_len == 64)
1532 		return sha512_prf(k, hash_len, label,
1533 				  context, context_len, out, out_len);
1534 #endif /* CONFIG_SHA512 */
1535 	return -1;
1536 }
1537 
1538 
sae_derive_keys(struct sae_data * sae,const u8 * k)1539 static int sae_derive_keys(struct sae_data *sae, const u8 *k)
1540 {
1541 	u8 zero[SAE_MAX_HASH_LEN], val[SAE_MAX_PRIME_LEN];
1542 	const u8 *salt;
1543 	struct wpabuf *rejected_groups = NULL;
1544 	u8 keyseed[SAE_MAX_HASH_LEN];
1545 	u8 keys[2 * SAE_MAX_HASH_LEN + SAE_PMK_LEN_MAX];
1546 	struct crypto_bignum *tmp;
1547 	int ret = -1;
1548 	size_t hash_len, salt_len, prime_len = sae->tmp->prime_len;
1549 	size_t pmk_len;
1550 	const u8 *addr[1];
1551 	size_t len[1];
1552 
1553 	tmp = crypto_bignum_init();
1554 	if (tmp == NULL)
1555 		goto fail;
1556 
1557 	/* keyseed = H(salt, k)
1558 	 * KCK || PMK = KDF-Hash-Length(keyseed, "SAE KCK and PMK",
1559 	 *                      (commit-scalar + peer-commit-scalar) modulo r)
1560 	 * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128)
1561 	 *
1562 	 * When SAE-PK is used,
1563 	 * KCK || PMK || KEK = KDF-Hash-Length(keyseed, "SAE-PK keys", context)
1564 	 */
1565 	if (!sae->h2e)
1566 		hash_len = SHA256_MAC_LEN;
1567 	else if (sae->tmp->dh)
1568 		hash_len = sae_ffc_prime_len_2_hash_len(prime_len);
1569 	else
1570 		hash_len = sae_ecc_prime_len_2_hash_len(prime_len);
1571 	if (wpa_key_mgmt_sae_ext_key(sae->akmp))
1572 		pmk_len = hash_len;
1573 	else
1574 		pmk_len = SAE_PMK_LEN;
1575 	wpa_printf(MSG_DEBUG, "SAE: Derive keys - H2E=%d AKMP=0x%x = %08x (%s)",
1576 		   sae->h2e, sae->akmp,
1577 		   wpa_akm_to_suite(sae->akmp),
1578 		   wpa_key_mgmt_txt(sae->akmp, WPA_PROTO_RSN));
1579 	if (sae->h2e && (sae->tmp->own_rejected_groups ||
1580 			 sae->tmp->peer_rejected_groups)) {
1581 		struct wpabuf *own, *peer;
1582 
1583 		own = sae->tmp->own_rejected_groups;
1584 		peer = sae->tmp->peer_rejected_groups;
1585 		salt_len = 0;
1586 		if (own)
1587 			salt_len += wpabuf_len(own);
1588 		if (peer)
1589 			salt_len += wpabuf_len(peer);
1590 		rejected_groups = wpabuf_alloc(salt_len);
1591 		if (!rejected_groups)
1592 			goto fail;
1593 		if (sae->tmp->own_addr_higher) {
1594 			if (own)
1595 				wpabuf_put_buf(rejected_groups, own);
1596 			if (peer)
1597 				wpabuf_put_buf(rejected_groups, peer);
1598 		} else {
1599 			if (peer)
1600 				wpabuf_put_buf(rejected_groups, peer);
1601 			if (own)
1602 				wpabuf_put_buf(rejected_groups, own);
1603 		}
1604 		salt = wpabuf_head(rejected_groups);
1605 		salt_len = wpabuf_len(rejected_groups);
1606 	} else {
1607 		os_memset(zero, 0, hash_len);
1608 		salt = zero;
1609 		salt_len = hash_len;
1610 	}
1611 	wpa_hexdump(MSG_DEBUG, "SAE: salt for keyseed derivation",
1612 		    salt, salt_len);
1613 	addr[0] = k;
1614 	len[0] = prime_len;
1615 	if (hkdf_extract(hash_len, salt, salt_len, 1, addr, len, keyseed) < 0)
1616 		goto fail;
1617 	wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, hash_len);
1618 
1619 	if (crypto_bignum_add(sae->tmp->own_commit_scalar,
1620 			      sae->peer_commit_scalar, tmp) < 0 ||
1621 	    crypto_bignum_mod(tmp, sae->tmp->order, tmp) < 0)
1622 		goto fail;
1623 	/* IEEE Std 802.11-2016 is not exactly clear on the encoding of the bit
1624 	 * string that is needed for KCK, PMK, and PMKID derivation, but it
1625 	 * seems to make most sense to encode the
1626 	 * (commit-scalar + peer-commit-scalar) mod r part as a bit string by
1627 	 * zero padding it from left to the length of the order (in full
1628 	 * octets). */
1629 	if (crypto_bignum_to_bin(tmp, val, sizeof(val),
1630 				 sae->tmp->order_len) < 0)
1631 		goto fail;
1632 	wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
1633 
1634 #ifdef CONFIG_SAE_PK
1635 	if (sae->pk) {
1636 		if (sae_kdf_hash(hash_len, keyseed, "SAE-PK keys",
1637 				 val, sae->tmp->order_len,
1638 				 keys, 2 * hash_len + pmk_len) < 0)
1639 			goto fail;
1640 	} else {
1641 		if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK",
1642 				 val, sae->tmp->order_len,
1643 				 keys, hash_len + pmk_len) < 0)
1644 			goto fail;
1645 	}
1646 #else /* CONFIG_SAE_PK */
1647 	if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK",
1648 			 val, sae->tmp->order_len,
1649 			 keys, hash_len + pmk_len) < 0)
1650 		goto fail;
1651 #endif /* !CONFIG_SAE_PK */
1652 
1653 	forced_memzero(keyseed, sizeof(keyseed));
1654 	os_memcpy(sae->tmp->kck, keys, hash_len);
1655 	sae->tmp->kck_len = hash_len;
1656 	os_memcpy(sae->pmk, keys + hash_len, pmk_len);
1657 	sae->pmk_len = pmk_len;
1658 	os_memcpy(sae->pmkid, val, SAE_PMKID_LEN);
1659 #ifdef CONFIG_SAE_PK
1660 	if (sae->pk) {
1661 		os_memcpy(sae->tmp->kek, keys + hash_len + SAE_PMK_LEN,
1662 			  hash_len);
1663 		sae->tmp->kek_len = hash_len;
1664 		wpa_hexdump_key(MSG_DEBUG, "SAE: KEK for SAE-PK",
1665 				sae->tmp->kek, sae->tmp->kek_len);
1666 	}
1667 #endif /* CONFIG_SAE_PK */
1668 	forced_memzero(keys, sizeof(keys));
1669 	wpa_hexdump_key(MSG_DEBUG, "SAE: KCK",
1670 			sae->tmp->kck, sae->tmp->kck_len);
1671 	wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, sae->pmk_len);
1672 
1673 	ret = 0;
1674 fail:
1675 	wpabuf_free(rejected_groups);
1676 	crypto_bignum_deinit(tmp, 0);
1677 	return ret;
1678 }
1679 
1680 
sae_process_commit(struct sae_data * sae)1681 int sae_process_commit(struct sae_data *sae)
1682 {
1683 	u8 k[SAE_MAX_PRIME_LEN];
1684 	int ret = 0;
1685 
1686 	if (sae->tmp == NULL ||
1687 	    (sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) ||
1688 	    (sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) ||
1689 	    sae_derive_keys(sae, k) < 0)
1690 		ret = -1;
1691 
1692 	forced_memzero(k, SAE_MAX_PRIME_LEN);
1693 
1694 	return ret;
1695 }
1696 
1697 
sae_write_commit(struct sae_data * sae,struct wpabuf * buf,const struct wpabuf * token,const u8 * identifier,size_t identifier_len)1698 int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
1699 		     const struct wpabuf *token, const u8 *identifier,
1700 		     size_t identifier_len)
1701 {
1702 	u8 *pos;
1703 
1704 	if (sae->tmp == NULL)
1705 		return -1;
1706 
1707 	wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
1708 	if (!sae->h2e && token) {
1709 		wpabuf_put_buf(buf, token);
1710 		wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token",
1711 			    wpabuf_head(token), wpabuf_len(token));
1712 	}
1713 	pos = wpabuf_put(buf, sae->tmp->prime_len);
1714 	if (crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
1715 				 sae->tmp->prime_len, sae->tmp->prime_len) < 0)
1716 		return -1;
1717 	wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar",
1718 		    pos, sae->tmp->prime_len);
1719 	if (sae->tmp->ec) {
1720 		pos = wpabuf_put(buf, 2 * sae->tmp->prime_len);
1721 		if (crypto_ec_point_to_bin(sae->tmp->ec,
1722 					   sae->tmp->own_commit_element_ecc,
1723 					   pos, pos + sae->tmp->prime_len) < 0)
1724 			return -1;
1725 		wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)",
1726 			    pos, sae->tmp->prime_len);
1727 		wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)",
1728 			    pos + sae->tmp->prime_len, sae->tmp->prime_len);
1729 	} else {
1730 		pos = wpabuf_put(buf, sae->tmp->prime_len);
1731 		if (crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos,
1732 					 sae->tmp->prime_len,
1733 					 sae->tmp->prime_len) < 0)
1734 			return -1;
1735 		wpa_hexdump(MSG_DEBUG, "SAE: own commit-element",
1736 			    pos, sae->tmp->prime_len);
1737 	}
1738 
1739 	if (identifier) {
1740 		/* Password Identifier element */
1741 		wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1742 		wpabuf_put_u8(buf, 1 + identifier_len);
1743 		wpabuf_put_u8(buf, WLAN_EID_EXT_PASSWORD_IDENTIFIER);
1744 		wpabuf_put_data(buf, identifier, identifier_len);
1745 		wpa_hexdump_ascii(MSG_DEBUG, "SAE: own Password Identifier",
1746 				  identifier, identifier_len);
1747 	}
1748 
1749 	if (sae->h2e && sae->tmp->own_rejected_groups) {
1750 		wpa_hexdump_buf(MSG_DEBUG, "SAE: own Rejected Groups",
1751 				sae->tmp->own_rejected_groups);
1752 		wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1753 		wpabuf_put_u8(buf,
1754 			      1 + wpabuf_len(sae->tmp->own_rejected_groups));
1755 		wpabuf_put_u8(buf, WLAN_EID_EXT_REJECTED_GROUPS);
1756 		wpabuf_put_buf(buf, sae->tmp->own_rejected_groups);
1757 	}
1758 
1759 	if (sae->h2e && token) {
1760 		wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1761 		wpabuf_put_u8(buf, 1 + wpabuf_len(token));
1762 		wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN);
1763 		wpabuf_put_buf(buf, token);
1764 		wpa_hexdump_buf(MSG_DEBUG,
1765 				"SAE: Anti-clogging token (in container)",
1766 				token);
1767 	}
1768 
1769 	if (wpa_key_mgmt_sae_ext_key(sae->akmp)) {
1770 		u32 suite = wpa_akm_to_suite(sae->akmp);
1771 
1772 		wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1773 		wpabuf_put_u8(buf, 1 + RSN_SELECTOR_LEN);
1774 		wpabuf_put_u8(buf, WLAN_EID_EXT_AKM_SUITE_SELECTOR);
1775 		RSN_SELECTOR_PUT(wpabuf_put(buf, RSN_SELECTOR_LEN), suite);
1776 		wpa_printf(MSG_DEBUG, "SAE: AKM Suite Selector: %08x", suite);
1777 		sae->own_akm_suite_selector = suite;
1778 	}
1779 
1780 	return 0;
1781 }
1782 
1783 
sae_group_allowed(struct sae_data * sae,int * allowed_groups,u16 group)1784 u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group)
1785 {
1786 	if (allowed_groups) {
1787 		int i;
1788 		for (i = 0; allowed_groups[i] > 0; i++) {
1789 			if (allowed_groups[i] == group)
1790 				break;
1791 		}
1792 		if (allowed_groups[i] != group) {
1793 			wpa_printf(MSG_DEBUG, "SAE: Proposed group %u not "
1794 				   "enabled in the current configuration",
1795 				   group);
1796 			return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1797 		}
1798 	}
1799 
1800 	if (sae->state == SAE_COMMITTED && group != sae->group) {
1801 		wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed");
1802 		return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1803 	}
1804 
1805 	if (group != sae->group && sae_set_group(sae, group) < 0) {
1806 		wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
1807 			   group);
1808 		return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1809 	}
1810 
1811 	if (sae->tmp == NULL) {
1812 		wpa_printf(MSG_DEBUG, "SAE: Group information not yet initialized");
1813 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1814 	}
1815 
1816 	if (sae->tmp->dh && !allowed_groups) {
1817 		wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without "
1818 			   "explicit configuration enabling it", group);
1819 		return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1820 	}
1821 
1822 	return WLAN_STATUS_SUCCESS;
1823 }
1824 
1825 
sae_is_password_id_elem(const u8 * pos,const u8 * end)1826 static int sae_is_password_id_elem(const u8 *pos, const u8 *end)
1827 {
1828 	return end - pos >= 3 &&
1829 		pos[0] == WLAN_EID_EXTENSION &&
1830 		pos[1] >= 1 &&
1831 		end - pos - 2 >= pos[1] &&
1832 		pos[2] == WLAN_EID_EXT_PASSWORD_IDENTIFIER;
1833 }
1834 
1835 
sae_is_rejected_groups_elem(const u8 * pos,const u8 * end)1836 static int sae_is_rejected_groups_elem(const u8 *pos, const u8 *end)
1837 {
1838 	return end - pos >= 3 &&
1839 		pos[0] == WLAN_EID_EXTENSION &&
1840 		pos[1] >= 2 &&
1841 		end - pos - 2 >= pos[1] &&
1842 		pos[2] == WLAN_EID_EXT_REJECTED_GROUPS;
1843 }
1844 
1845 
sae_is_token_container_elem(const u8 * pos,const u8 * end)1846 static int sae_is_token_container_elem(const u8 *pos, const u8 *end)
1847 {
1848 	return end - pos >= 3 &&
1849 		pos[0] == WLAN_EID_EXTENSION &&
1850 		pos[1] >= 1 &&
1851 		end - pos - 2 >= pos[1] &&
1852 		pos[2] == WLAN_EID_EXT_ANTI_CLOGGING_TOKEN;
1853 }
1854 
1855 
sae_is_akm_suite_selector_elem(const u8 * pos,const u8 * end)1856 static int sae_is_akm_suite_selector_elem(const u8 *pos, const u8 *end)
1857 {
1858 	return end - pos >= 2 + 1 + RSN_SELECTOR_LEN &&
1859 		pos[0] == WLAN_EID_EXTENSION &&
1860 		pos[1] >= 1 + RSN_SELECTOR_LEN &&
1861 		end - pos - 2 >= pos[1] &&
1862 		pos[2] == WLAN_EID_EXT_AKM_SUITE_SELECTOR;
1863 }
1864 
1865 
sae_parse_commit_token(struct sae_data * sae,const u8 ** pos,const u8 * end,const u8 ** token,size_t * token_len,int h2e)1866 static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
1867 				   const u8 *end, const u8 **token,
1868 				   size_t *token_len, int h2e)
1869 {
1870 	size_t scalar_elem_len, tlen;
1871 
1872 	if (token)
1873 		*token = NULL;
1874 	if (token_len)
1875 		*token_len = 0;
1876 
1877 	if (h2e)
1878 		return; /* No Anti-Clogging Token field outside container IE */
1879 
1880 	scalar_elem_len = (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len;
1881 	if (scalar_elem_len >= (size_t) (end - *pos))
1882 		return; /* No extra data beyond peer scalar and element */
1883 
1884 	tlen = end - (*pos + scalar_elem_len);
1885 
1886 	if (tlen < SHA256_MAC_LEN) {
1887 		wpa_printf(MSG_DEBUG,
1888 			   "SAE: Too short optional data (%u octets) to include our Anti-Clogging Token",
1889 			   (unsigned int) tlen);
1890 		return;
1891 	}
1892 
1893 	wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
1894 	if (token)
1895 		*token = *pos;
1896 	if (token_len)
1897 		*token_len = tlen;
1898 	*pos += tlen;
1899 }
1900 
1901 
sae_parse_token_container(struct sae_data * sae,const u8 * pos,const u8 * end,const u8 ** token,size_t * token_len)1902 static void sae_parse_token_container(struct sae_data *sae,
1903 				      const u8 *pos, const u8 *end,
1904 				      const u8 **token, size_t *token_len)
1905 {
1906 	if (!sae_is_token_container_elem(pos, end))
1907 		return;
1908 	if (token)
1909 		*token = pos + 3;
1910 	if (token_len)
1911 		*token_len = pos[1] - 1;
1912 	wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token (in container)",
1913 		    pos + 3, pos[1] - 1);
1914 }
1915 
1916 
sae_parse_commit_scalar(struct sae_data * sae,const u8 ** pos,const u8 * end)1917 static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos,
1918 				   const u8 *end)
1919 {
1920 	struct crypto_bignum *peer_scalar;
1921 
1922 	if (sae->tmp->prime_len > end - *pos) {
1923 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar");
1924 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1925 	}
1926 
1927 	peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len);
1928 	if (peer_scalar == NULL)
1929 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1930 
1931 	/*
1932 	 * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for
1933 	 * the peer and it is in Authenticated state, the new Commit Message
1934 	 * shall be dropped if the peer-scalar is identical to the one used in
1935 	 * the existing protocol instance.
1936 	 */
1937 	if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar_accepted &&
1938 	    crypto_bignum_cmp(sae->peer_commit_scalar_accepted,
1939 			      peer_scalar) == 0) {
1940 		wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous "
1941 			   "peer-commit-scalar");
1942 		crypto_bignum_deinit(peer_scalar, 0);
1943 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1944 	}
1945 
1946 	/* 1 < scalar < r */
1947 	if (crypto_bignum_is_zero(peer_scalar) ||
1948 	    crypto_bignum_is_one(peer_scalar) ||
1949 	    crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) {
1950 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar");
1951 		crypto_bignum_deinit(peer_scalar, 0);
1952 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1953 	}
1954 
1955 
1956 	crypto_bignum_deinit(sae->peer_commit_scalar, 0);
1957 	sae->peer_commit_scalar = peer_scalar;
1958 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar",
1959 		    *pos, sae->tmp->prime_len);
1960 	*pos += sae->tmp->prime_len;
1961 
1962 	return WLAN_STATUS_SUCCESS;
1963 }
1964 
1965 
sae_parse_commit_element_ecc(struct sae_data * sae,const u8 ** pos,const u8 * end)1966 static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 **pos,
1967 					const u8 *end)
1968 {
1969 	u8 prime[SAE_MAX_ECC_PRIME_LEN];
1970 
1971 	if (2 * sae->tmp->prime_len > end - *pos) {
1972 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
1973 			   "commit-element");
1974 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1975 	}
1976 
1977 	if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
1978 				 sae->tmp->prime_len) < 0)
1979 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1980 
1981 	/* element x and y coordinates < p */
1982 	if (os_memcmp(*pos, prime, sae->tmp->prime_len) >= 0 ||
1983 	    os_memcmp(*pos + sae->tmp->prime_len, prime,
1984 		      sae->tmp->prime_len) >= 0) {
1985 		wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer "
1986 			   "element");
1987 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1988 	}
1989 
1990 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)",
1991 		    *pos, sae->tmp->prime_len);
1992 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)",
1993 		    *pos + sae->tmp->prime_len, sae->tmp->prime_len);
1994 
1995 	crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0);
1996 	sae->tmp->peer_commit_element_ecc =
1997 		crypto_ec_point_from_bin(sae->tmp->ec, *pos);
1998 	if (!sae->tmp->peer_commit_element_ecc) {
1999 		wpa_printf(MSG_DEBUG, "SAE: Peer element is not a valid point");
2000 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2001 	}
2002 
2003 	if (!crypto_ec_point_is_on_curve(sae->tmp->ec,
2004 					 sae->tmp->peer_commit_element_ecc)) {
2005 		wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve");
2006 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2007 	}
2008 
2009 	*pos += 2 * sae->tmp->prime_len;
2010 
2011 	return WLAN_STATUS_SUCCESS;
2012 }
2013 
2014 
sae_parse_commit_element_ffc(struct sae_data * sae,const u8 ** pos,const u8 * end)2015 static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 **pos,
2016 					const u8 *end)
2017 {
2018 	struct crypto_bignum *res, *one;
2019 	const u8 one_bin[1] = { 0x01 };
2020 
2021 	if (sae->tmp->prime_len > end - *pos) {
2022 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
2023 			   "commit-element");
2024 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2025 	}
2026 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", *pos,
2027 		    sae->tmp->prime_len);
2028 
2029 	crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0);
2030 	sae->tmp->peer_commit_element_ffc =
2031 		crypto_bignum_init_set(*pos, sae->tmp->prime_len);
2032 	if (sae->tmp->peer_commit_element_ffc == NULL)
2033 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2034 	/* 1 < element < p - 1 */
2035 	res = crypto_bignum_init();
2036 	one = crypto_bignum_init_set(one_bin, sizeof(one_bin));
2037 	if (!res || !one ||
2038 	    crypto_bignum_sub(sae->tmp->prime, one, res) ||
2039 	    crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) ||
2040 	    crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) ||
2041 	    crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc, res) >= 0) {
2042 		crypto_bignum_deinit(res, 0);
2043 		crypto_bignum_deinit(one, 0);
2044 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer element");
2045 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2046 	}
2047 	crypto_bignum_deinit(one, 0);
2048 
2049 	/* scalar-op(r, ELEMENT) = 1 modulo p */
2050 	if (crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc,
2051 				  sae->tmp->order, sae->tmp->prime, res) < 0 ||
2052 	    !crypto_bignum_is_one(res)) {
2053 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer element (scalar-op)");
2054 		crypto_bignum_deinit(res, 0);
2055 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2056 	}
2057 	crypto_bignum_deinit(res, 0);
2058 
2059 	*pos += sae->tmp->prime_len;
2060 
2061 	return WLAN_STATUS_SUCCESS;
2062 }
2063 
2064 
sae_parse_commit_element(struct sae_data * sae,const u8 ** pos,const u8 * end)2065 static u16 sae_parse_commit_element(struct sae_data *sae, const u8 **pos,
2066 				    const u8 *end)
2067 {
2068 	if (sae->tmp->dh)
2069 		return sae_parse_commit_element_ffc(sae, pos, end);
2070 	return sae_parse_commit_element_ecc(sae, pos, end);
2071 }
2072 
2073 
sae_parse_password_identifier(struct sae_data * sae,bool h2e,const u8 ** pos,const u8 * end)2074 static int sae_parse_password_identifier(struct sae_data *sae, bool h2e,
2075 					 const u8 **pos, const u8 *end)
2076 {
2077 	const u8 *epos;
2078 	u8 len;
2079 
2080 	if (!sae_is_password_id_elem(*pos, end)) {
2081 		if (sae->tmp->pw_id) {
2082 			wpa_printf(MSG_DEBUG,
2083 				   "SAE: No Password Identifier included, but expected one (%s)",
2084 				   sae->tmp->pw_id);
2085 			return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
2086 		}
2087 		os_free(sae->tmp->parsed_pw_id);
2088 		sae->tmp->parsed_pw_id = NULL;
2089 		sae->tmp->parsed_pw_id_len = 0;
2090 		return WLAN_STATUS_SUCCESS; /* No Password Identifier */
2091 	}
2092 
2093 	epos = *pos;
2094 	epos++; /* skip IE type */
2095 	len = *epos++; /* IE length */
2096 	if (len > end - epos || len < 1)
2097 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2098 	epos++; /* skip ext ID */
2099 	len--;
2100 
2101 	if (!h2e) {
2102 		wpa_printf(MSG_DEBUG,
2103 			   "SAE: Password Identifier included, but H2E is not used");
2104 		return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
2105 	}
2106 
2107 	if (sae->no_pw_id) {
2108 		wpa_printf(MSG_DEBUG,
2109 			   "SAE: Password Identifier included, but none has been enabled");
2110 		return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
2111 	}
2112 
2113 	if (sae->tmp->pw_id &&
2114 	    (len != sae->tmp->pw_id_len ||
2115 	     os_memcmp(sae->tmp->pw_id, epos, len) != 0)) {
2116 		wpa_printf(MSG_DEBUG,
2117 			   "SAE: The included Password Identifier does not match the expected one (%s)",
2118 			   sae->tmp->pw_id);
2119 		return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
2120 	}
2121 
2122 	os_free(sae->tmp->parsed_pw_id);
2123 	sae->tmp->parsed_pw_id = os_malloc(len + 1);
2124 	if (!sae->tmp->parsed_pw_id) {
2125 		sae->tmp->parsed_pw_id_len = 0;
2126 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2127 	}
2128 	os_memcpy(sae->tmp->parsed_pw_id, epos, len);
2129 	sae->tmp->parsed_pw_id_len = len;
2130 	sae->tmp->parsed_pw_id[len] = '\0';
2131 	wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier",
2132 			  sae->tmp->parsed_pw_id, len);
2133 	*pos = epos + len;
2134 	return WLAN_STATUS_SUCCESS;
2135 }
2136 
2137 
sae_parse_rejected_groups(struct sae_data * sae,const u8 ** pos,const u8 * end)2138 static int sae_parse_rejected_groups(struct sae_data *sae,
2139 				     const u8 **pos, const u8 *end)
2140 {
2141 	const u8 *epos;
2142 	u8 len;
2143 
2144 	if (!sae_is_rejected_groups_elem(*pos, end)) {
2145 		wpabuf_free(sae->tmp->peer_rejected_groups);
2146 		sae->tmp->peer_rejected_groups = NULL;
2147 		return WLAN_STATUS_SUCCESS;
2148 	}
2149 
2150 	epos = *pos;
2151 	epos++; /* skip IE type */
2152 	len = *epos++; /* IE length */
2153 	if (len > end - epos || len < 1)
2154 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2155 	epos++; /* skip ext ID */
2156 	len--;
2157 	if (len & 1) {
2158 		wpa_printf(MSG_DEBUG,
2159 			   "SAE: Invalid length of the Rejected Groups element payload: %u",
2160 			   len);
2161 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2162 	}
2163 
2164 	wpabuf_free(sae->tmp->peer_rejected_groups);
2165 	sae->tmp->peer_rejected_groups = wpabuf_alloc(len);
2166 	if (!sae->tmp->peer_rejected_groups)
2167 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2168 	wpabuf_put_data(sae->tmp->peer_rejected_groups, epos, len);
2169 	wpa_hexdump_buf(MSG_DEBUG, "SAE: Received Rejected Groups list",
2170 			sae->tmp->peer_rejected_groups);
2171 	*pos = epos + len;
2172 	return WLAN_STATUS_SUCCESS;
2173 }
2174 
2175 
sae_parse_akm_suite_selector(struct sae_data * sae,const u8 ** pos,const u8 * end)2176 static int sae_parse_akm_suite_selector(struct sae_data *sae,
2177 					const u8 **pos, const u8 *end)
2178 {
2179 	const u8 *epos;
2180 	u8 len;
2181 
2182 	if (!sae_is_akm_suite_selector_elem(*pos, end))
2183 		return WLAN_STATUS_SUCCESS;
2184 
2185 	epos = *pos;
2186 	epos++; /* skip IE type */
2187 	len = *epos++; /* IE length */
2188 	if (len > end - epos || len < 1)
2189 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2190 	epos++; /* skip ext ID */
2191 	len--;
2192 
2193 	if (len < RSN_SELECTOR_LEN)
2194 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2195 	sae->peer_akm_suite_selector = RSN_SELECTOR_GET(epos);
2196 	wpa_printf(MSG_DEBUG, "SAE: Received AKM Suite Selector: %08x",
2197 		   sae->peer_akm_suite_selector);
2198 	*pos = epos + len;
2199 	return WLAN_STATUS_SUCCESS;
2200 }
2201 
2202 
sae_parse_commit(struct sae_data * sae,const u8 * data,size_t len,const u8 ** token,size_t * token_len,int * allowed_groups,int h2e,int * ie_offset)2203 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
2204 		     const u8 **token, size_t *token_len, int *allowed_groups,
2205 		     int h2e, int *ie_offset)
2206 {
2207 	const u8 *pos = data, *end = data + len;
2208 	u16 res;
2209 
2210 	/* Check Finite Cyclic Group */
2211 	if (end - pos < 2)
2212 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2213 	res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos));
2214 	if (res != WLAN_STATUS_SUCCESS)
2215 		return res;
2216 	pos += 2;
2217 
2218 	/* Optional Anti-Clogging Token */
2219 	sae_parse_commit_token(sae, &pos, end, token, token_len, h2e);
2220 
2221 	/* commit-scalar */
2222 	res = sae_parse_commit_scalar(sae, &pos, end);
2223 	if (res != WLAN_STATUS_SUCCESS)
2224 		return res;
2225 
2226 	/* commit-element */
2227 	res = sae_parse_commit_element(sae, &pos, end);
2228 	if (res != WLAN_STATUS_SUCCESS)
2229 		return res;
2230 
2231 	if (ie_offset)
2232 		*ie_offset = pos - data;
2233 
2234 	if (end > pos)
2235 		wpa_hexdump(MSG_DEBUG,
2236 			    "SAE: Possible elements at the end of the frame",
2237 			    pos, end - pos);
2238 
2239 	/* Optional Password Identifier element */
2240 	res = sae_parse_password_identifier(sae, h2e, &pos, end);
2241 	if (res != WLAN_STATUS_SUCCESS)
2242 		return res;
2243 
2244 	/* Conditional Rejected Groups element */
2245 	if (h2e) {
2246 		res = sae_parse_rejected_groups(sae, &pos, end);
2247 		if (res != WLAN_STATUS_SUCCESS)
2248 			return res;
2249 	} else {
2250 		wpabuf_free(sae->tmp->peer_rejected_groups);
2251 		sae->tmp->peer_rejected_groups = NULL;
2252 	}
2253 
2254 	/* Optional Anti-Clogging Token Container element */
2255 	if (h2e)
2256 		sae_parse_token_container(sae, pos, end, token, token_len);
2257 
2258 	/* Conditional AKM Suite Selector element */
2259 	res = sae_parse_akm_suite_selector(sae, &pos, end);
2260 	if (res != WLAN_STATUS_SUCCESS)
2261 		return res;
2262 
2263 	if (sae->own_akm_suite_selector &&
2264 	    sae->own_akm_suite_selector != sae->peer_akm_suite_selector) {
2265 		wpa_printf(MSG_DEBUG,
2266 			   "SAE: AKM suite selector mismatch: own=%08x peer=%08x",
2267 			   sae->own_akm_suite_selector,
2268 			   sae->peer_akm_suite_selector);
2269 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2270 	}
2271 
2272 	if (!sae->akmp) {
2273 		if (sae->peer_akm_suite_selector ==
2274 		    RSN_AUTH_KEY_MGMT_SAE_EXT_KEY)
2275 			sae->akmp = WPA_KEY_MGMT_SAE_EXT_KEY;
2276 		else if (sae->peer_akm_suite_selector ==
2277 		    RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY)
2278 			sae->akmp = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
2279 	}
2280 
2281 	if (wpa_key_mgmt_sae_ext_key(sae->akmp) && !h2e) {
2282 		wpa_printf(MSG_DEBUG,
2283 			   "SAE: Tried to use EXT-KEY AKM without H2E");
2284 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2285 	}
2286 
2287 	/*
2288 	 * Check whether peer-commit-scalar and PEER-COMMIT-ELEMENT are same as
2289 	 * the values we sent which would be evidence of a reflection attack.
2290 	 */
2291 	if (!sae->tmp->own_commit_scalar ||
2292 	    crypto_bignum_cmp(sae->tmp->own_commit_scalar,
2293 			      sae->peer_commit_scalar) != 0 ||
2294 	    (sae->tmp->dh &&
2295 	     (!sae->tmp->own_commit_element_ffc ||
2296 	      crypto_bignum_cmp(sae->tmp->own_commit_element_ffc,
2297 				sae->tmp->peer_commit_element_ffc) != 0)) ||
2298 	    (sae->tmp->ec &&
2299 	     (!sae->tmp->own_commit_element_ecc ||
2300 	      crypto_ec_point_cmp(sae->tmp->ec,
2301 				  sae->tmp->own_commit_element_ecc,
2302 				  sae->tmp->peer_commit_element_ecc) != 0)))
2303 		return WLAN_STATUS_SUCCESS; /* scalars/elements are different */
2304 
2305 	/*
2306 	 * This is a reflection attack - return special value to trigger caller
2307 	 * to silently discard the frame instead of replying with a specific
2308 	 * status code.
2309 	 */
2310 	return SAE_SILENTLY_DISCARD;
2311 }
2312 
2313 
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)2314 static int sae_cn_confirm(struct sae_data *sae, const u8 *sc,
2315 			  const struct crypto_bignum *scalar1,
2316 			  const u8 *element1, size_t element1_len,
2317 			  const struct crypto_bignum *scalar2,
2318 			  const u8 *element2, size_t element2_len,
2319 			  u8 *confirm)
2320 {
2321 	const u8 *addr[5];
2322 	size_t len[5];
2323 	u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN];
2324 
2325 	/* Confirm
2326 	 * CN(key, X, Y, Z, ...) =
2327 	 *    HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...)
2328 	 * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT,
2329 	 *              peer-commit-scalar, PEER-COMMIT-ELEMENT)
2330 	 * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar,
2331 	 *               PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT)
2332 	 */
2333 	if (crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1),
2334 				 sae->tmp->prime_len) < 0 ||
2335 	    crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2),
2336 				 sae->tmp->prime_len) < 0)
2337 		return -1;
2338 	addr[0] = sc;
2339 	len[0] = 2;
2340 	addr[1] = scalar_b1;
2341 	len[1] = sae->tmp->prime_len;
2342 	addr[2] = element1;
2343 	len[2] = element1_len;
2344 	addr[3] = scalar_b2;
2345 	len[3] = sae->tmp->prime_len;
2346 	addr[4] = element2;
2347 	len[4] = element2_len;
2348 	return hkdf_extract(sae->tmp->kck_len, sae->tmp->kck, sae->tmp->kck_len,
2349 			    5, addr, len, confirm);
2350 }
2351 
2352 
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)2353 static int sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
2354 			      const struct crypto_bignum *scalar1,
2355 			      const struct crypto_ec_point *element1,
2356 			      const struct crypto_bignum *scalar2,
2357 			      const struct crypto_ec_point *element2,
2358 			      u8 *confirm)
2359 {
2360 	u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN];
2361 	u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN];
2362 
2363 	if (crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1,
2364 				   element_b1 + sae->tmp->prime_len) < 0 ||
2365 	    crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2,
2366 				   element_b2 + sae->tmp->prime_len) < 0 ||
2367 	    sae_cn_confirm(sae, sc, scalar1, element_b1,
2368 			   2 * sae->tmp->prime_len,
2369 			   scalar2, element_b2, 2 * sae->tmp->prime_len,
2370 			   confirm) < 0)
2371 		return -1;
2372 	return 0;
2373 }
2374 
2375 
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)2376 static int sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
2377 			      const struct crypto_bignum *scalar1,
2378 			      const struct crypto_bignum *element1,
2379 			      const struct crypto_bignum *scalar2,
2380 			      const struct crypto_bignum *element2,
2381 			      u8 *confirm)
2382 {
2383 	u8 element_b1[SAE_MAX_PRIME_LEN];
2384 	u8 element_b2[SAE_MAX_PRIME_LEN];
2385 
2386 	if (crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1),
2387 				 sae->tmp->prime_len) < 0 ||
2388 	    crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2),
2389 				 sae->tmp->prime_len) < 0 ||
2390 	    sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len,
2391 			   scalar2, element_b2, sae->tmp->prime_len,
2392 			   confirm) < 0)
2393 		return -1;
2394 	return 0;
2395 }
2396 
2397 
sae_write_confirm(struct sae_data * sae,struct wpabuf * buf)2398 int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
2399 {
2400 	const u8 *sc;
2401 	size_t hash_len;
2402 	int res;
2403 
2404 	if (sae->tmp == NULL)
2405 		return -1;
2406 
2407 	hash_len = sae->tmp->kck_len;
2408 
2409 	/* Send-Confirm */
2410 	if (sae->send_confirm < 0xffff)
2411 		sae->send_confirm++;
2412 	sc = wpabuf_put(buf, 0);
2413 	wpabuf_put_le16(buf, sae->send_confirm);
2414 
2415 	if (sae->tmp->ec)
2416 		res = sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
2417 					 sae->tmp->own_commit_element_ecc,
2418 					 sae->peer_commit_scalar,
2419 					 sae->tmp->peer_commit_element_ecc,
2420 					 wpabuf_put(buf, hash_len));
2421 	else
2422 		res = sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar,
2423 					 sae->tmp->own_commit_element_ffc,
2424 					 sae->peer_commit_scalar,
2425 					 sae->tmp->peer_commit_element_ffc,
2426 					 wpabuf_put(buf, hash_len));
2427 	if (res)
2428 		return res;
2429 
2430 #ifdef CONFIG_SAE_PK
2431 	if (sae_write_confirm_pk(sae, buf) < 0)
2432 		return -1;
2433 #endif /* CONFIG_SAE_PK */
2434 
2435 	return 0;
2436 }
2437 
2438 
sae_check_confirm(struct sae_data * sae,const u8 * data,size_t len,int * ie_offset)2439 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len,
2440 		      int *ie_offset)
2441 {
2442 	u8 verifier[SAE_MAX_HASH_LEN];
2443 	size_t hash_len;
2444 
2445 	if (!sae->tmp)
2446 		return -1;
2447 
2448 	hash_len = sae->tmp->kck_len;
2449 	if (len < 2 + hash_len) {
2450 		wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
2451 		return -1;
2452 	}
2453 
2454 	wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data));
2455 
2456 	if (!sae->peer_commit_scalar || !sae->tmp->own_commit_scalar) {
2457 		wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available");
2458 		return -1;
2459 	}
2460 
2461 	if (sae->tmp->ec) {
2462 		if (!sae->tmp->peer_commit_element_ecc ||
2463 		    !sae->tmp->own_commit_element_ecc ||
2464 		    sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar,
2465 				       sae->tmp->peer_commit_element_ecc,
2466 				       sae->tmp->own_commit_scalar,
2467 				       sae->tmp->own_commit_element_ecc,
2468 				       verifier) < 0)
2469 			return -1;
2470 	} else {
2471 		if (!sae->tmp->peer_commit_element_ffc ||
2472 		    !sae->tmp->own_commit_element_ffc ||
2473 		    sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar,
2474 				       sae->tmp->peer_commit_element_ffc,
2475 				       sae->tmp->own_commit_scalar,
2476 				       sae->tmp->own_commit_element_ffc,
2477 				       verifier) < 0)
2478 			return -1;
2479 	}
2480 
2481 	if (os_memcmp_const(verifier, data + 2, hash_len) != 0) {
2482 		wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
2483 		wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
2484 			    data + 2, hash_len);
2485 		wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
2486 			    verifier, hash_len);
2487 		return -1;
2488 	}
2489 
2490 #ifdef CONFIG_SAE_PK
2491 	if (sae_check_confirm_pk(sae, data + 2 + hash_len,
2492 				 len - 2 - hash_len) < 0)
2493 		return -1;
2494 #endif /* CONFIG_SAE_PK */
2495 
2496 	/* 2 bytes are for send-confirm, then the hash, followed by IEs */
2497 	if (ie_offset)
2498 		*ie_offset = 2 + hash_len;
2499 
2500 	return 0;
2501 }
2502 
2503 
sae_state_txt(enum sae_state state)2504 const char * sae_state_txt(enum sae_state state)
2505 {
2506 	switch (state) {
2507 	case SAE_NOTHING:
2508 		return "Nothing";
2509 	case SAE_COMMITTED:
2510 		return "Committed";
2511 	case SAE_CONFIRMED:
2512 		return "Confirmed";
2513 	case SAE_ACCEPTED:
2514 		return "Accepted";
2515 	}
2516 	return "?";
2517 }
2518