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