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