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