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