• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Simultaneous authentication of equals
3  * Copyright (c) 2012-2016, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "common.h"
12 #include "utils/const_time.h"
13 #include "crypto/crypto.h"
14 #include "crypto/sha256.h"
15 #include "crypto/random.h"
16 #include "crypto/dh_groups.h"
17 #include "ieee802_11_defs.h"
18 #include "dragonfly.h"
19 #include "sae.h"
20 
21 
sae_set_group(struct sae_data * sae,int group)22 int sae_set_group(struct sae_data *sae, int group)
23 {
24 	struct sae_temporary_data *tmp;
25 
26 #ifdef CONFIG_TESTING_OPTIONS
27 	/* Allow all groups for testing purposes in non-production builds. */
28 #else /* CONFIG_TESTING_OPTIONS */
29 	if (!dragonfly_suitable_group(group, 0)) {
30 		wpa_printf(MSG_DEBUG, "SAE: Reject unsuitable group %d", group);
31 		return -1;
32 	}
33 #endif /* CONFIG_TESTING_OPTIONS */
34 
35 	sae_clear_data(sae);
36 	tmp = sae->tmp = os_zalloc(sizeof(*tmp));
37 	if (tmp == NULL)
38 		return -1;
39 
40 	/* First, check if this is an ECC group */
41 	tmp->ec = crypto_ec_init(group);
42 	if (tmp->ec) {
43 		wpa_printf(MSG_DEBUG, "SAE: Selecting supported ECC group %d",
44 			   group);
45 		sae->group = group;
46 		tmp->prime_len = crypto_ec_prime_len(tmp->ec);
47 		tmp->prime = crypto_ec_get_prime(tmp->ec);
48 		tmp->order_len = crypto_ec_order_len(tmp->ec);
49 		tmp->order = crypto_ec_get_order(tmp->ec);
50 		return 0;
51 	}
52 
53 	/* Not an ECC group, check FFC */
54 	tmp->dh = dh_groups_get(group);
55 	if (tmp->dh) {
56 		wpa_printf(MSG_DEBUG, "SAE: Selecting supported FFC group %d",
57 			   group);
58 		sae->group = group;
59 		tmp->prime_len = tmp->dh->prime_len;
60 		if (tmp->prime_len > SAE_MAX_PRIME_LEN) {
61 			sae_clear_data(sae);
62 			return -1;
63 		}
64 
65 		tmp->prime_buf = crypto_bignum_init_set(tmp->dh->prime,
66 							tmp->prime_len);
67 		if (tmp->prime_buf == NULL) {
68 			sae_clear_data(sae);
69 			return -1;
70 		}
71 		tmp->prime = tmp->prime_buf;
72 
73 		tmp->order_len = tmp->dh->order_len;
74 		tmp->order_buf = crypto_bignum_init_set(tmp->dh->order,
75 							tmp->dh->order_len);
76 		if (tmp->order_buf == NULL) {
77 			sae_clear_data(sae);
78 			return -1;
79 		}
80 		tmp->order = tmp->order_buf;
81 
82 		return 0;
83 	}
84 
85 	/* Unsupported group */
86 	wpa_printf(MSG_DEBUG,
87 		   "SAE: Group %d not supported by the crypto library", group);
88 	return -1;
89 }
90 
91 
sae_clear_temp_data(struct sae_data * sae)92 void sae_clear_temp_data(struct sae_data *sae)
93 {
94 	struct sae_temporary_data *tmp;
95 	if (sae == NULL || sae->tmp == NULL)
96 		return;
97 	tmp = sae->tmp;
98 	crypto_ec_deinit(tmp->ec);
99 	crypto_bignum_deinit(tmp->prime_buf, 0);
100 	crypto_bignum_deinit(tmp->order_buf, 0);
101 	crypto_bignum_deinit(tmp->sae_rand, 1);
102 	crypto_bignum_deinit(tmp->pwe_ffc, 1);
103 	crypto_bignum_deinit(tmp->own_commit_scalar, 0);
104 	crypto_bignum_deinit(tmp->own_commit_element_ffc, 0);
105 	crypto_bignum_deinit(tmp->peer_commit_element_ffc, 0);
106 	crypto_ec_point_deinit(tmp->pwe_ecc, 1);
107 	crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0);
108 	crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0);
109 	wpabuf_free(tmp->anti_clogging_token);
110 	os_free(tmp->pw_id);
111 	bin_clear_free(tmp, sizeof(*tmp));
112 	sae->tmp = NULL;
113 }
114 
115 
sae_clear_data(struct sae_data * sae)116 void sae_clear_data(struct sae_data *sae)
117 {
118 	if (sae == NULL)
119 		return;
120 	sae_clear_temp_data(sae);
121 	crypto_bignum_deinit(sae->peer_commit_scalar, 0);
122 	os_memset(sae, 0, sizeof(*sae));
123 }
124 
125 
sae_pwd_seed_key(const u8 * addr1,const u8 * addr2,u8 * key)126 static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key)
127 {
128 	wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR
129 		   " addr2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2));
130 	if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) {
131 		os_memcpy(key, addr1, ETH_ALEN);
132 		os_memcpy(key + ETH_ALEN, addr2, ETH_ALEN);
133 	} else {
134 		os_memcpy(key, addr2, ETH_ALEN);
135 		os_memcpy(key + ETH_ALEN, addr1, ETH_ALEN);
136 	}
137 }
138 
139 
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)140 static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
141 				 const u8 *prime, const u8 *qr, const u8 *qnr,
142 				 u8 *pwd_value)
143 {
144 	struct crypto_bignum *y_sqr, *x_cand;
145 	int res;
146 	size_t bits;
147 	int cmp_prime;
148 	unsigned int in_range;
149 
150 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
151 
152 	/* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
153 	bits = crypto_ec_prime_len_bits(sae->tmp->ec);
154 	if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
155 			    prime, sae->tmp->prime_len, pwd_value, bits) < 0)
156 		return -1;
157 	if (bits % 8)
158 		buf_shift_right(pwd_value, sae->tmp->prime_len, 8 - bits % 8);
159 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
160 			pwd_value, sae->tmp->prime_len);
161 
162 	cmp_prime = const_time_memcmp(pwd_value, prime, sae->tmp->prime_len);
163 	/* Create a const_time mask for selection based on prf result
164 	 * being smaller than prime. */
165 	in_range = const_time_fill_msb((unsigned int) cmp_prime);
166 	/* The algorithm description would skip the next steps if
167 	 * cmp_prime >= 0 (reutnr 0 here), but go through them regardless to
168 	 * minimize externally observable differences in behavior. */
169 
170 	x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
171 	if (!x_cand)
172 		return -1;
173 	y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand);
174 	crypto_bignum_deinit(x_cand, 1);
175 	if (!y_sqr)
176 		return -1;
177 
178 	res = dragonfly_is_quadratic_residue_blind(sae->tmp->ec, qr, qnr,
179 						   y_sqr);
180 	crypto_bignum_deinit(y_sqr, 1);
181 	if (res < 0)
182 		return res;
183 	return const_time_select_int(in_range, res, 0);
184 }
185 
186 
187 /* Returns -1 on fatal failure, 0 if PWE cannot be derived from the provided
188  * 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)189 static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
190 				 struct crypto_bignum *pwe)
191 {
192 	u8 pwd_value[SAE_MAX_PRIME_LEN];
193 	size_t bits = sae->tmp->prime_len * 8;
194 	u8 exp[1];
195 	struct crypto_bignum *a, *b = NULL;
196 	int res, is_val;
197 	u8 pwd_value_valid;
198 
199 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
200 
201 	/* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
202 	if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
203 			    sae->tmp->dh->prime, sae->tmp->prime_len, pwd_value,
204 			    bits) < 0)
205 		return -1;
206 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value,
207 			sae->tmp->prime_len);
208 
209 	/* Check whether pwd-value < p */
210 	res = const_time_memcmp(pwd_value, sae->tmp->dh->prime,
211 				sae->tmp->prime_len);
212 	/* pwd-value >= p is invalid, so res is < 0 for the valid cases and
213 	 * the negative sign can be used to fill the mask for constant time
214 	 * selection */
215 	pwd_value_valid = const_time_fill_msb(res);
216 
217 	/* If pwd-value >= p, force pwd-value to be < p and perform the
218 	 * calculations anyway to hide timing difference. The derived PWE will
219 	 * be ignored in that case. */
220 	pwd_value[0] = const_time_select_u8(pwd_value_valid, pwd_value[0], 0);
221 
222 	/* PWE = pwd-value^((p-1)/r) modulo p */
223 
224 	res = -1;
225 	a = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
226 	if (!a)
227 		goto fail;
228 
229 	/* This is an optimization based on the used group that does not depend
230 	 * on the password in any way, so it is fine to use separate branches
231 	 * for this step without constant time operations. */
232 	if (sae->tmp->dh->safe_prime) {
233 		/*
234 		 * r = (p-1)/2 for the group used here, so this becomes:
235 		 * PWE = pwd-value^2 modulo p
236 		 */
237 		exp[0] = 2;
238 		b = crypto_bignum_init_set(exp, sizeof(exp));
239 	} else {
240 		/* Calculate exponent: (p-1)/r */
241 		exp[0] = 1;
242 		b = crypto_bignum_init_set(exp, sizeof(exp));
243 		if (b == NULL ||
244 		    crypto_bignum_sub(sae->tmp->prime, b, b) < 0 ||
245 		    crypto_bignum_div(b, sae->tmp->order, b) < 0)
246 			goto fail;
247 	}
248 
249 	if (!b)
250 		goto fail;
251 
252 	res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe);
253 	if (res < 0)
254 		goto fail;
255 
256 	/* There were no fatal errors in calculations, so determine the return
257 	 * value using constant time operations. We get here for number of
258 	 * invalid cases which are cleared here after having performed all the
259 	 * computation. PWE is valid if pwd-value was less than prime and
260 	 * PWE > 1. Start with pwd-value check first and then use constant time
261 	 * operations to clear res to 0 if PWE is 0 or 1.
262 	 */
263 	res = const_time_select_u8(pwd_value_valid, 1, 0);
264 	is_val = crypto_bignum_is_zero(pwe);
265 	res = const_time_select_u8(const_time_is_zero(is_val), res, 0);
266 	is_val = crypto_bignum_is_one(pwe);
267 	res = const_time_select_u8(const_time_is_zero(is_val), res, 0);
268 
269 fail:
270 	crypto_bignum_deinit(a, 1);
271 	crypto_bignum_deinit(b, 1);
272 	return res;
273 }
274 
275 
sae_derive_pwe_ecc(struct sae_data * sae,const u8 * addr1,const u8 * addr2,const u8 * password,size_t password_len,const char * identifier)276 static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
277 			      const u8 *addr2, const u8 *password,
278 			      size_t password_len, const char *identifier)
279 {
280 	u8 counter, k;
281 	u8 addrs[2 * ETH_ALEN];
282 	const u8 *addr[3];
283 	size_t len[3];
284 	size_t num_elem;
285 	u8 *dummy_password, *tmp_password;
286 	int pwd_seed_odd = 0;
287 	u8 prime[SAE_MAX_ECC_PRIME_LEN];
288 	size_t prime_len;
289 	struct crypto_bignum *x = NULL, *y = NULL, *qr = NULL, *qnr = NULL;
290 	u8 x_bin[SAE_MAX_ECC_PRIME_LEN];
291 	u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN];
292 	u8 qr_bin[SAE_MAX_ECC_PRIME_LEN];
293 	u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN];
294 	u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN];
295 	int res = -1;
296 	u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
297 		       * mask */
298 	unsigned int is_eq;
299 
300 	os_memset(x_bin, 0, sizeof(x_bin));
301 
302 	dummy_password = os_malloc(password_len);
303 	tmp_password = os_malloc(password_len);
304 	if (!dummy_password || !tmp_password ||
305 	    random_get_bytes(dummy_password, password_len) < 0)
306 		goto fail;
307 
308 	prime_len = sae->tmp->prime_len;
309 	if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
310 				 prime_len) < 0)
311 		goto fail;
312 
313 	/*
314 	 * Create a random quadratic residue (qr) and quadratic non-residue
315 	 * (qnr) modulo p for blinding purposes during the loop.
316 	 */
317 	if (dragonfly_get_random_qr_qnr(sae->tmp->prime, &qr, &qnr) < 0 ||
318 	    crypto_bignum_to_bin(qr, qr_bin, sizeof(qr_bin), prime_len) < 0 ||
319 	    crypto_bignum_to_bin(qnr, qnr_bin, sizeof(qnr_bin), prime_len) < 0)
320 		goto fail;
321 
322 	wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
323 			      password, password_len);
324 	if (identifier)
325 		wpa_printf(MSG_DEBUG, "SAE: password identifier: %s",
326 			   identifier);
327 
328 	/*
329 	 * H(salt, ikm) = HMAC-SHA256(salt, ikm)
330 	 * base = password [|| identifier]
331 	 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
332 	 *              base || counter)
333 	 */
334 	sae_pwd_seed_key(addr1, addr2, addrs);
335 
336 	addr[0] = tmp_password;
337 	len[0] = password_len;
338 	num_elem = 1;
339 	if (identifier) {
340 		addr[num_elem] = (const u8 *) identifier;
341 		len[num_elem] = os_strlen(identifier);
342 		num_elem++;
343 	}
344 	addr[num_elem] = &counter;
345 	len[num_elem] = sizeof(counter);
346 	num_elem++;
347 
348 	/*
349 	 * Continue for at least k iterations to protect against side-channel
350 	 * attacks that attempt to determine the number of iterations required
351 	 * in the loop.
352 	 */
353 	k = dragonfly_min_pwe_loop_iter(sae->group);
354 
355 	for (counter = 1; counter <= k || !found; counter++) {
356 		u8 pwd_seed[SHA256_MAC_LEN];
357 
358 		if (counter > 200) {
359 			/* This should not happen in practice */
360 			wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
361 			break;
362 		}
363 
364 		wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter);
365 		const_time_select_bin(found, dummy_password, password,
366 				      password_len, tmp_password);
367 		if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
368 				       addr, len, pwd_seed) < 0)
369 			break;
370 
371 		res = sae_test_pwd_seed_ecc(sae, pwd_seed,
372 					    prime, qr_bin, qnr_bin, x_cand_bin);
373 		const_time_select_bin(found, x_bin, x_cand_bin, prime_len,
374 				      x_bin);
375 		pwd_seed_odd = const_time_select_u8(
376 			found, pwd_seed_odd,
377 			pwd_seed[SHA256_MAC_LEN - 1] & 0x01);
378 		os_memset(pwd_seed, 0, sizeof(pwd_seed));
379 		if (res < 0)
380 			goto fail;
381 		/* Need to minimize differences in handling res == 0 and 1 here
382 		 * to avoid differences in timing and instruction cache access,
383 		 * so use const_time_select_*() to make local copies of the
384 		 * values based on whether this loop iteration was the one that
385 		 * found the pwd-seed/x. */
386 
387 		/* found is 0 or 0xff here and res is 0 or 1. Bitwise OR of them
388 		 * (with res converted to 0/0xff) handles this in constant time.
389 		 */
390 		found |= res * 0xff;
391 		wpa_printf(MSG_DEBUG, "SAE: pwd-seed result %d found=0x%02x",
392 			   res, found);
393 	}
394 
395 	if (!found) {
396 		wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
397 		res = -1;
398 		goto fail;
399 	}
400 
401 	x = crypto_bignum_init_set(x_bin, prime_len);
402 	if (!x) {
403 		res = -1;
404 		goto fail;
405 	}
406 
407 	/* y = sqrt(x^3 + ax + b) mod p
408 	 * if LSB(save) == LSB(y): PWE = (x, y)
409 	 * else: PWE = (x, p - y)
410 	 *
411 	 * Calculate y and the two possible values for PWE and after that,
412 	 * use constant time selection to copy the correct alternative.
413 	 */
414 	y = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x);
415 	if (!y ||
416 	    dragonfly_sqrt(sae->tmp->ec, y, y) < 0 ||
417 	    crypto_bignum_to_bin(y, x_y, SAE_MAX_ECC_PRIME_LEN,
418 				 prime_len) < 0 ||
419 	    crypto_bignum_sub(sae->tmp->prime, y, y) < 0 ||
420 	    crypto_bignum_to_bin(y, x_y + SAE_MAX_ECC_PRIME_LEN,
421 				 SAE_MAX_ECC_PRIME_LEN, prime_len) < 0) {
422 		wpa_printf(MSG_DEBUG, "SAE: Could not solve y");
423 		goto fail;
424 	}
425 
426 	is_eq = const_time_eq(pwd_seed_odd, x_y[prime_len - 1] & 0x01);
427 	const_time_select_bin(is_eq, x_y, x_y + SAE_MAX_ECC_PRIME_LEN,
428 			      prime_len, x_y + prime_len);
429 	os_memcpy(x_y, x_bin, prime_len);
430 	wpa_hexdump_key(MSG_DEBUG, "SAE: PWE", x_y, 2 * prime_len);
431 	crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1);
432 	sae->tmp->pwe_ecc = crypto_ec_point_from_bin(sae->tmp->ec, x_y);
433 	if (!sae->tmp->pwe_ecc) {
434 		wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
435 		res = -1;
436 	}
437 
438 fail:
439 	forced_memzero(x_y, sizeof(x_y));
440 	crypto_bignum_deinit(qr, 0);
441 	crypto_bignum_deinit(qnr, 0);
442 	crypto_bignum_deinit(y, 1);
443 	os_free(dummy_password);
444 	bin_clear_free(tmp_password, password_len);
445 	crypto_bignum_deinit(x, 1);
446 	os_memset(x_bin, 0, sizeof(x_bin));
447 	os_memset(x_cand_bin, 0, sizeof(x_cand_bin));
448 
449 	return res;
450 }
451 
452 
sae_derive_pwe_ffc(struct sae_data * sae,const u8 * addr1,const u8 * addr2,const u8 * password,size_t password_len,const char * identifier)453 static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
454 			      const u8 *addr2, const u8 *password,
455 			      size_t password_len, const char *identifier)
456 {
457 	u8 counter, k, sel_counter = 0;
458 	u8 addrs[2 * ETH_ALEN];
459 	const u8 *addr[3];
460 	size_t len[3];
461 	size_t num_elem;
462 	u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
463 		       * mask */
464 	u8 mask;
465 	struct crypto_bignum *pwe;
466 	size_t prime_len = sae->tmp->prime_len * 8;
467 	u8 *pwe_buf;
468 
469 	crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
470 	sae->tmp->pwe_ffc = NULL;
471 
472 	/* Allocate a buffer to maintain selected and candidate PWE for constant
473 	 * time selection. */
474 	pwe_buf = os_zalloc(prime_len * 2);
475 	pwe = crypto_bignum_init();
476 	if (!pwe_buf || !pwe)
477 		goto fail;
478 
479 	wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
480 			      password, password_len);
481 
482 	/*
483 	 * H(salt, ikm) = HMAC-SHA256(salt, ikm)
484 	 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
485 	 *              password [|| identifier] || counter)
486 	 */
487 	sae_pwd_seed_key(addr1, addr2, addrs);
488 
489 	addr[0] = password;
490 	len[0] = password_len;
491 	num_elem = 1;
492 	if (identifier) {
493 		addr[num_elem] = (const u8 *) identifier;
494 		len[num_elem] = os_strlen(identifier);
495 		num_elem++;
496 	}
497 	addr[num_elem] = &counter;
498 	len[num_elem] = sizeof(counter);
499 	num_elem++;
500 
501 	k = dragonfly_min_pwe_loop_iter(sae->group);
502 
503 	for (counter = 1; counter <= k || !found; counter++) {
504 		u8 pwd_seed[SHA256_MAC_LEN];
505 		int res;
506 
507 		if (counter > 200) {
508 			/* This should not happen in practice */
509 			wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
510 			break;
511 		}
512 
513 		wpa_printf(MSG_DEBUG, "SAE: counter = %02u", counter);
514 		if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
515 				       addr, len, pwd_seed) < 0)
516 			break;
517 		res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
518 		/* res is -1 for fatal failure, 0 if a valid PWE was not found,
519 		 * or 1 if a valid PWE was found. */
520 		if (res < 0)
521 			break;
522 		/* Store the candidate PWE into the second half of pwe_buf and
523 		 * the selected PWE in the beginning of pwe_buf using constant
524 		 * time selection. */
525 		if (crypto_bignum_to_bin(pwe, pwe_buf + prime_len, prime_len,
526 					 prime_len) < 0)
527 			break;
528 		const_time_select_bin(found, pwe_buf, pwe_buf + prime_len,
529 				      prime_len, pwe_buf);
530 		sel_counter = const_time_select_u8(found, sel_counter, counter);
531 		mask = const_time_eq_u8(res, 1);
532 		found = const_time_select_u8(found, found, mask);
533 	}
534 
535 	if (!found)
536 		goto fail;
537 
538 	wpa_printf(MSG_DEBUG, "SAE: Use PWE from counter = %02u", sel_counter);
539 	sae->tmp->pwe_ffc = crypto_bignum_init_set(pwe_buf, prime_len);
540 fail:
541 	crypto_bignum_deinit(pwe, 1);
542 	bin_clear_free(pwe_buf, prime_len * 2);
543 	return sae->tmp->pwe_ffc ? 0 : -1;
544 }
545 
546 
sae_derive_commit_element_ecc(struct sae_data * sae,struct crypto_bignum * mask)547 static int sae_derive_commit_element_ecc(struct sae_data *sae,
548 					 struct crypto_bignum *mask)
549 {
550 	/* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
551 	if (!sae->tmp->own_commit_element_ecc) {
552 		sae->tmp->own_commit_element_ecc =
553 			crypto_ec_point_init(sae->tmp->ec);
554 		if (!sae->tmp->own_commit_element_ecc)
555 			return -1;
556 	}
557 
558 	if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, mask,
559 				sae->tmp->own_commit_element_ecc) < 0 ||
560 	    crypto_ec_point_invert(sae->tmp->ec,
561 				   sae->tmp->own_commit_element_ecc) < 0) {
562 		wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
563 		return -1;
564 	}
565 
566 	return 0;
567 }
568 
569 
sae_derive_commit_element_ffc(struct sae_data * sae,struct crypto_bignum * mask)570 static int sae_derive_commit_element_ffc(struct sae_data *sae,
571 					 struct crypto_bignum *mask)
572 {
573 	/* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
574 	if (!sae->tmp->own_commit_element_ffc) {
575 		sae->tmp->own_commit_element_ffc = crypto_bignum_init();
576 		if (!sae->tmp->own_commit_element_ffc)
577 			return -1;
578 	}
579 
580 	if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, mask, sae->tmp->prime,
581 				  sae->tmp->own_commit_element_ffc) < 0 ||
582 	    crypto_bignum_inverse(sae->tmp->own_commit_element_ffc,
583 				  sae->tmp->prime,
584 				  sae->tmp->own_commit_element_ffc) < 0) {
585 		wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
586 		return -1;
587 	}
588 
589 	return 0;
590 }
591 
592 
sae_derive_commit(struct sae_data * sae)593 static int sae_derive_commit(struct sae_data *sae)
594 {
595 	struct crypto_bignum *mask;
596 	int ret;
597 
598 	mask = crypto_bignum_init();
599 	if (!sae->tmp->sae_rand)
600 		sae->tmp->sae_rand = crypto_bignum_init();
601 	if (!sae->tmp->own_commit_scalar)
602 		sae->tmp->own_commit_scalar = crypto_bignum_init();
603 	ret = !mask || !sae->tmp->sae_rand || !sae->tmp->own_commit_scalar ||
604 		dragonfly_generate_scalar(sae->tmp->order, sae->tmp->sae_rand,
605 					  mask,
606 					  sae->tmp->own_commit_scalar) < 0 ||
607 		(sae->tmp->ec &&
608 		 sae_derive_commit_element_ecc(sae, mask) < 0) ||
609 		(sae->tmp->dh &&
610 		 sae_derive_commit_element_ffc(sae, mask) < 0);
611 	crypto_bignum_deinit(mask, 1);
612 	return ret ? -1 : 0;
613 }
614 
615 
sae_prepare_commit(const u8 * addr1,const u8 * addr2,const u8 * password,size_t password_len,const char * identifier,struct sae_data * sae)616 int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
617 		       const u8 *password, size_t password_len,
618 		       const char *identifier, struct sae_data *sae)
619 {
620 	if (sae->tmp == NULL ||
621 	    (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
622 						password_len,
623 						identifier) < 0) ||
624 	    (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
625 						password_len,
626 						identifier) < 0) ||
627 	    sae_derive_commit(sae) < 0)
628 		return -1;
629 	return 0;
630 }
631 
632 
sae_derive_k_ecc(struct sae_data * sae,u8 * k)633 static int sae_derive_k_ecc(struct sae_data *sae, u8 *k)
634 {
635 	struct crypto_ec_point *K;
636 	int ret = -1;
637 
638 	K = crypto_ec_point_init(sae->tmp->ec);
639 	if (K == NULL)
640 		goto fail;
641 
642 	/*
643 	 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
644 	 *                                        PEER-COMMIT-ELEMENT)))
645 	 * If K is identity element (point-at-infinity), reject
646 	 * k = F(K) (= x coordinate)
647 	 */
648 
649 	if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc,
650 				sae->peer_commit_scalar, K) < 0 ||
651 	    crypto_ec_point_add(sae->tmp->ec, K,
652 				sae->tmp->peer_commit_element_ecc, K) < 0 ||
653 	    crypto_ec_point_mul(sae->tmp->ec, K, sae->tmp->sae_rand, K) < 0 ||
654 	    crypto_ec_point_is_at_infinity(sae->tmp->ec, K) ||
655 	    crypto_ec_point_to_bin(sae->tmp->ec, K, k, NULL) < 0) {
656 		wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
657 		goto fail;
658 	}
659 
660 	wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len);
661 
662 	ret = 0;
663 fail:
664 	crypto_ec_point_deinit(K, 1);
665 	return ret;
666 }
667 
668 
sae_derive_k_ffc(struct sae_data * sae,u8 * k)669 static int sae_derive_k_ffc(struct sae_data *sae, u8 *k)
670 {
671 	struct crypto_bignum *K;
672 	int ret = -1;
673 
674 	K = crypto_bignum_init();
675 	if (K == NULL)
676 		goto fail;
677 
678 	/*
679 	 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
680 	 *                                        PEER-COMMIT-ELEMENT)))
681 	 * If K is identity element (one), reject.
682 	 * k = F(K) (= x coordinate)
683 	 */
684 
685 	if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, sae->peer_commit_scalar,
686 				  sae->tmp->prime, K) < 0 ||
687 	    crypto_bignum_mulmod(K, sae->tmp->peer_commit_element_ffc,
688 				 sae->tmp->prime, K) < 0 ||
689 	    crypto_bignum_exptmod(K, sae->tmp->sae_rand, sae->tmp->prime, K) < 0
690 	    ||
691 	    crypto_bignum_is_one(K) ||
692 	    crypto_bignum_to_bin(K, k, SAE_MAX_PRIME_LEN, sae->tmp->prime_len) <
693 	    0) {
694 		wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
695 		goto fail;
696 	}
697 
698 	wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len);
699 
700 	ret = 0;
701 fail:
702 	crypto_bignum_deinit(K, 1);
703 	return ret;
704 }
705 
706 
sae_derive_keys(struct sae_data * sae,const u8 * k)707 static int sae_derive_keys(struct sae_data *sae, const u8 *k)
708 {
709 	u8 null_key[SAE_KEYSEED_KEY_LEN], val[SAE_MAX_PRIME_LEN];
710 	u8 keyseed[SHA256_MAC_LEN];
711 	u8 keys[SAE_KCK_LEN + SAE_PMK_LEN];
712 	struct crypto_bignum *tmp;
713 	int ret = -1;
714 
715 	tmp = crypto_bignum_init();
716 	if (tmp == NULL)
717 		goto fail;
718 
719 	/* keyseed = H(<0>32, k)
720 	 * KCK || PMK = KDF-512(keyseed, "SAE KCK and PMK",
721 	 *                      (commit-scalar + peer-commit-scalar) modulo r)
722 	 * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128)
723 	 */
724 
725 	os_memset(null_key, 0, sizeof(null_key));
726 	hmac_sha256(null_key, sizeof(null_key), k, sae->tmp->prime_len,
727 		    keyseed);
728 	wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, sizeof(keyseed));
729 
730 	crypto_bignum_add(sae->tmp->own_commit_scalar, sae->peer_commit_scalar,
731 			  tmp);
732 	crypto_bignum_mod(tmp, sae->tmp->order, tmp);
733 	/* IEEE Std 802.11-2016 is not exactly clear on the encoding of the bit
734 	 * string that is needed for KCK, PMK, and PMKID derivation, but it
735 	 * seems to make most sense to encode the
736 	 * (commit-scalar + peer-commit-scalar) mod r part as a bit string by
737 	 * zero padding it from left to the length of the order (in full
738 	 * octets). */
739 	crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->order_len);
740 	wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
741 	if (sha256_prf(keyseed, sizeof(keyseed), "SAE KCK and PMK",
742 		       val, sae->tmp->order_len, keys, sizeof(keys)) < 0)
743 		goto fail;
744 	os_memset(keyseed, 0, sizeof(keyseed));
745 	os_memcpy(sae->tmp->kck, keys, SAE_KCK_LEN);
746 	os_memcpy(sae->pmk, keys + SAE_KCK_LEN, SAE_PMK_LEN);
747 	os_memcpy(sae->pmkid, val, SAE_PMKID_LEN);
748 	os_memset(keys, 0, sizeof(keys));
749 	wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->tmp->kck, SAE_KCK_LEN);
750 	wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN);
751 
752 	ret = 0;
753 fail:
754 	crypto_bignum_deinit(tmp, 0);
755 	return ret;
756 }
757 
758 
sae_process_commit(struct sae_data * sae)759 int sae_process_commit(struct sae_data *sae)
760 {
761 	u8 k[SAE_MAX_PRIME_LEN];
762 	if (sae->tmp == NULL ||
763 	    (sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) ||
764 	    (sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) ||
765 	    sae_derive_keys(sae, k) < 0)
766 		return -1;
767 	return 0;
768 }
769 
770 
sae_write_commit(struct sae_data * sae,struct wpabuf * buf,const struct wpabuf * token,const char * identifier)771 void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
772 		      const struct wpabuf *token, const char *identifier)
773 {
774 	u8 *pos;
775 
776 	if (sae->tmp == NULL)
777 		return;
778 
779 	wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
780 	if (token) {
781 		wpabuf_put_buf(buf, token);
782 		wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token",
783 			    wpabuf_head(token), wpabuf_len(token));
784 	}
785 	pos = wpabuf_put(buf, sae->tmp->prime_len);
786 	crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
787 			     sae->tmp->prime_len, sae->tmp->prime_len);
788 	wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar",
789 		    pos, sae->tmp->prime_len);
790 	if (sae->tmp->ec) {
791 		pos = wpabuf_put(buf, 2 * sae->tmp->prime_len);
792 		crypto_ec_point_to_bin(sae->tmp->ec,
793 				       sae->tmp->own_commit_element_ecc,
794 				       pos, pos + sae->tmp->prime_len);
795 		wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)",
796 			    pos, sae->tmp->prime_len);
797 		wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)",
798 			    pos + sae->tmp->prime_len, sae->tmp->prime_len);
799 	} else {
800 		pos = wpabuf_put(buf, sae->tmp->prime_len);
801 		crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos,
802 				     sae->tmp->prime_len, sae->tmp->prime_len);
803 		wpa_hexdump(MSG_DEBUG, "SAE: own commit-element",
804 			    pos, sae->tmp->prime_len);
805 	}
806 
807 	if (identifier) {
808 		/* Password Identifier element */
809 		wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
810 		wpabuf_put_u8(buf, 1 + os_strlen(identifier));
811 		wpabuf_put_u8(buf, WLAN_EID_EXT_PASSWORD_IDENTIFIER);
812 		wpabuf_put_str(buf, identifier);
813 		wpa_printf(MSG_DEBUG, "SAE: own Password Identifier: %s",
814 			   identifier);
815 	}
816 }
817 
818 
sae_group_allowed(struct sae_data * sae,int * allowed_groups,u16 group)819 u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group)
820 {
821 	if (allowed_groups) {
822 		int i;
823 		for (i = 0; allowed_groups[i] > 0; i++) {
824 			if (allowed_groups[i] == group)
825 				break;
826 		}
827 		if (allowed_groups[i] != group) {
828 			wpa_printf(MSG_DEBUG, "SAE: Proposed group %u not "
829 				   "enabled in the current configuration",
830 				   group);
831 			return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
832 		}
833 	}
834 
835 	if (sae->state == SAE_COMMITTED && group != sae->group) {
836 		wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed");
837 		return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
838 	}
839 
840 	if (group != sae->group && sae_set_group(sae, group) < 0) {
841 		wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
842 			   group);
843 		return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
844 	}
845 
846 	if (sae->tmp == NULL) {
847 		wpa_printf(MSG_DEBUG, "SAE: Group information not yet initialized");
848 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
849 	}
850 
851 	if (sae->tmp->dh && !allowed_groups) {
852 		wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without "
853 			   "explicit configuration enabling it", group);
854 		return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
855 	}
856 
857 	return WLAN_STATUS_SUCCESS;
858 }
859 
860 
sae_is_password_id_elem(const u8 * pos,const u8 * end)861 static int sae_is_password_id_elem(const u8 *pos, const u8 *end)
862 {
863 	return end - pos >= 3 &&
864 		pos[0] == WLAN_EID_EXTENSION &&
865 		pos[1] >= 1 &&
866 		end - pos - 2 >= pos[1] &&
867 		pos[2] == WLAN_EID_EXT_PASSWORD_IDENTIFIER;
868 }
869 
870 
sae_parse_commit_token(struct sae_data * sae,const u8 ** pos,const u8 * end,const u8 ** token,size_t * token_len)871 static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
872 				   const u8 *end, const u8 **token,
873 				   size_t *token_len)
874 {
875 	size_t scalar_elem_len, tlen;
876 	const u8 *elem;
877 
878 	if (token)
879 		*token = NULL;
880 	if (token_len)
881 		*token_len = 0;
882 
883 	scalar_elem_len = (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len;
884 	if (scalar_elem_len >= (size_t) (end - *pos))
885 		return; /* No extra data beyond peer scalar and element */
886 
887 	/* It is a bit difficult to parse this now that there is an
888 	 * optional variable length Anti-Clogging Token field and
889 	 * optional variable length Password Identifier element in the
890 	 * frame. We are sending out fixed length Anti-Clogging Token
891 	 * fields, so use that length as a requirement for the received
892 	 * token and check for the presence of possible Password
893 	 * Identifier element based on the element header information.
894 	 */
895 	tlen = end - (*pos + scalar_elem_len);
896 
897 	if (tlen < SHA256_MAC_LEN) {
898 		wpa_printf(MSG_DEBUG,
899 			   "SAE: Too short optional data (%u octets) to include our Anti-Clogging Token",
900 			   (unsigned int) tlen);
901 		return;
902 	}
903 
904 	elem = *pos + scalar_elem_len;
905 	if (sae_is_password_id_elem(elem, end)) {
906 		 /* Password Identifier element takes out all available
907 		  * extra octets, so there can be no Anti-Clogging token in
908 		  * this frame. */
909 		return;
910 	}
911 
912 	elem += SHA256_MAC_LEN;
913 	if (sae_is_password_id_elem(elem, end)) {
914 		 /* Password Identifier element is included in the end, so
915 		  * remove its length from the Anti-Clogging token field. */
916 		tlen -= 2 + elem[1];
917 	}
918 
919 	wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
920 	if (token)
921 		*token = *pos;
922 	if (token_len)
923 		*token_len = tlen;
924 	*pos += tlen;
925 }
926 
927 
sae_parse_commit_scalar(struct sae_data * sae,const u8 ** pos,const u8 * end)928 static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos,
929 				   const u8 *end)
930 {
931 	struct crypto_bignum *peer_scalar;
932 
933 	if (sae->tmp->prime_len > end - *pos) {
934 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar");
935 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
936 	}
937 
938 	peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len);
939 	if (peer_scalar == NULL)
940 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
941 
942 	/*
943 	 * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for
944 	 * the peer and it is in Authenticated state, the new Commit Message
945 	 * shall be dropped if the peer-scalar is identical to the one used in
946 	 * the existing protocol instance.
947 	 */
948 	if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar &&
949 	    crypto_bignum_cmp(sae->peer_commit_scalar, peer_scalar) == 0) {
950 		wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous "
951 			   "peer-commit-scalar");
952 		crypto_bignum_deinit(peer_scalar, 0);
953 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
954 	}
955 
956 	/* 1 < scalar < r */
957 	if (crypto_bignum_is_zero(peer_scalar) ||
958 	    crypto_bignum_is_one(peer_scalar) ||
959 	    crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) {
960 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar");
961 		crypto_bignum_deinit(peer_scalar, 0);
962 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
963 	}
964 
965 
966 	crypto_bignum_deinit(sae->peer_commit_scalar, 0);
967 	sae->peer_commit_scalar = peer_scalar;
968 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar",
969 		    *pos, sae->tmp->prime_len);
970 	*pos += sae->tmp->prime_len;
971 
972 	return WLAN_STATUS_SUCCESS;
973 }
974 
975 
sae_parse_commit_element_ecc(struct sae_data * sae,const u8 ** pos,const u8 * end)976 static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 **pos,
977 					const u8 *end)
978 {
979 	u8 prime[SAE_MAX_ECC_PRIME_LEN];
980 
981 	if (2 * sae->tmp->prime_len > end - *pos) {
982 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
983 			   "commit-element");
984 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
985 	}
986 
987 	if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
988 				 sae->tmp->prime_len) < 0)
989 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
990 
991 	/* element x and y coordinates < p */
992 	if (os_memcmp(*pos, prime, sae->tmp->prime_len) >= 0 ||
993 	    os_memcmp(*pos + sae->tmp->prime_len, prime,
994 		      sae->tmp->prime_len) >= 0) {
995 		wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer "
996 			   "element");
997 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
998 	}
999 
1000 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)",
1001 		    *pos, sae->tmp->prime_len);
1002 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)",
1003 		    *pos + sae->tmp->prime_len, sae->tmp->prime_len);
1004 
1005 	crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0);
1006 	sae->tmp->peer_commit_element_ecc =
1007 		crypto_ec_point_from_bin(sae->tmp->ec, *pos);
1008 	if (sae->tmp->peer_commit_element_ecc == NULL)
1009 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1010 
1011 	if (!crypto_ec_point_is_on_curve(sae->tmp->ec,
1012 					 sae->tmp->peer_commit_element_ecc)) {
1013 		wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve");
1014 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1015 	}
1016 
1017 	*pos += 2 * sae->tmp->prime_len;
1018 
1019 	return WLAN_STATUS_SUCCESS;
1020 }
1021 
1022 
sae_parse_commit_element_ffc(struct sae_data * sae,const u8 ** pos,const u8 * end)1023 static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 **pos,
1024 					const u8 *end)
1025 {
1026 	struct crypto_bignum *res, *one;
1027 	const u8 one_bin[1] = { 0x01 };
1028 
1029 	if (sae->tmp->prime_len > end - *pos) {
1030 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
1031 			   "commit-element");
1032 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1033 	}
1034 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", *pos,
1035 		    sae->tmp->prime_len);
1036 
1037 	crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0);
1038 	sae->tmp->peer_commit_element_ffc =
1039 		crypto_bignum_init_set(*pos, sae->tmp->prime_len);
1040 	if (sae->tmp->peer_commit_element_ffc == NULL)
1041 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1042 	/* 1 < element < p - 1 */
1043 	res = crypto_bignum_init();
1044 	one = crypto_bignum_init_set(one_bin, sizeof(one_bin));
1045 	if (!res || !one ||
1046 	    crypto_bignum_sub(sae->tmp->prime, one, res) ||
1047 	    crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) ||
1048 	    crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) ||
1049 	    crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc, res) >= 0) {
1050 		crypto_bignum_deinit(res, 0);
1051 		crypto_bignum_deinit(one, 0);
1052 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer element");
1053 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1054 	}
1055 	crypto_bignum_deinit(one, 0);
1056 
1057 	/* scalar-op(r, ELEMENT) = 1 modulo p */
1058 	if (crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc,
1059 				  sae->tmp->order, sae->tmp->prime, res) < 0 ||
1060 	    !crypto_bignum_is_one(res)) {
1061 		wpa_printf(MSG_DEBUG, "SAE: Invalid peer element (scalar-op)");
1062 		crypto_bignum_deinit(res, 0);
1063 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1064 	}
1065 	crypto_bignum_deinit(res, 0);
1066 
1067 	*pos += sae->tmp->prime_len;
1068 
1069 	return WLAN_STATUS_SUCCESS;
1070 }
1071 
1072 
sae_parse_commit_element(struct sae_data * sae,const u8 ** pos,const u8 * end)1073 static u16 sae_parse_commit_element(struct sae_data *sae, const u8 **pos,
1074 				    const u8 *end)
1075 {
1076 	if (sae->tmp->dh)
1077 		return sae_parse_commit_element_ffc(sae, pos, end);
1078 	return sae_parse_commit_element_ecc(sae, pos, end);
1079 }
1080 
1081 
sae_parse_password_identifier(struct sae_data * sae,const u8 * pos,const u8 * end)1082 static int sae_parse_password_identifier(struct sae_data *sae,
1083 					 const u8 *pos, const u8 *end)
1084 {
1085 	wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
1086 		    pos, end - pos);
1087 	if (!sae_is_password_id_elem(pos, end)) {
1088 		if (sae->tmp->pw_id) {
1089 			wpa_printf(MSG_DEBUG,
1090 				   "SAE: No Password Identifier included, but expected one (%s)",
1091 				   sae->tmp->pw_id);
1092 			return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
1093 		}
1094 		os_free(sae->tmp->pw_id);
1095 		sae->tmp->pw_id = NULL;
1096 		return WLAN_STATUS_SUCCESS; /* No Password Identifier */
1097 	}
1098 
1099 	if (sae->tmp->pw_id &&
1100 	    (pos[1] - 1 != (int) os_strlen(sae->tmp->pw_id) ||
1101 	     os_memcmp(sae->tmp->pw_id, pos + 3, pos[1] - 1) != 0)) {
1102 		wpa_printf(MSG_DEBUG,
1103 			   "SAE: The included Password Identifier does not match the expected one (%s)",
1104 			   sae->tmp->pw_id);
1105 		return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
1106 	}
1107 
1108 	os_free(sae->tmp->pw_id);
1109 	sae->tmp->pw_id = os_malloc(pos[1]);
1110 	if (!sae->tmp->pw_id)
1111 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1112 	os_memcpy(sae->tmp->pw_id, pos + 3, pos[1] - 1);
1113 	sae->tmp->pw_id[pos[1] - 1] = '\0';
1114 	wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier",
1115 			  sae->tmp->pw_id, pos[1] -  1);
1116 	return WLAN_STATUS_SUCCESS;
1117 }
1118 
1119 
sae_parse_commit(struct sae_data * sae,const u8 * data,size_t len,const u8 ** token,size_t * token_len,int * allowed_groups)1120 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
1121 		     const u8 **token, size_t *token_len, int *allowed_groups)
1122 {
1123 	const u8 *pos = data, *end = data + len;
1124 	u16 res;
1125 
1126 	/* Check Finite Cyclic Group */
1127 	if (end - pos < 2)
1128 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
1129 	res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos));
1130 	if (res != WLAN_STATUS_SUCCESS)
1131 		return res;
1132 	pos += 2;
1133 
1134 	/* Optional Anti-Clogging Token */
1135 	sae_parse_commit_token(sae, &pos, end, token, token_len);
1136 
1137 	/* commit-scalar */
1138 	res = sae_parse_commit_scalar(sae, &pos, end);
1139 	if (res != WLAN_STATUS_SUCCESS)
1140 		return res;
1141 
1142 	/* commit-element */
1143 	res = sae_parse_commit_element(sae, &pos, end);
1144 	if (res != WLAN_STATUS_SUCCESS)
1145 		return res;
1146 
1147 	/* Optional Password Identifier element */
1148 	res = sae_parse_password_identifier(sae, pos, end);
1149 	if (res != WLAN_STATUS_SUCCESS)
1150 		return res;
1151 
1152 	/*
1153 	 * Check whether peer-commit-scalar and PEER-COMMIT-ELEMENT are same as
1154 	 * the values we sent which would be evidence of a reflection attack.
1155 	 */
1156 	if (!sae->tmp->own_commit_scalar ||
1157 	    crypto_bignum_cmp(sae->tmp->own_commit_scalar,
1158 			      sae->peer_commit_scalar) != 0 ||
1159 	    (sae->tmp->dh &&
1160 	     (!sae->tmp->own_commit_element_ffc ||
1161 	      crypto_bignum_cmp(sae->tmp->own_commit_element_ffc,
1162 				sae->tmp->peer_commit_element_ffc) != 0)) ||
1163 	    (sae->tmp->ec &&
1164 	     (!sae->tmp->own_commit_element_ecc ||
1165 	      crypto_ec_point_cmp(sae->tmp->ec,
1166 				  sae->tmp->own_commit_element_ecc,
1167 				  sae->tmp->peer_commit_element_ecc) != 0)))
1168 		return WLAN_STATUS_SUCCESS; /* scalars/elements are different */
1169 
1170 	/*
1171 	 * This is a reflection attack - return special value to trigger caller
1172 	 * to silently discard the frame instead of replying with a specific
1173 	 * status code.
1174 	 */
1175 	return SAE_SILENTLY_DISCARD;
1176 }
1177 
1178 
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)1179 static void sae_cn_confirm(struct sae_data *sae, const u8 *sc,
1180 			   const struct crypto_bignum *scalar1,
1181 			   const u8 *element1, size_t element1_len,
1182 			   const struct crypto_bignum *scalar2,
1183 			   const u8 *element2, size_t element2_len,
1184 			   u8 *confirm)
1185 {
1186 	const u8 *addr[5];
1187 	size_t len[5];
1188 	u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN];
1189 
1190 	/* Confirm
1191 	 * CN(key, X, Y, Z, ...) =
1192 	 *    HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...)
1193 	 * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT,
1194 	 *              peer-commit-scalar, PEER-COMMIT-ELEMENT)
1195 	 * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar,
1196 	 *               PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT)
1197 	 */
1198 	addr[0] = sc;
1199 	len[0] = 2;
1200 	crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1),
1201 			     sae->tmp->prime_len);
1202 	addr[1] = scalar_b1;
1203 	len[1] = sae->tmp->prime_len;
1204 	addr[2] = element1;
1205 	len[2] = element1_len;
1206 	crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2),
1207 			     sae->tmp->prime_len);
1208 	addr[3] = scalar_b2;
1209 	len[3] = sae->tmp->prime_len;
1210 	addr[4] = element2;
1211 	len[4] = element2_len;
1212 	hmac_sha256_vector(sae->tmp->kck, sizeof(sae->tmp->kck), 5, addr, len,
1213 			   confirm);
1214 }
1215 
1216 
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)1217 static void sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
1218 			       const struct crypto_bignum *scalar1,
1219 			       const struct crypto_ec_point *element1,
1220 			       const struct crypto_bignum *scalar2,
1221 			       const struct crypto_ec_point *element2,
1222 			       u8 *confirm)
1223 {
1224 	u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN];
1225 	u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN];
1226 
1227 	crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1,
1228 			       element_b1 + sae->tmp->prime_len);
1229 	crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2,
1230 			       element_b2 + sae->tmp->prime_len);
1231 
1232 	sae_cn_confirm(sae, sc, scalar1, element_b1, 2 * sae->tmp->prime_len,
1233 		       scalar2, element_b2, 2 * sae->tmp->prime_len, confirm);
1234 }
1235 
1236 
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)1237 static void sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
1238 			       const struct crypto_bignum *scalar1,
1239 			       const struct crypto_bignum *element1,
1240 			       const struct crypto_bignum *scalar2,
1241 			       const struct crypto_bignum *element2,
1242 			       u8 *confirm)
1243 {
1244 	u8 element_b1[SAE_MAX_PRIME_LEN];
1245 	u8 element_b2[SAE_MAX_PRIME_LEN];
1246 
1247 	crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1),
1248 			     sae->tmp->prime_len);
1249 	crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2),
1250 			     sae->tmp->prime_len);
1251 
1252 	sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len,
1253 		       scalar2, element_b2, sae->tmp->prime_len, confirm);
1254 }
1255 
1256 
sae_write_confirm(struct sae_data * sae,struct wpabuf * buf)1257 void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
1258 {
1259 	const u8 *sc;
1260 
1261 	if (sae->tmp == NULL)
1262 		return;
1263 
1264 	/* Send-Confirm */
1265 	sc = wpabuf_put(buf, 0);
1266 	wpabuf_put_le16(buf, sae->send_confirm);
1267 	if (sae->send_confirm < 0xffff)
1268 		sae->send_confirm++;
1269 
1270 	if (sae->tmp->ec)
1271 		sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
1272 				   sae->tmp->own_commit_element_ecc,
1273 				   sae->peer_commit_scalar,
1274 				   sae->tmp->peer_commit_element_ecc,
1275 				   wpabuf_put(buf, SHA256_MAC_LEN));
1276 	else
1277 		sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar,
1278 				   sae->tmp->own_commit_element_ffc,
1279 				   sae->peer_commit_scalar,
1280 				   sae->tmp->peer_commit_element_ffc,
1281 				   wpabuf_put(buf, SHA256_MAC_LEN));
1282 }
1283 
1284 
sae_check_confirm(struct sae_data * sae,const u8 * data,size_t len)1285 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
1286 {
1287 	u8 verifier[SHA256_MAC_LEN];
1288 
1289 	if (len < 2 + SHA256_MAC_LEN) {
1290 		wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
1291 		return -1;
1292 	}
1293 
1294 	wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data));
1295 
1296 	if (!sae->tmp || !sae->peer_commit_scalar ||
1297 	    !sae->tmp->own_commit_scalar) {
1298 		wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available");
1299 		return -1;
1300 	}
1301 
1302 	if (sae->tmp->ec) {
1303 		if (!sae->tmp->peer_commit_element_ecc ||
1304 		    !sae->tmp->own_commit_element_ecc)
1305 			return -1;
1306 		sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar,
1307 				   sae->tmp->peer_commit_element_ecc,
1308 				   sae->tmp->own_commit_scalar,
1309 				   sae->tmp->own_commit_element_ecc,
1310 				   verifier);
1311 	} else {
1312 		if (!sae->tmp->peer_commit_element_ffc ||
1313 		    !sae->tmp->own_commit_element_ffc)
1314 			return -1;
1315 		sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar,
1316 				   sae->tmp->peer_commit_element_ffc,
1317 				   sae->tmp->own_commit_scalar,
1318 				   sae->tmp->own_commit_element_ffc,
1319 				   verifier);
1320 	}
1321 
1322 	if (os_memcmp_const(verifier, data + 2, SHA256_MAC_LEN) != 0) {
1323 		wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
1324 		wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
1325 			    data + 2, SHA256_MAC_LEN);
1326 		wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
1327 			    verifier, SHA256_MAC_LEN);
1328 		return -1;
1329 	}
1330 
1331 	return 0;
1332 }
1333 
1334 
sae_state_txt(enum sae_state state)1335 const char * sae_state_txt(enum sae_state state)
1336 {
1337 	switch (state) {
1338 	case SAE_NOTHING:
1339 		return "Nothing";
1340 	case SAE_COMMITTED:
1341 		return "Committed";
1342 	case SAE_CONFIRMED:
1343 		return "Confirmed";
1344 	case SAE_ACCEPTED:
1345 		return "Accepted";
1346 	}
1347 	return "?";
1348 }
1349