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