• 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 	debug_print_bignum("SSWU: x1 = CSEL(l, x1a, x1b)", x1, prime_len);
717 
718 	/* gx1 = x1^3 + a * x1 + b */
719 	if (crypto_bignum_exptmod(x1, three, prime, t1) < 0 ||
720 	    crypto_bignum_mulmod(a, x1, prime, t2) < 0 ||
721 	    crypto_bignum_addmod(t1, t2, prime, t1) < 0 ||
722 	    crypto_bignum_addmod(t1, b, prime, gx1) < 0)
723 		goto fail;
724 	debug_print_bignum("SSWU: gx1 = x1^3 + a * x1 + b", gx1, prime_len);
725 
726 	/* x2 = z * u^2 * x1 */
727 	if (crypto_bignum_mulmod(z, u2, prime, t1) < 0 ||
728 	    crypto_bignum_mulmod(t1, x1, prime, x2) < 0)
729 		goto fail;
730 	debug_print_bignum("SSWU: x2 = z * u^2 * x1", x2, prime_len);
731 
732 	/* gx2 = x2^3 + a * x2 + b */
733 	if (crypto_bignum_exptmod(x2, three, prime, t1) < 0 ||
734 	    crypto_bignum_mulmod(a, x2, prime, t2) < 0 ||
735 	    crypto_bignum_addmod(t1, t2, prime, t1) < 0 ||
736 	    crypto_bignum_addmod(t1, b, prime, gx2) < 0)
737 		goto fail;
738 	debug_print_bignum("SSWU: gx2 = x2^3 + a * x2 + b", gx2, prime_len);
739 
740 	/* l = gx1 is a quadratic residue modulo p
741 	 * --> gx1^((p-1)/2) modulo p is zero or one */
742 	if (crypto_bignum_sub(prime, one, t1) < 0 ||
743 	    crypto_bignum_rshift(t1, 1, t1) < 0 ||
744 	    crypto_bignum_exptmod(gx1, t1, prime, t1) < 0)
745 		goto fail;
746 	debug_print_bignum("SSWU: gx1^((p-1)/2) modulo p", t1, prime_len);
747 	is_qr = const_time_eq(crypto_bignum_is_zero(t1) |
748 			      crypto_bignum_is_one(t1), 1);
749 
750 	/* v = CSEL(l, gx1, gx2) */
751 	if (crypto_bignum_to_bin(gx1, bin1, sizeof(bin1), prime_len) < 0 ||
752 	    crypto_bignum_to_bin(gx2, bin2, sizeof(bin2), prime_len) < 0)
753 		goto fail;
754 	const_time_select_bin(is_qr, bin1, bin2, prime_len, bin);
755 	v = crypto_bignum_init_set(bin, prime_len);
756 	debug_print_bignum("SSWU: v = CSEL(l, gx1, gx2)", v, prime_len);
757 
758 	/* x = CSEL(l, x1, x2) */
759 	if (crypto_bignum_to_bin(x1, bin1, sizeof(bin1), prime_len) < 0 ||
760 	    crypto_bignum_to_bin(x2, bin2, sizeof(bin2), prime_len) < 0)
761 		goto fail;
762 	const_time_select_bin(is_qr, bin1, bin2, prime_len, x_y);
763 	wpa_hexdump_key(MSG_DEBUG, "SSWU: x = CSEL(l, x1, x2)", x_y, prime_len);
764 
765 	/* y = sqrt(v)
766 	 * For prime p such that p = 3 mod 4 --> v^((p+1)/4) */
767 	if (crypto_bignum_to_bin(prime, bin1, sizeof(bin1), prime_len) < 0)
768 		goto fail;
769 	if ((bin1[prime_len - 1] & 0x03) != 3) {
770 		wpa_printf(MSG_DEBUG, "SSWU: prime does not have p = 3 mod 4");
771 		goto fail;
772 	}
773 	y = crypto_bignum_init();
774 	if (!y ||
775 	    crypto_bignum_add(prime, one, t1) < 0 ||
776 	    crypto_bignum_rshift(t1, 2, t1) < 0 ||
777 	    crypto_bignum_exptmod(v, t1, prime, y) < 0)
778 		goto fail;
779 	debug_print_bignum("SSWU: y = sqrt(v)", y, prime_len);
780 
781 	/* l = CEQ(LSB(u), LSB(y)) */
782 	if (crypto_bignum_to_bin(u, bin1, sizeof(bin1), prime_len) < 0 ||
783 	    crypto_bignum_to_bin(y, bin2, sizeof(bin2), prime_len) < 0)
784 		goto fail;
785 	is_eq = const_time_eq(bin1[prime_len - 1] & 0x01,
786 			      bin2[prime_len - 1] & 0x01);
787 
788 	/* P = CSEL(l, (x,y), (x, p-y)) */
789 	if (crypto_bignum_sub(prime, y, t1) < 0)
790 		goto fail;
791 	debug_print_bignum("SSWU: p - y", t1, prime_len);
792 	if (crypto_bignum_to_bin(y, bin1, sizeof(bin1), prime_len) < 0 ||
793 	    crypto_bignum_to_bin(t1, bin2, sizeof(bin2), prime_len) < 0)
794 		goto fail;
795 	const_time_select_bin(is_eq, bin1, bin2, prime_len, &x_y[prime_len]);
796 
797 	/* output P */
798 	wpa_hexdump_key(MSG_DEBUG, "SSWU: P.x", x_y, prime_len);
799 	wpa_hexdump_key(MSG_DEBUG, "SSWU: P.y", &x_y[prime_len], prime_len);
800 	p = crypto_ec_point_from_bin(ec, x_y);
801 
802 fail:
803 	crypto_bignum_deinit(u2, 1);
804 	crypto_bignum_deinit(t1, 1);
805 	crypto_bignum_deinit(t2, 1);
806 	crypto_bignum_deinit(z, 0);
807 	crypto_bignum_deinit(t, 1);
808 	crypto_bignum_deinit(x1a, 1);
809 	crypto_bignum_deinit(x1b, 1);
810 	crypto_bignum_deinit(x1, 1);
811 	crypto_bignum_deinit(x2, 1);
812 	crypto_bignum_deinit(gx1, 1);
813 	crypto_bignum_deinit(gx2, 1);
814 	crypto_bignum_deinit(y, 1);
815 	crypto_bignum_deinit(v, 1);
816 	crypto_bignum_deinit(zero, 0);
817 	crypto_bignum_deinit(one, 0);
818 	crypto_bignum_deinit(two, 0);
819 	crypto_bignum_deinit(three, 0);
820 	forced_memzero(bin, sizeof(bin));
821 	forced_memzero(bin1, sizeof(bin1));
822 	forced_memzero(bin2, sizeof(bin2));
823 	forced_memzero(x_y, sizeof(x_y));
824 	return p;
825 }
826 
827 
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)828 static int sae_pwd_seed(size_t hash_len, const u8 *ssid, size_t ssid_len,
829 			const u8 *password, size_t password_len,
830 			const char *identifier, u8 *pwd_seed)
831 {
832 	const u8 *addr[2];
833 	size_t len[2];
834 	size_t num_elem;
835 
836 	/* pwd-seed = HKDF-Extract(ssid, password [ || identifier ]) */
837 	addr[0] = password;
838 	len[0] = password_len;
839 	num_elem = 1;
840 	wpa_hexdump_ascii(MSG_DEBUG, "SAE: SSID", ssid, ssid_len);
841 	wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
842 			      password, password_len);
843 	if (identifier) {
844 		wpa_printf(MSG_DEBUG, "SAE: password identifier: %s",
845 			   identifier);
846 		addr[num_elem] = (const u8 *) identifier;
847 		len[num_elem] = os_strlen(identifier);
848 		num_elem++;
849 	}
850 	if (hkdf_extract(hash_len, ssid, ssid_len, num_elem, addr, len,
851 			 pwd_seed) < 0)
852 		return -1;
853 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, hash_len);
854 	return 0;
855 }
856 
857 
sae_ecc_prime_len_2_hash_len(size_t prime_len)858 size_t sae_ecc_prime_len_2_hash_len(size_t prime_len)
859 {
860 	if (prime_len <= 256 / 8)
861 		return 32;
862 	if (prime_len <= 384 / 8)
863 		return 48;
864 	return 64;
865 }
866 
867 
868 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)869 sae_derive_pt_ecc(struct crypto_ec *ec, int group,
870 		  const u8 *ssid, size_t ssid_len,
871 		  const u8 *password, size_t password_len,
872 		  const char *identifier)
873 {
874 	u8 pwd_seed[64];
875 	u8 pwd_value[SAE_MAX_ECC_PRIME_LEN * 2];
876 	size_t pwd_value_len, hash_len, prime_len;
877 	const struct crypto_bignum *prime;
878 	struct crypto_bignum *bn = NULL;
879 	struct crypto_ec_point *p1 = NULL, *p2 = NULL, *pt = NULL;
880 
881 	prime = crypto_ec_get_prime(ec);
882 	prime_len = crypto_ec_prime_len(ec);
883 	if (prime_len > SAE_MAX_ECC_PRIME_LEN)
884 		goto fail;
885 	hash_len = sae_ecc_prime_len_2_hash_len(prime_len);
886 
887 	/* len = olen(p) + ceil(olen(p)/2) */
888 	pwd_value_len = prime_len + (prime_len + 1) / 2;
889 
890 	if (sae_pwd_seed(hash_len, ssid, ssid_len, password, password_len,
891 			 identifier, pwd_seed) < 0)
892 		goto fail;
893 
894 	/* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element u1 P1", len)
895 	 */
896 	if (hkdf_expand(hash_len, pwd_seed, hash_len,
897 			"SAE Hash to Element u1 P1", pwd_value, pwd_value_len) <
898 	    0)
899 		goto fail;
900 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value (u1 P1)",
901 			pwd_value, pwd_value_len);
902 
903 	/* u1 = pwd-value modulo p */
904 	bn = crypto_bignum_init_set(pwd_value, pwd_value_len);
905 	if (!bn || crypto_bignum_mod(bn, prime, bn) < 0 ||
906 	    crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value),
907 				 prime_len) < 0)
908 		goto fail;
909 	wpa_hexdump_key(MSG_DEBUG, "SAE: u1", pwd_value, prime_len);
910 
911 	/* P1 = SSWU(u1) */
912 	p1 = sswu(ec, group, bn);
913 	if (!p1)
914 		goto fail;
915 
916 	/* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element u2 P2", len)
917 	 */
918 	if (hkdf_expand(hash_len, pwd_seed, hash_len,
919 			"SAE Hash to Element u2 P2", pwd_value,
920 			pwd_value_len) < 0)
921 		goto fail;
922 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value (u2 P2)",
923 			pwd_value, pwd_value_len);
924 
925 	/* u2 = pwd-value modulo p */
926 	crypto_bignum_deinit(bn, 1);
927 	bn = crypto_bignum_init_set(pwd_value, pwd_value_len);
928 	if (!bn || crypto_bignum_mod(bn, prime, bn) < 0 ||
929 	    crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value),
930 				 prime_len) < 0)
931 		goto fail;
932 	wpa_hexdump_key(MSG_DEBUG, "SAE: u2", pwd_value, prime_len);
933 
934 	/* P2 = SSWU(u2) */
935 	p2 = sswu(ec, group, bn);
936 	if (!p2)
937 		goto fail;
938 
939 	/* PT = elem-op(P1, P2) */
940 	pt = crypto_ec_point_init(ec);
941 	if (!pt)
942 		goto fail;
943 	if (crypto_ec_point_add(ec, p1, p2, pt) < 0) {
944 		crypto_ec_point_deinit(pt, 1);
945 		pt = NULL;
946 	}
947 
948 fail:
949 	forced_memzero(pwd_seed, sizeof(pwd_seed));
950 	forced_memzero(pwd_value, sizeof(pwd_value));
951 	crypto_bignum_deinit(bn, 1);
952 	crypto_ec_point_deinit(p1, 1);
953 	crypto_ec_point_deinit(p2, 1);
954 	return pt;
955 }
956 
957 
sae_ffc_prime_len_2_hash_len(size_t prime_len)958 size_t sae_ffc_prime_len_2_hash_len(size_t prime_len)
959 {
960 	if (prime_len <= 2048 / 8)
961 		return 32;
962 	if (prime_len <= 3072 / 8)
963 		return 48;
964 	return 64;
965 }
966 
967 
968 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)969 sae_derive_pt_ffc(const struct dh_group *dh, int group,
970 		  const u8 *ssid, size_t ssid_len,
971 		  const u8 *password, size_t password_len,
972 		  const char *identifier)
973 {
974 	size_t hash_len, prime_len, pwd_value_len;
975 	struct crypto_bignum *prime, *order;
976 	struct crypto_bignum *one = NULL, *two = NULL, *bn = NULL, *tmp = NULL,
977 		*pt = NULL;
978 	u8 pwd_seed[64];
979 	u8 pwd_value[SAE_MAX_PRIME_LEN + SAE_MAX_PRIME_LEN / 2];
980 
981 	prime = crypto_bignum_init_set(dh->prime, dh->prime_len);
982 	order = crypto_bignum_init_set(dh->order, dh->order_len);
983 	if (!prime || !order)
984 		goto fail;
985 	prime_len = dh->prime_len;
986 	if (prime_len > SAE_MAX_PRIME_LEN)
987 		goto fail;
988 	hash_len = sae_ffc_prime_len_2_hash_len(prime_len);
989 
990 	/* len = olen(p) + ceil(olen(p)/2) */
991 	pwd_value_len = prime_len + (prime_len + 1) / 2;
992 	if (pwd_value_len > sizeof(pwd_value))
993 		goto fail;
994 
995 	if (sae_pwd_seed(hash_len, ssid, ssid_len, password, password_len,
996 			 identifier, pwd_seed) < 0)
997 		goto fail;
998 
999 	/* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element", len) */
1000 	if (hkdf_expand(hash_len, pwd_seed, hash_len,
1001 			"SAE Hash to Element", pwd_value, pwd_value_len) < 0)
1002 		goto fail;
1003 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
1004 			pwd_value, pwd_value_len);
1005 
1006 	/* pwd-value = (pwd-value modulo (p-2)) + 2 */
1007 	bn = crypto_bignum_init_set(pwd_value, pwd_value_len);
1008 	one = crypto_bignum_init_uint(1);
1009 	two = crypto_bignum_init_uint(2);
1010 	tmp = crypto_bignum_init();
1011 	if (!bn || !one || !two || !tmp ||
1012 	    crypto_bignum_sub(prime, two, tmp) < 0 ||
1013 	    crypto_bignum_mod(bn, tmp, bn) < 0 ||
1014 	    crypto_bignum_add(bn, two, bn) < 0 ||
1015 	    crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value),
1016 				 prime_len) < 0)
1017 		goto fail;
1018 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value(reduced)",
1019 			pwd_value, prime_len);
1020 
1021 	/* PT = pwd-value^((p-1)/q) modulo p */
1022 	pt = crypto_bignum_init();
1023 	if (!pt ||
1024 	    crypto_bignum_sub(prime, one, tmp) < 0 ||
1025 	    crypto_bignum_div(tmp, order, tmp) < 0 ||
1026 	    crypto_bignum_exptmod(bn, tmp, prime, pt) < 0) {
1027 		crypto_bignum_deinit(pt, 1);
1028 		pt = NULL;
1029 		goto fail;
1030 	}
1031 	debug_print_bignum("SAE: PT", pt, prime_len);
1032 
1033 fail:
1034 	forced_memzero(pwd_seed, sizeof(pwd_seed));
1035 	forced_memzero(pwd_value, sizeof(pwd_value));
1036 	crypto_bignum_deinit(bn, 1);
1037 	crypto_bignum_deinit(tmp, 1);
1038 	crypto_bignum_deinit(one, 0);
1039 	crypto_bignum_deinit(two, 0);
1040 	crypto_bignum_deinit(prime, 0);
1041 	crypto_bignum_deinit(order, 0);
1042 	return pt;
1043 }
1044 
1045 
1046 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)1047 sae_derive_pt_group(int group, const u8 *ssid, size_t ssid_len,
1048 		    const u8 *password, size_t password_len,
1049 		    const char *identifier)
1050 {
1051 	struct sae_pt *pt;
1052 
1053 	wpa_printf(MSG_DEBUG, "SAE: Derive PT - group %d", group);
1054 
1055 	pt = os_zalloc(sizeof(*pt));
1056 	if (!pt)
1057 		return NULL;
1058 
1059 	pt->group = group;
1060 	pt->ec = crypto_ec_init(group);
1061 	if (pt->ec) {
1062 		pt->ecc_pt = sae_derive_pt_ecc(pt->ec, group, ssid, ssid_len,
1063 					       password, password_len,
1064 					       identifier);
1065 		if (!pt->ecc_pt) {
1066 			wpa_printf(MSG_DEBUG, "SAE: Failed to derive PT");
1067 			goto fail;
1068 		}
1069 
1070 		return pt;
1071 	}
1072 
1073 	pt->dh = dh_groups_get(group);
1074 	if (!pt->dh) {
1075 		wpa_printf(MSG_DEBUG, "SAE: Unsupported group %d", group);
1076 		goto fail;
1077 	}
1078 
1079 	pt->ffc_pt = sae_derive_pt_ffc(pt->dh, group, ssid, ssid_len,
1080 				       password, password_len, identifier);
1081 	if (!pt->ffc_pt) {
1082 		wpa_printf(MSG_DEBUG, "SAE: Failed to derive PT");
1083 		goto fail;
1084 	}
1085 
1086 	return pt;
1087 fail:
1088 	sae_deinit_pt(pt);
1089 	return NULL;
1090 }
1091 
1092 
sae_derive_pt(int * groups,const u8 * ssid,size_t ssid_len,const u8 * password,size_t password_len,const char * identifier)1093 struct sae_pt * sae_derive_pt(int *groups, const u8 *ssid, size_t ssid_len,
1094 			      const u8 *password, size_t password_len,
1095 			      const char *identifier)
1096 {
1097 	struct sae_pt *pt = NULL, *last = NULL, *tmp;
1098 	int default_groups[] = { 19, 0 };
1099 	int i;
1100 
1101 	if (!groups)
1102 		groups = default_groups;
1103 	for (i = 0; groups[i] > 0; i++) {
1104 		tmp = sae_derive_pt_group(groups[i], ssid, ssid_len, password,
1105 					  password_len, identifier);
1106 		if (!tmp)
1107 			continue;
1108 
1109 		if (last)
1110 			last->next = tmp;
1111 		else
1112 			pt = tmp;
1113 		last = tmp;
1114 	}
1115 
1116 	return pt;
1117 }
1118 
1119 
sae_max_min_addr(const u8 * addr[],size_t len[],const u8 * addr1,const u8 * addr2)1120 static void sae_max_min_addr(const u8 *addr[], size_t len[],
1121 			     const u8 *addr1, const u8 *addr2)
1122 {
1123 	len[0] = ETH_ALEN;
1124 	len[1] = ETH_ALEN;
1125 	if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) {
1126 		addr[0] = addr1;
1127 		addr[1] = addr2;
1128 	} else {
1129 		addr[0] = addr2;
1130 		addr[1] = addr1;
1131 	}
1132 }
1133 
1134 
1135 struct crypto_ec_point *
sae_derive_pwe_from_pt_ecc(const struct sae_pt * pt,const u8 * addr1,const u8 * addr2)1136 sae_derive_pwe_from_pt_ecc(const struct sae_pt *pt,
1137 			   const u8 *addr1, const u8 *addr2)
1138 {
1139 	u8 bin[SAE_MAX_ECC_PRIME_LEN * 2];
1140 	size_t prime_len;
1141 	const u8 *addr[2];
1142 	size_t len[2];
1143 	u8 salt[64], hash[64];
1144 	size_t hash_len;
1145 	const struct crypto_bignum *order;
1146 	struct crypto_bignum *tmp = NULL, *val = NULL, *one = NULL;
1147 	struct crypto_ec_point *pwe = NULL;
1148 
1149 	wpa_printf(MSG_DEBUG, "SAE: Derive PWE from PT");
1150 	prime_len = crypto_ec_prime_len(pt->ec);
1151 	if (crypto_ec_point_to_bin(pt->ec, pt->ecc_pt,
1152 				   bin, bin + prime_len) < 0)
1153 		return NULL;
1154 	wpa_hexdump_key(MSG_DEBUG, "SAE: PT.x", bin, prime_len);
1155 	wpa_hexdump_key(MSG_DEBUG, "SAE: PT.y", bin + prime_len, prime_len);
1156 
1157 	sae_max_min_addr(addr, len, addr1, addr2);
1158 
1159 	/* val = H(0^n,
1160 	 *         MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC)) */
1161 	wpa_printf(MSG_DEBUG, "SAE: val = H(0^n, MAX(addrs) || MIN(addrs))");
1162 	hash_len = sae_ecc_prime_len_2_hash_len(prime_len);
1163 	os_memset(salt, 0, hash_len);
1164 	if (hkdf_extract(hash_len, salt, hash_len, 2, addr, len, hash) < 0)
1165 		goto fail;
1166 	wpa_hexdump(MSG_DEBUG, "SAE: val", hash, hash_len);
1167 
1168 	/* val = val modulo (q - 1) + 1 */
1169 	order = crypto_ec_get_order(pt->ec);
1170 	tmp = crypto_bignum_init();
1171 	val = crypto_bignum_init_set(hash, hash_len);
1172 	one = crypto_bignum_init_uint(1);
1173 	if (!tmp || !val || !one ||
1174 	    crypto_bignum_sub(order, one, tmp) < 0 ||
1175 	    crypto_bignum_mod(val, tmp, val) < 0 ||
1176 	    crypto_bignum_add(val, one, val) < 0)
1177 		goto fail;
1178 	debug_print_bignum("SAE: val(reduced to 1..q-1)", val, prime_len);
1179 
1180 	/* PWE = scalar-op(val, PT) */
1181 	pwe = crypto_ec_point_init(pt->ec);
1182 	if (!pwe ||
1183 	    crypto_ec_point_mul(pt->ec, pt->ecc_pt, val, pwe) < 0 ||
1184 	    crypto_ec_point_to_bin(pt->ec, pwe, bin, bin + prime_len) < 0) {
1185 		crypto_ec_point_deinit(pwe, 1);
1186 		pwe = NULL;
1187 		goto fail;
1188 	}
1189 	wpa_hexdump_key(MSG_DEBUG, "SAE: PWE.x", bin, prime_len);
1190 	wpa_hexdump_key(MSG_DEBUG, "SAE: PWE.y", bin + prime_len, prime_len);
1191 
1192 fail:
1193 	crypto_bignum_deinit(tmp, 1);
1194 	crypto_bignum_deinit(val, 1);
1195 	crypto_bignum_deinit(one, 0);
1196 	return pwe;
1197 }
1198 
1199 
1200 struct crypto_bignum *
sae_derive_pwe_from_pt_ffc(const struct sae_pt * pt,const u8 * addr1,const u8 * addr2)1201 sae_derive_pwe_from_pt_ffc(const struct sae_pt *pt,
1202 			   const u8 *addr1, const u8 *addr2)
1203 {
1204 	size_t prime_len;
1205 	const u8 *addr[2];
1206 	size_t len[2];
1207 	u8 salt[64], hash[64];
1208 	size_t hash_len;
1209 	struct crypto_bignum *tmp = NULL, *val = NULL, *one = NULL;
1210 	struct crypto_bignum *pwe = NULL, *order = NULL, *prime = NULL;
1211 
1212 	wpa_printf(MSG_DEBUG, "SAE: Derive PWE from PT");
1213 	prime = crypto_bignum_init_set(pt->dh->prime, pt->dh->prime_len);
1214 	order = crypto_bignum_init_set(pt->dh->order, pt->dh->order_len);
1215 	if (!prime || !order)
1216 		goto fail;
1217 	prime_len = pt->dh->prime_len;
1218 
1219 	sae_max_min_addr(addr, len, addr1, addr2);
1220 
1221 	/* val = H(0^n,
1222 	 *         MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC)) */
1223 	wpa_printf(MSG_DEBUG, "SAE: val = H(0^n, MAX(addrs) || MIN(addrs))");
1224 	hash_len = sae_ffc_prime_len_2_hash_len(prime_len);
1225 	os_memset(salt, 0, hash_len);
1226 	if (hkdf_extract(hash_len, salt, hash_len, 2, addr, len, hash) < 0)
1227 		goto fail;
1228 	wpa_hexdump(MSG_DEBUG, "SAE: val", hash, hash_len);
1229 
1230 	/* val = val modulo (q - 1) + 1 */
1231 	tmp = crypto_bignum_init();
1232 	val = crypto_bignum_init_set(hash, hash_len);
1233 	one = crypto_bignum_init_uint(1);
1234 	if (!tmp || !val || !one ||
1235 	    crypto_bignum_sub(order, one, tmp) < 0 ||
1236 	    crypto_bignum_mod(val, tmp, val) < 0 ||
1237 	    crypto_bignum_add(val, one, val) < 0)
1238 		goto fail;
1239 	debug_print_bignum("SAE: val(reduced to 1..q-1)", val, prime_len);
1240 
1241 	/* PWE = scalar-op(val, PT) */
1242 	pwe = crypto_bignum_init();
1243 	if (!pwe || crypto_bignum_exptmod(pt->ffc_pt, val, prime, pwe) < 0) {
1244 		crypto_bignum_deinit(pwe, 1);
1245 		pwe = NULL;
1246 		goto fail;
1247 	}
1248 	debug_print_bignum("SAE: PWE", pwe, prime_len);
1249 
1250 fail:
1251 	crypto_bignum_deinit(tmp, 1);
1252 	crypto_bignum_deinit(val, 1);
1253 	crypto_bignum_deinit(one, 0);
1254 	crypto_bignum_deinit(prime, 0);
1255 	crypto_bignum_deinit(order, 0);
1256 	return pwe;
1257 }
1258 
1259 
sae_deinit_pt(struct sae_pt * pt)1260 void sae_deinit_pt(struct sae_pt *pt)
1261 {
1262 	struct sae_pt *prev;
1263 
1264 	while (pt) {
1265 		crypto_ec_point_deinit(pt->ecc_pt, 1);
1266 		crypto_bignum_deinit(pt->ffc_pt, 1);
1267 		crypto_ec_deinit(pt->ec);
1268 		prev = pt;
1269 		pt = pt->next;
1270 		os_free(prev);
1271 	}
1272 }
1273 
1274 
sae_derive_commit_element_ecc(struct sae_data * sae,struct crypto_bignum * mask)1275 static int sae_derive_commit_element_ecc(struct sae_data *sae,
1276 					 struct crypto_bignum *mask)
1277 {
1278 	/* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
1279 	if (!sae->tmp->own_commit_element_ecc) {
1280 		sae->tmp->own_commit_element_ecc =
1281 			crypto_ec_point_init(sae->tmp->ec);
1282 		if (!sae->tmp->own_commit_element_ecc)
1283 			return -1;
1284 	}
1285 
1286 	if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, mask,
1287 				sae->tmp->own_commit_element_ecc) < 0 ||
1288 	    crypto_ec_point_invert(sae->tmp->ec,
1289 				   sae->tmp->own_commit_element_ecc) < 0) {
1290 		wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
1291 		return -1;
1292 	}
1293 
1294 	return 0;
1295 }
1296 
1297 
sae_derive_commit_element_ffc(struct sae_data * sae,struct crypto_bignum * mask)1298 static int sae_derive_commit_element_ffc(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_ffc) {
1303 		sae->tmp->own_commit_element_ffc = crypto_bignum_init();
1304 		if (!sae->tmp->own_commit_element_ffc)
1305 			return -1;
1306 	}
1307 
1308 	if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, mask, sae->tmp->prime,
1309 				  sae->tmp->own_commit_element_ffc) < 0 ||
1310 	    crypto_bignum_inverse(sae->tmp->own_commit_element_ffc,
1311 				  sae->tmp->prime,
1312 				  sae->tmp->own_commit_element_ffc) < 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(struct sae_data * sae)1321 static int sae_derive_commit(struct sae_data *sae)
1322 {
1323 	struct crypto_bignum *mask;
1324 	int ret;
1325 
1326 	mask = crypto_bignum_init();
1327 	if (!sae->tmp->sae_rand)
1328 		sae->tmp->sae_rand = crypto_bignum_init();
1329 	if (!sae->tmp->own_commit_scalar)
1330 		sae->tmp->own_commit_scalar = crypto_bignum_init();
1331 	ret = !mask || !sae->tmp->sae_rand || !sae->tmp->own_commit_scalar ||
1332 		dragonfly_generate_scalar(sae->tmp->order, sae->tmp->sae_rand,
1333 					  mask,
1334 					  sae->tmp->own_commit_scalar) < 0 ||
1335 		(sae->tmp->ec &&
1336 		 sae_derive_commit_element_ecc(sae, mask) < 0) ||
1337 		(sae->tmp->dh &&
1338 		 sae_derive_commit_element_ffc(sae, mask) < 0);
1339 	crypto_bignum_deinit(mask, 1);
1340 	return ret ? -1 : 0;
1341 }
1342 
1343 
sae_prepare_commit(const u8 * addr1,const u8 * addr2,const u8 * password,size_t password_len,const char * identifier,struct sae_data * sae)1344 int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
1345 		       const u8 *password, size_t password_len,
1346 		       const char *identifier, struct sae_data *sae)
1347 {
1348 	if (sae->tmp == NULL ||
1349 	    (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
1350 						password_len,
1351 						identifier) < 0) ||
1352 	    (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
1353 						password_len,
1354 						identifier) < 0))
1355 		return -1;
1356 
1357 	sae->tmp->h2e = 0;
1358 	return sae_derive_commit(sae);
1359 }
1360 
1361 
sae_prepare_commit_pt(struct sae_data * sae,const struct sae_pt * pt,const u8 * addr1,const u8 * addr2,int * rejected_groups)1362 int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
1363 			  const u8 *addr1, const u8 *addr2,
1364 			  int *rejected_groups)
1365 {
1366 	if (!sae->tmp)
1367 		return -1;
1368 
1369 	while (pt) {
1370 		if (pt->group == sae->group)
1371 			break;
1372 		pt = pt->next;
1373 	}
1374 	if (!pt) {
1375 		wpa_printf(MSG_INFO, "SAE: Could not find PT for group %u",
1376 			   sae->group);
1377 		return -1;
1378 	}
1379 
1380 	sae->tmp->own_addr_higher = os_memcmp(addr1, addr2, ETH_ALEN) > 0;
1381 	wpabuf_free(sae->tmp->own_rejected_groups);
1382 	sae->tmp->own_rejected_groups = NULL;
1383 	if (rejected_groups) {
1384 		int count, i;
1385 		struct wpabuf *groups;
1386 
1387 		count = int_array_len(rejected_groups);
1388 		groups = wpabuf_alloc(count * 2);
1389 		if (!groups)
1390 			return -1;
1391 		for (i = 0; i < count; i++)
1392 			wpabuf_put_le16(groups, rejected_groups[i]);
1393 		sae->tmp->own_rejected_groups = groups;
1394 	}
1395 
1396 	if (pt->ec) {
1397 		crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1);
1398 		sae->tmp->pwe_ecc = sae_derive_pwe_from_pt_ecc(pt, addr1,
1399 							       addr2);
1400 		if (!sae->tmp->pwe_ecc)
1401 			return -1;
1402 	}
1403 
1404 	if (pt->dh) {
1405 		crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
1406 		sae->tmp->pwe_ffc = sae_derive_pwe_from_pt_ffc(pt, addr1,
1407 							       addr2);
1408 		if (!sae->tmp->pwe_ffc)
1409 			return -1;
1410 	}
1411 
1412 	sae->tmp->h2e = 1;
1413 	return sae_derive_commit(sae);
1414 }
1415 
1416 
sae_derive_k_ecc(struct sae_data * sae,u8 * k)1417 static int sae_derive_k_ecc(struct sae_data *sae, u8 *k)
1418 {
1419 	struct crypto_ec_point *K;
1420 	int ret = -1;
1421 
1422 	K = crypto_ec_point_init(sae->tmp->ec);
1423 	if (K == NULL)
1424 		goto fail;
1425 
1426 	/*
1427 	 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
1428 	 *                                        PEER-COMMIT-ELEMENT)))
1429 	 * If K is identity element (point-at-infinity), reject
1430 	 * k = F(K) (= x coordinate)
1431 	 */
1432 
1433 	if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc,
1434 				sae->peer_commit_scalar, K) < 0 ||
1435 	    crypto_ec_point_add(sae->tmp->ec, K,
1436 				sae->tmp->peer_commit_element_ecc, K) < 0 ||
1437 	    crypto_ec_point_mul(sae->tmp->ec, K, sae->tmp->sae_rand, K) < 0 ||
1438 	    crypto_ec_point_is_at_infinity(sae->tmp->ec, K) ||
1439 	    crypto_ec_point_to_bin(sae->tmp->ec, K, k, NULL) < 0) {
1440 		wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
1441 		goto fail;
1442 	}
1443 
1444 	wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len);
1445 
1446 	ret = 0;
1447 fail:
1448 	crypto_ec_point_deinit(K, 1);
1449 	return ret;
1450 }
1451 
1452 
sae_derive_k_ffc(struct sae_data * sae,u8 * k)1453 static int sae_derive_k_ffc(struct sae_data *sae, u8 *k)
1454 {
1455 	struct crypto_bignum *K;
1456 	int ret = -1;
1457 
1458 	K = crypto_bignum_init();
1459 	if (K == NULL)
1460 		goto fail;
1461 
1462 	/*
1463 	 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
1464 	 *                                        PEER-COMMIT-ELEMENT)))
1465 	 * If K is identity element (one), reject.
1466 	 * k = F(K) (= x coordinate)
1467 	 */
1468 
1469 	if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, sae->peer_commit_scalar,
1470 				  sae->tmp->prime, K) < 0 ||
1471 	    crypto_bignum_mulmod(K, sae->tmp->peer_commit_element_ffc,
1472 				 sae->tmp->prime, K) < 0 ||
1473 	    crypto_bignum_exptmod(K, sae->tmp->sae_rand, sae->tmp->prime, K) < 0
1474 	    ||
1475 	    crypto_bignum_is_one(K) ||
1476 	    crypto_bignum_to_bin(K, k, SAE_MAX_PRIME_LEN, sae->tmp->prime_len) <
1477 	    0) {
1478 		wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
1479 		goto fail;
1480 	}
1481 
1482 	wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len);
1483 
1484 	ret = 0;
1485 fail:
1486 	crypto_bignum_deinit(K, 1);
1487 	return ret;
1488 }
1489 
1490 
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)1491 static int sae_kdf_hash(size_t hash_len, const u8 *k, const char *label,
1492 			const u8 *context, size_t context_len,
1493 			u8 *out, size_t out_len)
1494 {
1495 	if (hash_len == 32)
1496 		return sha256_prf(k, hash_len, label,
1497 				  context, context_len, out, out_len);
1498 #ifdef CONFIG_SHA384
1499 	if (hash_len == 48)
1500 		return sha384_prf(k, hash_len, label,
1501 				  context, context_len, out, out_len);
1502 #endif /* CONFIG_SHA384 */
1503 #ifdef CONFIG_SHA512
1504 	if (hash_len == 64)
1505 		return sha512_prf(k, hash_len, label,
1506 				  context, context_len, out, out_len);
1507 #endif /* CONFIG_SHA512 */
1508 	return -1;
1509 }
1510 
1511 
sae_derive_keys(struct sae_data * sae,const u8 * k)1512 static int sae_derive_keys(struct sae_data *sae, const u8 *k)
1513 {
1514 	u8 zero[SAE_MAX_HASH_LEN], val[SAE_MAX_PRIME_LEN];
1515 	const u8 *salt;
1516 	struct wpabuf *rejected_groups = NULL;
1517 	u8 keyseed[SAE_MAX_HASH_LEN];
1518 	u8 keys[SAE_MAX_HASH_LEN + SAE_PMK_LEN];
1519 	struct crypto_bignum *tmp;
1520 	int ret = -1;
1521 	size_t hash_len, salt_len, prime_len = sae->tmp->prime_len;
1522 	const u8 *addr[1];
1523 	size_t len[1];
1524 
1525 	tmp = crypto_bignum_init();
1526 	if (tmp == NULL)
1527 		goto fail;
1528 
1529 	/* keyseed = H(salt, k)
1530 	 * KCK || PMK = KDF-Hash-Length(keyseed, "SAE KCK and PMK",
1531 	 *                      (commit-scalar + peer-commit-scalar) modulo r)
1532 	 * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128)
1533 	 */
1534 	if (!sae->tmp->h2e)
1535 		hash_len = SHA256_MAC_LEN;
1536 	else if (sae->tmp->dh)
1537 		hash_len = sae_ffc_prime_len_2_hash_len(prime_len);
1538 	else
1539 		hash_len = sae_ecc_prime_len_2_hash_len(prime_len);
1540 	if (sae->tmp->h2e && (sae->tmp->own_rejected_groups ||
1541 			      sae->tmp->peer_rejected_groups)) {
1542 		struct wpabuf *own, *peer;
1543 
1544 		own = sae->tmp->own_rejected_groups;
1545 		peer = sae->tmp->peer_rejected_groups;
1546 		salt_len = 0;
1547 		if (own)
1548 			salt_len += wpabuf_len(own);
1549 		if (peer)
1550 			salt_len += wpabuf_len(peer);
1551 		rejected_groups = wpabuf_alloc(salt_len);
1552 		if (!rejected_groups)
1553 			goto fail;
1554 		if (sae->tmp->own_addr_higher) {
1555 			if (own)
1556 				wpabuf_put_buf(rejected_groups, own);
1557 			if (peer)
1558 				wpabuf_put_buf(rejected_groups, peer);
1559 		} else {
1560 			if (peer)
1561 				wpabuf_put_buf(rejected_groups, peer);
1562 			if (own)
1563 				wpabuf_put_buf(rejected_groups, own);
1564 		}
1565 		salt = wpabuf_head(rejected_groups);
1566 		salt_len = wpabuf_len(rejected_groups);
1567 	} else {
1568 		os_memset(zero, 0, hash_len);
1569 		salt = zero;
1570 		salt_len = hash_len;
1571 	}
1572 	wpa_hexdump(MSG_DEBUG, "SAE: salt for keyseed derivation",
1573 		    salt, salt_len);
1574 	addr[0] = k;
1575 	len[0] = prime_len;
1576 	if (hkdf_extract(hash_len, salt, salt_len, 1, addr, len, keyseed) < 0)
1577 		goto fail;
1578 	wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, hash_len);
1579 
1580 	if (crypto_bignum_add(sae->tmp->own_commit_scalar,
1581 			      sae->peer_commit_scalar, tmp) < 0 ||
1582 	    crypto_bignum_mod(tmp, sae->tmp->order, tmp) < 0)
1583 		goto fail;
1584 	/* IEEE Std 802.11-2016 is not exactly clear on the encoding of the bit
1585 	 * string that is needed for KCK, PMK, and PMKID derivation, but it
1586 	 * seems to make most sense to encode the
1587 	 * (commit-scalar + peer-commit-scalar) mod r part as a bit string by
1588 	 * zero padding it from left to the length of the order (in full
1589 	 * octets). */
1590 	crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->order_len);
1591 	wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
1592 	if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK",
1593 			 val, sae->tmp->order_len,
1594 			 keys, hash_len + SAE_PMK_LEN) < 0)
1595 		goto fail;
1596 	forced_memzero(keyseed, sizeof(keyseed));
1597 	os_memcpy(sae->tmp->kck, keys, hash_len);
1598 	sae->tmp->kck_len = hash_len;
1599 	os_memcpy(sae->pmk, keys + hash_len, SAE_PMK_LEN);
1600 	os_memcpy(sae->pmkid, val, SAE_PMKID_LEN);
1601 	forced_memzero(keys, sizeof(keys));
1602 	wpa_hexdump_key(MSG_DEBUG, "SAE: KCK",
1603 			sae->tmp->kck, sae->tmp->kck_len);
1604 	wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN);
1605 
1606 	ret = 0;
1607 fail:
1608 	wpabuf_free(rejected_groups);
1609 	crypto_bignum_deinit(tmp, 0);
1610 	return ret;
1611 }
1612 
1613 
sae_process_commit(struct sae_data * sae)1614 int sae_process_commit(struct sae_data *sae)
1615 {
1616 	u8 k[SAE_MAX_PRIME_LEN];
1617 	if (sae->tmp == NULL ||
1618 	    (sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) ||
1619 	    (sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) ||
1620 	    sae_derive_keys(sae, k) < 0)
1621 		return -1;
1622 	return 0;
1623 }
1624 
1625 
sae_write_commit(struct sae_data * sae,struct wpabuf * buf,const struct wpabuf * token,const char * identifier)1626 int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
1627 		     const struct wpabuf *token, const char *identifier)
1628 {
1629 	u8 *pos;
1630 
1631 	if (sae->tmp == NULL)
1632 		return -1;
1633 
1634 	wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
1635 	if (!sae->tmp->h2e && token) {
1636 		wpabuf_put_buf(buf, token);
1637 		wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token",
1638 			    wpabuf_head(token), wpabuf_len(token));
1639 	}
1640 	pos = wpabuf_put(buf, sae->tmp->prime_len);
1641 	if (crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
1642 				 sae->tmp->prime_len, sae->tmp->prime_len) < 0)
1643 		return -1;
1644 	wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar",
1645 		    pos, sae->tmp->prime_len);
1646 	if (sae->tmp->ec) {
1647 		pos = wpabuf_put(buf, 2 * sae->tmp->prime_len);
1648 		if (crypto_ec_point_to_bin(sae->tmp->ec,
1649 					   sae->tmp->own_commit_element_ecc,
1650 					   pos, pos + sae->tmp->prime_len) < 0)
1651 			return -1;
1652 		wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)",
1653 			    pos, sae->tmp->prime_len);
1654 		wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)",
1655 			    pos + sae->tmp->prime_len, sae->tmp->prime_len);
1656 	} else {
1657 		pos = wpabuf_put(buf, sae->tmp->prime_len);
1658 		if (crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos,
1659 					 sae->tmp->prime_len,
1660 					 sae->tmp->prime_len) < 0)
1661 			return -1;
1662 		wpa_hexdump(MSG_DEBUG, "SAE: own commit-element",
1663 			    pos, sae->tmp->prime_len);
1664 	}
1665 
1666 	if (identifier) {
1667 		/* Password Identifier element */
1668 		wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1669 		wpabuf_put_u8(buf, 1 + os_strlen(identifier));
1670 		wpabuf_put_u8(buf, WLAN_EID_EXT_PASSWORD_IDENTIFIER);
1671 		wpabuf_put_str(buf, identifier);
1672 		wpa_printf(MSG_DEBUG, "SAE: own Password Identifier: %s",
1673 			   identifier);
1674 	}
1675 
1676 	if (sae->tmp->h2e && sae->tmp->own_rejected_groups) {
1677 		wpa_hexdump_buf(MSG_DEBUG, "SAE: own Rejected Groups",
1678 				sae->tmp->own_rejected_groups);
1679 		wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1680 		wpabuf_put_u8(buf,
1681 			      1 + wpabuf_len(sae->tmp->own_rejected_groups));
1682 		wpabuf_put_u8(buf, WLAN_EID_EXT_REJECTED_GROUPS);
1683 		wpabuf_put_buf(buf, sae->tmp->own_rejected_groups);
1684 	}
1685 
1686 	if (sae->tmp->h2e && token) {
1687 		wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1688 		wpabuf_put_u8(buf, 1 + wpabuf_len(token));
1689 		wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN);
1690 		wpabuf_put_buf(buf, token);
1691 		wpa_hexdump_buf(MSG_DEBUG,
1692 				"SAE: Anti-clogging token (in container)",
1693 				token);
1694 	}
1695 
1696 	return 0;
1697 }
1698 
1699 
sae_group_allowed(struct sae_data * sae,int * allowed_groups,u16 group)1700 u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group)
1701 {
1702 	if (allowed_groups) {
1703 		int i;
1704 		for (i = 0; allowed_groups[i] > 0; i++) {
1705 			if (allowed_groups[i] == group)
1706 				break;
1707 		}
1708 		if (allowed_groups[i] != group) {
1709 			wpa_printf(MSG_DEBUG, "SAE: Proposed group %u not "
1710 				   "enabled in the current configuration",
1711 				   group);
1712 			return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1713 		}
1714 	}
1715 
1716 	if (sae->state == SAE_COMMITTED && group != sae->group) {
1717 		wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed");
1718 		return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1719 	}
1720 
1721 	if (group != sae->group && sae_set_group(sae, group) < 0) {
1722 		wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
1723 			   group);
1724 		return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1725 	}
1726 
1727 	if (sae->tmp == NULL) {
1728 		wpa_printf(MSG_DEBUG, "SAE: Group information not yet initialized");
1729 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1730 	}
1731 
1732 	if (sae->tmp->dh && !allowed_groups) {
1733 		wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without "
1734 			   "explicit configuration enabling it", group);
1735 		return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1736 	}
1737 
1738 	return WLAN_STATUS_SUCCESS;
1739 }
1740 
1741 
sae_is_password_id_elem(const u8 * pos,const u8 * end)1742 static int sae_is_password_id_elem(const u8 *pos, const u8 *end)
1743 {
1744 	return end - pos >= 3 &&
1745 		pos[0] == WLAN_EID_EXTENSION &&
1746 		pos[1] >= 1 &&
1747 		end - pos - 2 >= pos[1] &&
1748 		pos[2] == WLAN_EID_EXT_PASSWORD_IDENTIFIER;
1749 }
1750 
1751 
sae_is_rejected_groups_elem(const u8 * pos,const u8 * end)1752 static int sae_is_rejected_groups_elem(const u8 *pos, const u8 *end)
1753 {
1754 	return end - pos >= 3 &&
1755 		pos[0] == WLAN_EID_EXTENSION &&
1756 		pos[1] >= 2 &&
1757 		end - pos - 2 >= pos[1] &&
1758 		pos[2] == WLAN_EID_EXT_REJECTED_GROUPS;
1759 }
1760 
1761 
sae_is_token_container_elem(const u8 * pos,const u8 * end)1762 static int sae_is_token_container_elem(const u8 *pos, const u8 *end)
1763 {
1764 	return end - pos >= 3 &&
1765 		pos[0] == WLAN_EID_EXTENSION &&
1766 		pos[1] >= 1 &&
1767 		end - pos - 2 >= pos[1] &&
1768 		pos[2] == WLAN_EID_EXT_ANTI_CLOGGING_TOKEN;
1769 }
1770 
1771 
sae_parse_commit_token(struct sae_data * sae,const u8 ** pos,const u8 * end,const u8 ** token,size_t * token_len,int h2e)1772 static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
1773 				   const u8 *end, const u8 **token,
1774 				   size_t *token_len, int h2e)
1775 {
1776 	size_t scalar_elem_len, tlen;
1777 
1778 	if (token)
1779 		*token = NULL;
1780 	if (token_len)
1781 		*token_len = 0;
1782 
1783 	if (h2e)
1784 		return; /* No Anti-Clogging Token field outside container IE */
1785 
1786 	scalar_elem_len = (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len;
1787 	if (scalar_elem_len >= (size_t) (end - *pos))
1788 		return; /* No extra data beyond peer scalar and element */
1789 
1790 	tlen = end - (*pos + scalar_elem_len);
1791 
1792 	if (tlen < SHA256_MAC_LEN) {
1793 		wpa_printf(MSG_DEBUG,
1794 			   "SAE: Too short optional data (%u octets) to include our Anti-Clogging Token",
1795 			   (unsigned int) tlen);
1796 		return;
1797 	}
1798 
1799 	wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
1800 	if (token)
1801 		*token = *pos;
1802 	if (token_len)
1803 		*token_len = tlen;
1804 	*pos += tlen;
1805 }
1806 
1807 
sae_parse_token_container(struct sae_data * sae,const u8 * pos,const u8 * end,const u8 ** token,size_t * token_len)1808 static void sae_parse_token_container(struct sae_data *sae,
1809 				      const u8 *pos, const u8 *end,
1810 				      const u8 **token, size_t *token_len)
1811 {
1812 	wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
1813 		    pos, end - pos);
1814 	if (!sae_is_token_container_elem(pos, end))
1815 		return;
1816 	*token = pos + 3;
1817 	*token_len = pos[1] - 1;
1818 	wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token (in container)",
1819 		    *token, *token_len);
1820 }
1821 
1822 
sae_parse_commit_scalar(struct sae_data * sae,const u8 ** pos,const u8 * end)1823 static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos,
1824 				   const u8 *end)
1825 {
1826 	struct crypto_bignum *peer_scalar;
1827 
1828 	if (sae->tmp->prime_len > end - *pos) {
1829 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar");
1830 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1831 	}
1832 
1833 	peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len);
1834 	if (peer_scalar == NULL)
1835 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1836 
1837 	/*
1838 	 * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for
1839 	 * the peer and it is in Authenticated state, the new Commit Message
1840 	 * shall be dropped if the peer-scalar is identical to the one used in
1841 	 * the existing protocol instance.
1842 	 */
1843 	if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar_accepted &&
1844 	    crypto_bignum_cmp(sae->peer_commit_scalar_accepted,
1845 			      peer_scalar) == 0) {
1846 		wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous "
1847 			   "peer-commit-scalar");
1848 		crypto_bignum_deinit(peer_scalar, 0);
1849 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1850 	}
1851 
1852 	/* 1 < scalar < r */
1853 	if (crypto_bignum_is_zero(peer_scalar) ||
1854 	    crypto_bignum_is_one(peer_scalar) ||
1855 	    crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) {
1856 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar");
1857 		crypto_bignum_deinit(peer_scalar, 0);
1858 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1859 	}
1860 
1861 
1862 	crypto_bignum_deinit(sae->peer_commit_scalar, 0);
1863 	sae->peer_commit_scalar = peer_scalar;
1864 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar",
1865 		    *pos, sae->tmp->prime_len);
1866 	*pos += sae->tmp->prime_len;
1867 
1868 	return WLAN_STATUS_SUCCESS;
1869 }
1870 
1871 
sae_parse_commit_element_ecc(struct sae_data * sae,const u8 ** pos,const u8 * end)1872 static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 **pos,
1873 					const u8 *end)
1874 {
1875 	u8 prime[SAE_MAX_ECC_PRIME_LEN];
1876 
1877 	if (2 * sae->tmp->prime_len > end - *pos) {
1878 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
1879 			   "commit-element");
1880 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1881 	}
1882 
1883 	if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
1884 				 sae->tmp->prime_len) < 0)
1885 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1886 
1887 	/* element x and y coordinates < p */
1888 	if (os_memcmp(*pos, prime, sae->tmp->prime_len) >= 0 ||
1889 	    os_memcmp(*pos + sae->tmp->prime_len, prime,
1890 		      sae->tmp->prime_len) >= 0) {
1891 		wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer "
1892 			   "element");
1893 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1894 	}
1895 
1896 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)",
1897 		    *pos, sae->tmp->prime_len);
1898 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)",
1899 		    *pos + sae->tmp->prime_len, sae->tmp->prime_len);
1900 
1901 	crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0);
1902 	sae->tmp->peer_commit_element_ecc =
1903 		crypto_ec_point_from_bin(sae->tmp->ec, *pos);
1904 	if (sae->tmp->peer_commit_element_ecc == NULL)
1905 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1906 
1907 	if (!crypto_ec_point_is_on_curve(sae->tmp->ec,
1908 					 sae->tmp->peer_commit_element_ecc)) {
1909 		wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve");
1910 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1911 	}
1912 
1913 	*pos += 2 * sae->tmp->prime_len;
1914 
1915 	return WLAN_STATUS_SUCCESS;
1916 }
1917 
1918 
sae_parse_commit_element_ffc(struct sae_data * sae,const u8 ** pos,const u8 * end)1919 static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 **pos,
1920 					const u8 *end)
1921 {
1922 	struct crypto_bignum *res, *one;
1923 	const u8 one_bin[1] = { 0x01 };
1924 
1925 	if (sae->tmp->prime_len > end - *pos) {
1926 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
1927 			   "commit-element");
1928 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1929 	}
1930 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", *pos,
1931 		    sae->tmp->prime_len);
1932 
1933 	crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0);
1934 	sae->tmp->peer_commit_element_ffc =
1935 		crypto_bignum_init_set(*pos, sae->tmp->prime_len);
1936 	if (sae->tmp->peer_commit_element_ffc == NULL)
1937 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1938 	/* 1 < element < p - 1 */
1939 	res = crypto_bignum_init();
1940 	one = crypto_bignum_init_set(one_bin, sizeof(one_bin));
1941 	if (!res || !one ||
1942 	    crypto_bignum_sub(sae->tmp->prime, one, res) ||
1943 	    crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) ||
1944 	    crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) ||
1945 	    crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc, res) >= 0) {
1946 		crypto_bignum_deinit(res, 0);
1947 		crypto_bignum_deinit(one, 0);
1948 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer element");
1949 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1950 	}
1951 	crypto_bignum_deinit(one, 0);
1952 
1953 	/* scalar-op(r, ELEMENT) = 1 modulo p */
1954 	if (crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc,
1955 				  sae->tmp->order, sae->tmp->prime, res) < 0 ||
1956 	    !crypto_bignum_is_one(res)) {
1957 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer element (scalar-op)");
1958 		crypto_bignum_deinit(res, 0);
1959 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1960 	}
1961 	crypto_bignum_deinit(res, 0);
1962 
1963 	*pos += sae->tmp->prime_len;
1964 
1965 	return WLAN_STATUS_SUCCESS;
1966 }
1967 
1968 
sae_parse_commit_element(struct sae_data * sae,const u8 ** pos,const u8 * end)1969 static u16 sae_parse_commit_element(struct sae_data *sae, const u8 **pos,
1970 				    const u8 *end)
1971 {
1972 	if (sae->tmp->dh)
1973 		return sae_parse_commit_element_ffc(sae, pos, end);
1974 	return sae_parse_commit_element_ecc(sae, pos, end);
1975 }
1976 
1977 
sae_parse_password_identifier(struct sae_data * sae,const u8 ** pos,const u8 * end)1978 static int sae_parse_password_identifier(struct sae_data *sae,
1979 					 const u8 **pos, const u8 *end)
1980 {
1981 	wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
1982 		    *pos, end - *pos);
1983 	if (!sae_is_password_id_elem(*pos, end)) {
1984 		if (sae->tmp->pw_id) {
1985 			wpa_printf(MSG_DEBUG,
1986 				   "SAE: No Password Identifier included, but expected one (%s)",
1987 				   sae->tmp->pw_id);
1988 			return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
1989 		}
1990 		os_free(sae->tmp->pw_id);
1991 		sae->tmp->pw_id = NULL;
1992 		return WLAN_STATUS_SUCCESS; /* No Password Identifier */
1993 	}
1994 
1995 	if (sae->tmp->pw_id &&
1996 	    ((*pos)[1] - 1 != (int) os_strlen(sae->tmp->pw_id) ||
1997 	     os_memcmp(sae->tmp->pw_id, (*pos) + 3, (*pos)[1] - 1) != 0)) {
1998 		wpa_printf(MSG_DEBUG,
1999 			   "SAE: The included Password Identifier does not match the expected one (%s)",
2000 			   sae->tmp->pw_id);
2001 		return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
2002 	}
2003 
2004 	os_free(sae->tmp->pw_id);
2005 	sae->tmp->pw_id = os_malloc((*pos)[1]);
2006 	if (!sae->tmp->pw_id)
2007 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2008 	os_memcpy(sae->tmp->pw_id, (*pos) + 3, (*pos)[1] - 1);
2009 	sae->tmp->pw_id[(*pos)[1] - 1] = '\0';
2010 	wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier",
2011 			  sae->tmp->pw_id, (*pos)[1] -  1);
2012 	*pos = *pos + 2 + (*pos)[1];
2013 	return WLAN_STATUS_SUCCESS;
2014 }
2015 
2016 
sae_parse_rejected_groups(struct sae_data * sae,const u8 ** pos,const u8 * end)2017 static int sae_parse_rejected_groups(struct sae_data *sae,
2018 				     const u8 **pos, const u8 *end)
2019 {
2020 	wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
2021 		    *pos, end - *pos);
2022 	if (!sae_is_rejected_groups_elem(*pos, end))
2023 		return WLAN_STATUS_SUCCESS;
2024 	wpabuf_free(sae->tmp->peer_rejected_groups);
2025 	sae->tmp->peer_rejected_groups = wpabuf_alloc((*pos)[1] - 1);
2026 	if (!sae->tmp->peer_rejected_groups)
2027 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2028 	wpabuf_put_data(sae->tmp->peer_rejected_groups, (*pos) + 3,
2029 			(*pos)[1] - 1);
2030 	wpa_hexdump_buf(MSG_DEBUG, "SAE: Received Rejected Groups list",
2031 			sae->tmp->peer_rejected_groups);
2032 	*pos = *pos + 2 + (*pos)[1];
2033 	return WLAN_STATUS_SUCCESS;
2034 }
2035 
2036 
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)2037 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
2038 		     const u8 **token, size_t *token_len, int *allowed_groups,
2039 		     int h2e)
2040 {
2041 	const u8 *pos = data, *end = data + len;
2042 	u16 res;
2043 
2044 	/* Check Finite Cyclic Group */
2045 	if (end - pos < 2)
2046 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
2047 	res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos));
2048 	if (res != WLAN_STATUS_SUCCESS)
2049 		return res;
2050 	pos += 2;
2051 
2052 	/* Optional Anti-Clogging Token */
2053 	sae_parse_commit_token(sae, &pos, end, token, token_len, h2e);
2054 
2055 	/* commit-scalar */
2056 	res = sae_parse_commit_scalar(sae, &pos, end);
2057 	if (res != WLAN_STATUS_SUCCESS)
2058 		return res;
2059 
2060 	/* commit-element */
2061 	res = sae_parse_commit_element(sae, &pos, end);
2062 	if (res != WLAN_STATUS_SUCCESS)
2063 		return res;
2064 
2065 	/* Optional Password Identifier element */
2066 	res = sae_parse_password_identifier(sae, &pos, end);
2067 	if (res != WLAN_STATUS_SUCCESS)
2068 		return res;
2069 
2070 	/* Conditional Rejected Groups element */
2071 	if (h2e) {
2072 		res = sae_parse_rejected_groups(sae, &pos, end);
2073 		if (res != WLAN_STATUS_SUCCESS)
2074 			return res;
2075 	}
2076 
2077 	/* Optional Anti-Clogging Token Container element */
2078 	if (h2e)
2079 		sae_parse_token_container(sae, pos, end, token, token_len);
2080 
2081 	/*
2082 	 * Check whether peer-commit-scalar and PEER-COMMIT-ELEMENT are same as
2083 	 * the values we sent which would be evidence of a reflection attack.
2084 	 */
2085 	if (!sae->tmp->own_commit_scalar ||
2086 	    crypto_bignum_cmp(sae->tmp->own_commit_scalar,
2087 			      sae->peer_commit_scalar) != 0 ||
2088 	    (sae->tmp->dh &&
2089 	     (!sae->tmp->own_commit_element_ffc ||
2090 	      crypto_bignum_cmp(sae->tmp->own_commit_element_ffc,
2091 				sae->tmp->peer_commit_element_ffc) != 0)) ||
2092 	    (sae->tmp->ec &&
2093 	     (!sae->tmp->own_commit_element_ecc ||
2094 	      crypto_ec_point_cmp(sae->tmp->ec,
2095 				  sae->tmp->own_commit_element_ecc,
2096 				  sae->tmp->peer_commit_element_ecc) != 0)))
2097 		return WLAN_STATUS_SUCCESS; /* scalars/elements are different */
2098 
2099 	/*
2100 	 * This is a reflection attack - return special value to trigger caller
2101 	 * to silently discard the frame instead of replying with a specific
2102 	 * status code.
2103 	 */
2104 	return SAE_SILENTLY_DISCARD;
2105 }
2106 
2107 
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)2108 static int sae_cn_confirm(struct sae_data *sae, const u8 *sc,
2109 			  const struct crypto_bignum *scalar1,
2110 			  const u8 *element1, size_t element1_len,
2111 			  const struct crypto_bignum *scalar2,
2112 			  const u8 *element2, size_t element2_len,
2113 			  u8 *confirm)
2114 {
2115 	const u8 *addr[5];
2116 	size_t len[5];
2117 	u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN];
2118 
2119 	/* Confirm
2120 	 * CN(key, X, Y, Z, ...) =
2121 	 *    HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...)
2122 	 * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT,
2123 	 *              peer-commit-scalar, PEER-COMMIT-ELEMENT)
2124 	 * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar,
2125 	 *               PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT)
2126 	 */
2127 	if (crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1),
2128 				 sae->tmp->prime_len) < 0 ||
2129 	    crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2),
2130 				 sae->tmp->prime_len) < 0)
2131 		return -1;
2132 	addr[0] = sc;
2133 	len[0] = 2;
2134 	addr[1] = scalar_b1;
2135 	len[1] = sae->tmp->prime_len;
2136 	addr[2] = element1;
2137 	len[2] = element1_len;
2138 	addr[3] = scalar_b2;
2139 	len[3] = sae->tmp->prime_len;
2140 	addr[4] = element2;
2141 	len[4] = element2_len;
2142 	return hkdf_extract(sae->tmp->kck_len, sae->tmp->kck, sae->tmp->kck_len,
2143 			    5, addr, len, confirm);
2144 }
2145 
2146 
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)2147 static int sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
2148 			      const struct crypto_bignum *scalar1,
2149 			      const struct crypto_ec_point *element1,
2150 			      const struct crypto_bignum *scalar2,
2151 			      const struct crypto_ec_point *element2,
2152 			      u8 *confirm)
2153 {
2154 	u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN];
2155 	u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN];
2156 
2157 	if (crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1,
2158 				   element_b1 + sae->tmp->prime_len) < 0 ||
2159 	    crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2,
2160 				   element_b2 + sae->tmp->prime_len) < 0 ||
2161 	    sae_cn_confirm(sae, sc, scalar1, element_b1,
2162 			   2 * sae->tmp->prime_len,
2163 			   scalar2, element_b2, 2 * sae->tmp->prime_len,
2164 			   confirm) < 0)
2165 		return -1;
2166 	return 0;
2167 }
2168 
2169 
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)2170 static int sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
2171 			      const struct crypto_bignum *scalar1,
2172 			      const struct crypto_bignum *element1,
2173 			      const struct crypto_bignum *scalar2,
2174 			      const struct crypto_bignum *element2,
2175 			      u8 *confirm)
2176 {
2177 	u8 element_b1[SAE_MAX_PRIME_LEN];
2178 	u8 element_b2[SAE_MAX_PRIME_LEN];
2179 
2180 	if (crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1),
2181 				 sae->tmp->prime_len) < 0 ||
2182 	    crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2),
2183 				 sae->tmp->prime_len) < 0 ||
2184 	    sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len,
2185 			   scalar2, element_b2, sae->tmp->prime_len,
2186 			   confirm) < 0)
2187 		return -1;
2188 	return 0;
2189 }
2190 
2191 
sae_write_confirm(struct sae_data * sae,struct wpabuf * buf)2192 void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
2193 {
2194 	const u8 *sc;
2195 	size_t hash_len;
2196 
2197 	if (sae->tmp == NULL)
2198 		return;
2199 
2200 	hash_len = sae->tmp->kck_len;
2201 
2202 	/* Send-Confirm */
2203 	sc = wpabuf_put(buf, 0);
2204 	wpabuf_put_le16(buf, sae->send_confirm);
2205 	if (sae->send_confirm < 0xffff)
2206 		sae->send_confirm++;
2207 
2208 	if (sae->tmp->ec)
2209 		sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
2210 				   sae->tmp->own_commit_element_ecc,
2211 				   sae->peer_commit_scalar,
2212 				   sae->tmp->peer_commit_element_ecc,
2213 				   wpabuf_put(buf, hash_len));
2214 	else
2215 		sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar,
2216 				   sae->tmp->own_commit_element_ffc,
2217 				   sae->peer_commit_scalar,
2218 				   sae->tmp->peer_commit_element_ffc,
2219 				   wpabuf_put(buf, hash_len));
2220 }
2221 
2222 
sae_check_confirm(struct sae_data * sae,const u8 * data,size_t len)2223 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
2224 {
2225 	u8 verifier[SAE_MAX_HASH_LEN];
2226 	size_t hash_len;
2227 
2228 	if (!sae->tmp)
2229 		return -1;
2230 
2231 	hash_len = sae->tmp->kck_len;
2232 	if (len < 2 + hash_len) {
2233 		wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
2234 		return -1;
2235 	}
2236 
2237 	wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data));
2238 
2239 	if (!sae->peer_commit_scalar || !sae->tmp->own_commit_scalar) {
2240 		wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available");
2241 		return -1;
2242 	}
2243 
2244 	if (sae->tmp->ec) {
2245 		if (!sae->tmp->peer_commit_element_ecc ||
2246 		    !sae->tmp->own_commit_element_ecc ||
2247 		    sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar,
2248 				       sae->tmp->peer_commit_element_ecc,
2249 				       sae->tmp->own_commit_scalar,
2250 				       sae->tmp->own_commit_element_ecc,
2251 				       verifier) < 0)
2252 			return -1;
2253 	} else {
2254 		if (!sae->tmp->peer_commit_element_ffc ||
2255 		    !sae->tmp->own_commit_element_ffc ||
2256 		    sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar,
2257 				       sae->tmp->peer_commit_element_ffc,
2258 				       sae->tmp->own_commit_scalar,
2259 				       sae->tmp->own_commit_element_ffc,
2260 				       verifier) < 0)
2261 			return -1;
2262 	}
2263 
2264 	if (os_memcmp_const(verifier, data + 2, hash_len) != 0) {
2265 		wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
2266 		wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
2267 			    data + 2, hash_len);
2268 		wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
2269 			    verifier, hash_len);
2270 		return -1;
2271 	}
2272 
2273 	return 0;
2274 }
2275 
2276 
sae_state_txt(enum sae_state state)2277 const char * sae_state_txt(enum sae_state state)
2278 {
2279 	switch (state) {
2280 	case SAE_NOTHING:
2281 		return "Nothing";
2282 	case SAE_COMMITTED:
2283 		return "Committed";
2284 	case SAE_CONFIRMED:
2285 		return "Confirmed";
2286 	case SAE_ACCEPTED:
2287 		return "Accepted";
2288 	}
2289 	return "?";
2290 }
2291