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