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