]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa/src/common/sae.c
MFV ntp 4.2.8p2 (r281348)
[FreeBSD/FreeBSD.git] / contrib / wpa / src / common / sae.c
1 /*
2  * Simultaneous authentication of equals
3  * Copyright (c) 2012-2013, 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                 sae->group = group;
33                 tmp->prime_len = crypto_ec_prime_len(tmp->ec);
34                 tmp->prime = crypto_ec_get_prime(tmp->ec);
35                 tmp->order = crypto_ec_get_order(tmp->ec);
36                 return 0;
37         }
38
39         /* Not an ECC group, check FFC */
40         tmp->dh = dh_groups_get(group);
41         if (tmp->dh) {
42                 sae->group = group;
43                 tmp->prime_len = tmp->dh->prime_len;
44                 if (tmp->prime_len > SAE_MAX_PRIME_LEN) {
45                         sae_clear_data(sae);
46                         return -1;
47                 }
48
49                 tmp->prime_buf = crypto_bignum_init_set(tmp->dh->prime,
50                                                         tmp->prime_len);
51                 if (tmp->prime_buf == NULL) {
52                         sae_clear_data(sae);
53                         return -1;
54                 }
55                 tmp->prime = tmp->prime_buf;
56
57                 tmp->order_buf = crypto_bignum_init_set(tmp->dh->order,
58                                                         tmp->dh->order_len);
59                 if (tmp->order_buf == NULL) {
60                         sae_clear_data(sae);
61                         return -1;
62                 }
63                 tmp->order = tmp->order_buf;
64
65                 return 0;
66         }
67
68         /* Unsupported group */
69         return -1;
70 }
71
72
73 void sae_clear_temp_data(struct sae_data *sae)
74 {
75         struct sae_temporary_data *tmp;
76         if (sae == NULL || sae->tmp == NULL)
77                 return;
78         tmp = sae->tmp;
79         crypto_ec_deinit(tmp->ec);
80         crypto_bignum_deinit(tmp->prime_buf, 0);
81         crypto_bignum_deinit(tmp->order_buf, 0);
82         crypto_bignum_deinit(tmp->sae_rand, 1);
83         crypto_bignum_deinit(tmp->pwe_ffc, 1);
84         crypto_bignum_deinit(tmp->own_commit_scalar, 0);
85         crypto_bignum_deinit(tmp->own_commit_element_ffc, 0);
86         crypto_bignum_deinit(tmp->peer_commit_element_ffc, 0);
87         crypto_ec_point_deinit(tmp->pwe_ecc, 1);
88         crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0);
89         crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0);
90         wpabuf_free(tmp->anti_clogging_token);
91         bin_clear_free(tmp, sizeof(*tmp));
92         sae->tmp = NULL;
93 }
94
95
96 void sae_clear_data(struct sae_data *sae)
97 {
98         if (sae == NULL)
99                 return;
100         sae_clear_temp_data(sae);
101         crypto_bignum_deinit(sae->peer_commit_scalar, 0);
102         os_memset(sae, 0, sizeof(*sae));
103 }
104
105
106 static void buf_shift_right(u8 *buf, size_t len, size_t bits)
107 {
108         size_t i;
109         for (i = len - 1; i > 0; i--)
110                 buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits);
111         buf[0] >>= bits;
112 }
113
114
115 static struct crypto_bignum * sae_get_rand(struct sae_data *sae)
116 {
117         u8 val[SAE_MAX_PRIME_LEN];
118         int iter = 0;
119         struct crypto_bignum *bn = NULL;
120         int order_len_bits = crypto_bignum_bits(sae->tmp->order);
121         size_t order_len = (order_len_bits + 7) / 8;
122
123         if (order_len > sizeof(val))
124                 return NULL;
125
126         for (;;) {
127                 if (iter++ > 100)
128                         return NULL;
129                 if (random_get_bytes(val, order_len) < 0)
130                         return NULL;
131                 if (order_len_bits % 8)
132                         buf_shift_right(val, order_len, 8 - order_len_bits % 8);
133                 bn = crypto_bignum_init_set(val, order_len);
134                 if (bn == NULL)
135                         return NULL;
136                 if (crypto_bignum_is_zero(bn) ||
137                     crypto_bignum_is_one(bn) ||
138                     crypto_bignum_cmp(bn, sae->tmp->order) >= 0) {
139                         crypto_bignum_deinit(bn, 0);
140                         continue;
141                 }
142                 break;
143         }
144
145         os_memset(val, 0, order_len);
146         return bn;
147 }
148
149
150 static struct crypto_bignum * sae_get_rand_and_mask(struct sae_data *sae)
151 {
152         crypto_bignum_deinit(sae->tmp->sae_rand, 1);
153         sae->tmp->sae_rand = sae_get_rand(sae);
154         if (sae->tmp->sae_rand == NULL)
155                 return NULL;
156         return sae_get_rand(sae);
157 }
158
159
160 static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key)
161 {
162         wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR
163                    " addr2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2));
164         if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) {
165                 os_memcpy(key, addr1, ETH_ALEN);
166                 os_memcpy(key + ETH_ALEN, addr2, ETH_ALEN);
167         } else {
168                 os_memcpy(key, addr2, ETH_ALEN);
169                 os_memcpy(key + ETH_ALEN, addr1, ETH_ALEN);
170         }
171 }
172
173
174 static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
175                                  struct crypto_ec_point *pwe)
176 {
177         u8 pwd_value[SAE_MAX_ECC_PRIME_LEN], prime[SAE_MAX_ECC_PRIME_LEN];
178         struct crypto_bignum *x;
179         int y_bit;
180         size_t bits;
181
182         if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
183                                  sae->tmp->prime_len) < 0)
184                 return -1;
185
186         wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
187
188         /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
189         bits = crypto_ec_prime_len_bits(sae->tmp->ec);
190         sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
191                         prime, sae->tmp->prime_len, pwd_value, bits);
192         if (bits % 8)
193                 buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
194         wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
195                         pwd_value, sae->tmp->prime_len);
196
197         if (os_memcmp(pwd_value, prime, sae->tmp->prime_len) >= 0)
198                 return 0;
199
200         y_bit = pwd_seed[SHA256_MAC_LEN - 1] & 0x01;
201
202         x = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
203         if (x == NULL)
204                 return -1;
205         if (crypto_ec_point_solve_y_coord(sae->tmp->ec, pwe, x, y_bit) < 0) {
206                 crypto_bignum_deinit(x, 0);
207                 wpa_printf(MSG_DEBUG, "SAE: No solution found");
208                 return 0;
209         }
210         crypto_bignum_deinit(x, 0);
211
212         wpa_printf(MSG_DEBUG, "SAE: PWE found");
213
214         return 1;
215 }
216
217
218 static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
219                                  struct crypto_bignum *pwe)
220 {
221         u8 pwd_value[SAE_MAX_PRIME_LEN];
222         size_t bits = sae->tmp->prime_len * 8;
223         u8 exp[1];
224         struct crypto_bignum *a, *b;
225         int res;
226
227         wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
228
229         /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
230         sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
231                         sae->tmp->dh->prime, sae->tmp->prime_len, pwd_value,
232                         bits);
233         if (bits % 8)
234                 buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
235         wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value,
236                         sae->tmp->prime_len);
237
238         if (os_memcmp(pwd_value, sae->tmp->dh->prime, sae->tmp->prime_len) >= 0)
239         {
240                 wpa_printf(MSG_DEBUG, "SAE: pwd-value >= p");
241                 return 0;
242         }
243
244         /* PWE = pwd-value^((p-1)/r) modulo p */
245
246         a = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
247
248         if (sae->tmp->dh->safe_prime) {
249                 /*
250                  * r = (p-1)/2 for the group used here, so this becomes:
251                  * PWE = pwd-value^2 modulo p
252                  */
253                 exp[0] = 2;
254                 b = crypto_bignum_init_set(exp, sizeof(exp));
255         } else {
256                 /* Calculate exponent: (p-1)/r */
257                 exp[0] = 1;
258                 b = crypto_bignum_init_set(exp, sizeof(exp));
259                 if (b == NULL ||
260                     crypto_bignum_sub(sae->tmp->prime, b, b) < 0 ||
261                     crypto_bignum_div(b, sae->tmp->order, b) < 0) {
262                         crypto_bignum_deinit(b, 0);
263                         b = NULL;
264                 }
265         }
266
267         if (a == NULL || b == NULL)
268                 res = -1;
269         else
270                 res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe);
271
272         crypto_bignum_deinit(a, 0);
273         crypto_bignum_deinit(b, 0);
274
275         if (res < 0) {
276                 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate PWE");
277                 return -1;
278         }
279
280         /* if (PWE > 1) --> found */
281         if (crypto_bignum_is_zero(pwe) || crypto_bignum_is_one(pwe)) {
282                 wpa_printf(MSG_DEBUG, "SAE: PWE <= 1");
283                 return 0;
284         }
285
286         wpa_printf(MSG_DEBUG, "SAE: PWE found");
287         return 1;
288 }
289
290
291 static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
292                               const u8 *addr2, const u8 *password,
293                               size_t password_len)
294 {
295         u8 counter, k = 4;
296         u8 addrs[2 * ETH_ALEN];
297         const u8 *addr[2];
298         size_t len[2];
299         int found = 0;
300         struct crypto_ec_point *pwe_tmp;
301
302         if (sae->tmp->pwe_ecc == NULL) {
303                 sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec);
304                 if (sae->tmp->pwe_ecc == NULL)
305                         return -1;
306         }
307         pwe_tmp = crypto_ec_point_init(sae->tmp->ec);
308         if (pwe_tmp == NULL)
309                 return -1;
310
311         wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
312                               password, password_len);
313
314         /*
315          * H(salt, ikm) = HMAC-SHA256(salt, ikm)
316          * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
317          *              password || counter)
318          */
319         sae_pwd_seed_key(addr1, addr2, addrs);
320
321         addr[0] = password;
322         len[0] = password_len;
323         addr[1] = &counter;
324         len[1] = sizeof(counter);
325
326         /*
327          * Continue for at least k iterations to protect against side-channel
328          * attacks that attempt to determine the number of iterations required
329          * in the loop.
330          */
331         for (counter = 1; counter < k || !found; counter++) {
332                 u8 pwd_seed[SHA256_MAC_LEN];
333                 int res;
334
335                 if (counter > 200) {
336                         /* This should not happen in practice */
337                         wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
338                         break;
339                 }
340
341                 wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
342                 if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len,
343                                        pwd_seed) < 0)
344                         break;
345                 res = sae_test_pwd_seed_ecc(sae, pwd_seed,
346                                             found ? pwe_tmp :
347                                             sae->tmp->pwe_ecc);
348                 if (res < 0)
349                         break;
350                 if (res == 0)
351                         continue;
352                 if (found) {
353                         wpa_printf(MSG_DEBUG, "SAE: Ignore this PWE (one was "
354                                    "already selected)");
355                 } else {
356                         wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
357                         found = 1;
358                 }
359         }
360
361         crypto_ec_point_deinit(pwe_tmp, 1);
362
363         return found ? 0 : -1;
364 }
365
366
367 static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
368                               const u8 *addr2, const u8 *password,
369                               size_t password_len)
370 {
371         u8 counter;
372         u8 addrs[2 * ETH_ALEN];
373         const u8 *addr[2];
374         size_t len[2];
375         int found = 0;
376
377         if (sae->tmp->pwe_ffc == NULL) {
378                 sae->tmp->pwe_ffc = crypto_bignum_init();
379                 if (sae->tmp->pwe_ffc == NULL)
380                         return -1;
381         }
382
383         wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
384                               password, password_len);
385
386         /*
387          * H(salt, ikm) = HMAC-SHA256(salt, ikm)
388          * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
389          *              password || counter)
390          */
391         sae_pwd_seed_key(addr1, addr2, addrs);
392
393         addr[0] = password;
394         len[0] = password_len;
395         addr[1] = &counter;
396         len[1] = sizeof(counter);
397
398         for (counter = 1; !found; counter++) {
399                 u8 pwd_seed[SHA256_MAC_LEN];
400                 int res;
401
402                 if (counter > 200) {
403                         /* This should not happen in practice */
404                         wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
405                         break;
406                 }
407
408                 wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
409                 if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len,
410                                        pwd_seed) < 0)
411                         break;
412                 res = sae_test_pwd_seed_ffc(sae, pwd_seed, sae->tmp->pwe_ffc);
413                 if (res < 0)
414                         break;
415                 if (res > 0) {
416                         wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
417                         found = 1;
418                 }
419         }
420
421         return found ? 0 : -1;
422 }
423
424
425 static int sae_derive_commit_element_ecc(struct sae_data *sae,
426                                          struct crypto_bignum *mask)
427 {
428         /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
429         if (!sae->tmp->own_commit_element_ecc) {
430                 sae->tmp->own_commit_element_ecc =
431                         crypto_ec_point_init(sae->tmp->ec);
432                 if (!sae->tmp->own_commit_element_ecc)
433                         return -1;
434         }
435
436         if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, mask,
437                                 sae->tmp->own_commit_element_ecc) < 0 ||
438             crypto_ec_point_invert(sae->tmp->ec,
439                                    sae->tmp->own_commit_element_ecc) < 0) {
440                 wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
441                 return -1;
442         }
443
444         return 0;
445 }
446
447
448 static int sae_derive_commit_element_ffc(struct sae_data *sae,
449                                          struct crypto_bignum *mask)
450 {
451         /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
452         if (!sae->tmp->own_commit_element_ffc) {
453                 sae->tmp->own_commit_element_ffc = crypto_bignum_init();
454                 if (!sae->tmp->own_commit_element_ffc)
455                         return -1;
456         }
457
458         if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, mask, sae->tmp->prime,
459                                   sae->tmp->own_commit_element_ffc) < 0 ||
460             crypto_bignum_inverse(sae->tmp->own_commit_element_ffc,
461                                   sae->tmp->prime,
462                                   sae->tmp->own_commit_element_ffc) < 0) {
463                 wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
464                 return -1;
465         }
466
467         return 0;
468 }
469
470
471 static int sae_derive_commit(struct sae_data *sae)
472 {
473         struct crypto_bignum *mask;
474         int ret = -1;
475
476         mask = sae_get_rand_and_mask(sae);
477         if (mask == NULL) {
478                 wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask");
479                 return -1;
480         }
481
482         /* commit-scalar = (rand + mask) modulo r */
483         if (!sae->tmp->own_commit_scalar) {
484                 sae->tmp->own_commit_scalar = crypto_bignum_init();
485                 if (!sae->tmp->own_commit_scalar)
486                         goto fail;
487         }
488         crypto_bignum_add(sae->tmp->sae_rand, mask,
489                           sae->tmp->own_commit_scalar);
490         crypto_bignum_mod(sae->tmp->own_commit_scalar, sae->tmp->order,
491                           sae->tmp->own_commit_scalar);
492
493         if (sae->tmp->ec && sae_derive_commit_element_ecc(sae, mask) < 0)
494                 goto fail;
495         if (sae->tmp->dh && sae_derive_commit_element_ffc(sae, mask) < 0)
496                 goto fail;
497
498         ret = 0;
499 fail:
500         crypto_bignum_deinit(mask, 1);
501         return ret;
502 }
503
504
505 int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
506                        const u8 *password, size_t password_len,
507                        struct sae_data *sae)
508 {
509         if (sae->tmp == NULL)
510                 return -1;
511         if (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
512                                           password_len) < 0)
513                 return -1;
514         if (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
515                                           password_len) < 0)
516                 return -1;
517         if (sae_derive_commit(sae) < 0)
518                 return -1;
519         return 0;
520 }
521
522
523 static int sae_derive_k_ecc(struct sae_data *sae, u8 *k)
524 {
525         struct crypto_ec_point *K;
526         int ret = -1;
527
528         K = crypto_ec_point_init(sae->tmp->ec);
529         if (K == NULL)
530                 goto fail;
531
532         /*
533          * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
534          *                                        PEER-COMMIT-ELEMENT)))
535          * If K is identity element (point-at-infinity), reject
536          * k = F(K) (= x coordinate)
537          */
538
539         if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc,
540                                 sae->peer_commit_scalar, K) < 0 ||
541             crypto_ec_point_add(sae->tmp->ec, K,
542                                 sae->tmp->peer_commit_element_ecc, K) < 0 ||
543             crypto_ec_point_mul(sae->tmp->ec, K, sae->tmp->sae_rand, K) < 0 ||
544             crypto_ec_point_is_at_infinity(sae->tmp->ec, K) ||
545             crypto_ec_point_to_bin(sae->tmp->ec, K, k, NULL) < 0) {
546                 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
547                 goto fail;
548         }
549
550         wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len);
551
552         ret = 0;
553 fail:
554         crypto_ec_point_deinit(K, 1);
555         return ret;
556 }
557
558
559 static int sae_derive_k_ffc(struct sae_data *sae, u8 *k)
560 {
561         struct crypto_bignum *K;
562         int ret = -1;
563
564         K = crypto_bignum_init();
565         if (K == NULL)
566                 goto fail;
567
568         /*
569          * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
570          *                                        PEER-COMMIT-ELEMENT)))
571          * If K is identity element (one), reject.
572          * k = F(K) (= x coordinate)
573          */
574
575         if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, sae->peer_commit_scalar,
576                                   sae->tmp->prime, K) < 0 ||
577             crypto_bignum_mulmod(K, sae->tmp->peer_commit_element_ffc,
578                                  sae->tmp->prime, K) < 0 ||
579             crypto_bignum_exptmod(K, sae->tmp->sae_rand, sae->tmp->prime, K) < 0
580             ||
581             crypto_bignum_is_one(K) ||
582             crypto_bignum_to_bin(K, k, SAE_MAX_PRIME_LEN, sae->tmp->prime_len) <
583             0) {
584                 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
585                 goto fail;
586         }
587
588         wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len);
589
590         ret = 0;
591 fail:
592         crypto_bignum_deinit(K, 1);
593         return ret;
594 }
595
596
597 static int sae_derive_keys(struct sae_data *sae, const u8 *k)
598 {
599         u8 null_key[SAE_KEYSEED_KEY_LEN], val[SAE_MAX_PRIME_LEN];
600         u8 keyseed[SHA256_MAC_LEN];
601         u8 keys[SAE_KCK_LEN + SAE_PMK_LEN];
602         struct crypto_bignum *tmp;
603         int ret = -1;
604
605         tmp = crypto_bignum_init();
606         if (tmp == NULL)
607                 goto fail;
608
609         /* keyseed = H(<0>32, k)
610          * KCK || PMK = KDF-512(keyseed, "SAE KCK and PMK",
611          *                      (commit-scalar + peer-commit-scalar) modulo r)
612          * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128)
613          */
614
615         os_memset(null_key, 0, sizeof(null_key));
616         hmac_sha256(null_key, sizeof(null_key), k, sae->tmp->prime_len,
617                     keyseed);
618         wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, sizeof(keyseed));
619
620         crypto_bignum_add(sae->tmp->own_commit_scalar, sae->peer_commit_scalar,
621                           tmp);
622         crypto_bignum_mod(tmp, sae->tmp->order, tmp);
623         crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->prime_len);
624         wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
625         sha256_prf(keyseed, sizeof(keyseed), "SAE KCK and PMK",
626                    val, sae->tmp->prime_len, keys, sizeof(keys));
627         os_memset(keyseed, 0, sizeof(keyseed));
628         os_memcpy(sae->tmp->kck, keys, SAE_KCK_LEN);
629         os_memcpy(sae->pmk, keys + SAE_KCK_LEN, SAE_PMK_LEN);
630         os_memset(keys, 0, sizeof(keys));
631         wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->tmp->kck, SAE_KCK_LEN);
632         wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN);
633
634         ret = 0;
635 fail:
636         crypto_bignum_deinit(tmp, 0);
637         return ret;
638 }
639
640
641 int sae_process_commit(struct sae_data *sae)
642 {
643         u8 k[SAE_MAX_PRIME_LEN];
644         if (sae->tmp == NULL ||
645             (sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) ||
646             (sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) ||
647             sae_derive_keys(sae, k) < 0)
648                 return -1;
649         return 0;
650 }
651
652
653 void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
654                       const struct wpabuf *token)
655 {
656         u8 *pos;
657
658         if (sae->tmp == NULL)
659                 return;
660
661         wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
662         if (token) {
663                 wpabuf_put_buf(buf, token);
664                 wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token",
665                             wpabuf_head(token), wpabuf_len(token));
666         }
667         pos = wpabuf_put(buf, sae->tmp->prime_len);
668         crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
669                              sae->tmp->prime_len, sae->tmp->prime_len);
670         wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar",
671                     pos, sae->tmp->prime_len);
672         if (sae->tmp->ec) {
673                 pos = wpabuf_put(buf, 2 * sae->tmp->prime_len);
674                 crypto_ec_point_to_bin(sae->tmp->ec,
675                                        sae->tmp->own_commit_element_ecc,
676                                        pos, pos + sae->tmp->prime_len);
677                 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)",
678                             pos, sae->tmp->prime_len);
679                 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)",
680                             pos + sae->tmp->prime_len, sae->tmp->prime_len);
681         } else {
682                 pos = wpabuf_put(buf, sae->tmp->prime_len);
683                 crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos,
684                                      sae->tmp->prime_len, sae->tmp->prime_len);
685                 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element",
686                             pos, sae->tmp->prime_len);
687         }
688 }
689
690
691 u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group)
692 {
693         if (allowed_groups) {
694                 int i;
695                 for (i = 0; allowed_groups[i] > 0; i++) {
696                         if (allowed_groups[i] == group)
697                                 break;
698                 }
699                 if (allowed_groups[i] != group) {
700                         wpa_printf(MSG_DEBUG, "SAE: Proposed group %u not "
701                                    "enabled in the current configuration",
702                                    group);
703                         return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
704                 }
705         }
706
707         if (sae->state == SAE_COMMITTED && group != sae->group) {
708                 wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed");
709                 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
710         }
711
712         if (group != sae->group && sae_set_group(sae, group) < 0) {
713                 wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
714                            group);
715                 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
716         }
717
718         if (sae->tmp == NULL) {
719                 wpa_printf(MSG_DEBUG, "SAE: Group information not yet initialized");
720                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
721         }
722
723         if (sae->tmp->dh && !allowed_groups) {
724                 wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without "
725                            "explicit configuration enabling it", group);
726                 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
727         }
728
729         return WLAN_STATUS_SUCCESS;
730 }
731
732
733 static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
734                                    const u8 *end, const u8 **token,
735                                    size_t *token_len)
736 {
737         if (*pos + (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len < end) {
738                 size_t tlen = end - (*pos + (sae->tmp->ec ? 3 : 2) *
739                                      sae->tmp->prime_len);
740                 wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
741                 if (token)
742                         *token = *pos;
743                 if (token_len)
744                         *token_len = tlen;
745                 *pos += tlen;
746         } else {
747                 if (token)
748                         *token = NULL;
749                 if (token_len)
750                         *token_len = 0;
751         }
752 }
753
754
755 static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos,
756                                    const u8 *end)
757 {
758         struct crypto_bignum *peer_scalar;
759
760         if (*pos + sae->tmp->prime_len > end) {
761                 wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar");
762                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
763         }
764
765         peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len);
766         if (peer_scalar == NULL)
767                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
768
769         /*
770          * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for
771          * the peer and it is in Authenticated state, the new Commit Message
772          * shall be dropped if the peer-scalar is identical to the one used in
773          * the existing protocol instance.
774          */
775         if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar &&
776             crypto_bignum_cmp(sae->peer_commit_scalar, peer_scalar) == 0) {
777                 wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous "
778                            "peer-commit-scalar");
779                 crypto_bignum_deinit(peer_scalar, 0);
780                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
781         }
782
783         /* 0 < scalar < r */
784         if (crypto_bignum_is_zero(peer_scalar) ||
785             crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) {
786                 wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar");
787                 crypto_bignum_deinit(peer_scalar, 0);
788                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
789         }
790
791
792         crypto_bignum_deinit(sae->peer_commit_scalar, 0);
793         sae->peer_commit_scalar = peer_scalar;
794         wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar",
795                     *pos, sae->tmp->prime_len);
796         *pos += sae->tmp->prime_len;
797
798         return WLAN_STATUS_SUCCESS;
799 }
800
801
802 static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 *pos,
803                                         const u8 *end)
804 {
805         u8 prime[SAE_MAX_ECC_PRIME_LEN];
806
807         if (pos + 2 * sae->tmp->prime_len > end) {
808                 wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
809                            "commit-element");
810                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
811         }
812
813         if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
814                                  sae->tmp->prime_len) < 0)
815                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
816
817         /* element x and y coordinates < p */
818         if (os_memcmp(pos, prime, sae->tmp->prime_len) >= 0 ||
819             os_memcmp(pos + sae->tmp->prime_len, prime,
820                       sae->tmp->prime_len) >= 0) {
821                 wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer "
822                            "element");
823                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
824         }
825
826         wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)",
827                     pos, sae->tmp->prime_len);
828         wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)",
829                     pos + sae->tmp->prime_len, sae->tmp->prime_len);
830
831         crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0);
832         sae->tmp->peer_commit_element_ecc =
833                 crypto_ec_point_from_bin(sae->tmp->ec, pos);
834         if (sae->tmp->peer_commit_element_ecc == NULL)
835                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
836
837         if (!crypto_ec_point_is_on_curve(sae->tmp->ec,
838                                          sae->tmp->peer_commit_element_ecc)) {
839                 wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve");
840                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
841         }
842
843         return WLAN_STATUS_SUCCESS;
844 }
845
846
847 static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 *pos,
848                                         const u8 *end)
849 {
850         struct crypto_bignum *res;
851
852         if (pos + sae->tmp->prime_len > end) {
853                 wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
854                            "commit-element");
855                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
856         }
857         wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", pos,
858                     sae->tmp->prime_len);
859
860         crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0);
861         sae->tmp->peer_commit_element_ffc =
862                 crypto_bignum_init_set(pos, sae->tmp->prime_len);
863         if (sae->tmp->peer_commit_element_ffc == NULL)
864                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
865         if (crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) ||
866             crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) ||
867             crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc,
868                               sae->tmp->prime) >= 0) {
869                 wpa_printf(MSG_DEBUG, "SAE: Invalid peer element");
870                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
871         }
872
873         /* scalar-op(r, ELEMENT) = 1 modulo p */
874         res = crypto_bignum_init();
875         if (res == NULL ||
876             crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc,
877                                   sae->tmp->order, sae->tmp->prime, res) < 0 ||
878             !crypto_bignum_is_one(res)) {
879                 wpa_printf(MSG_DEBUG, "SAE: Invalid peer element (scalar-op)");
880                 crypto_bignum_deinit(res, 0);
881                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
882         }
883         crypto_bignum_deinit(res, 0);
884
885         return WLAN_STATUS_SUCCESS;
886 }
887
888
889 static u16 sae_parse_commit_element(struct sae_data *sae, const u8 *pos,
890                                     const u8 *end)
891 {
892         if (sae->tmp->dh)
893                 return sae_parse_commit_element_ffc(sae, pos, end);
894         return sae_parse_commit_element_ecc(sae, pos, end);
895 }
896
897
898 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
899                      const u8 **token, size_t *token_len, int *allowed_groups)
900 {
901         const u8 *pos = data, *end = data + len;
902         u16 res;
903
904         /* Check Finite Cyclic Group */
905         if (pos + 2 > end)
906                 return WLAN_STATUS_UNSPECIFIED_FAILURE;
907         res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos));
908         if (res != WLAN_STATUS_SUCCESS)
909                 return res;
910         pos += 2;
911
912         /* Optional Anti-Clogging Token */
913         sae_parse_commit_token(sae, &pos, end, token, token_len);
914
915         /* commit-scalar */
916         res = sae_parse_commit_scalar(sae, &pos, end);
917         if (res != WLAN_STATUS_SUCCESS)
918                 return res;
919
920         /* commit-element */
921         return sae_parse_commit_element(sae, pos, end);
922 }
923
924
925 static void sae_cn_confirm(struct sae_data *sae, const u8 *sc,
926                            const struct crypto_bignum *scalar1,
927                            const u8 *element1, size_t element1_len,
928                            const struct crypto_bignum *scalar2,
929                            const u8 *element2, size_t element2_len,
930                            u8 *confirm)
931 {
932         const u8 *addr[5];
933         size_t len[5];
934         u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN];
935
936         /* Confirm
937          * CN(key, X, Y, Z, ...) =
938          *    HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...)
939          * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT,
940          *              peer-commit-scalar, PEER-COMMIT-ELEMENT)
941          * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar,
942          *               PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT)
943          */
944         addr[0] = sc;
945         len[0] = 2;
946         crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1),
947                              sae->tmp->prime_len);
948         addr[1] = scalar_b1;
949         len[1] = sae->tmp->prime_len;
950         addr[2] = element1;
951         len[2] = element1_len;
952         crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2),
953                              sae->tmp->prime_len);
954         addr[3] = scalar_b2;
955         len[3] = sae->tmp->prime_len;
956         addr[4] = element2;
957         len[4] = element2_len;
958         hmac_sha256_vector(sae->tmp->kck, sizeof(sae->tmp->kck), 5, addr, len,
959                            confirm);
960 }
961
962
963 static void sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
964                                const struct crypto_bignum *scalar1,
965                                const struct crypto_ec_point *element1,
966                                const struct crypto_bignum *scalar2,
967                                const struct crypto_ec_point *element2,
968                                u8 *confirm)
969 {
970         u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN];
971         u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN];
972
973         crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1,
974                                element_b1 + sae->tmp->prime_len);
975         crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2,
976                                element_b2 + sae->tmp->prime_len);
977
978         sae_cn_confirm(sae, sc, scalar1, element_b1, 2 * sae->tmp->prime_len,
979                        scalar2, element_b2, 2 * sae->tmp->prime_len, confirm);
980 }
981
982
983 static void sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
984                                const struct crypto_bignum *scalar1,
985                                const struct crypto_bignum *element1,
986                                const struct crypto_bignum *scalar2,
987                                const struct crypto_bignum *element2,
988                                u8 *confirm)
989 {
990         u8 element_b1[SAE_MAX_PRIME_LEN];
991         u8 element_b2[SAE_MAX_PRIME_LEN];
992
993         crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1),
994                              sae->tmp->prime_len);
995         crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2),
996                              sae->tmp->prime_len);
997
998         sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len,
999                        scalar2, element_b2, sae->tmp->prime_len, confirm);
1000 }
1001
1002
1003 void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
1004 {
1005         const u8 *sc;
1006
1007         if (sae->tmp == NULL)
1008                 return;
1009
1010         /* Send-Confirm */
1011         sc = wpabuf_put(buf, 0);
1012         wpabuf_put_le16(buf, sae->send_confirm);
1013         sae->send_confirm++;
1014
1015         if (sae->tmp->ec)
1016                 sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
1017                                    sae->tmp->own_commit_element_ecc,
1018                                    sae->peer_commit_scalar,
1019                                    sae->tmp->peer_commit_element_ecc,
1020                                    wpabuf_put(buf, SHA256_MAC_LEN));
1021         else
1022                 sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar,
1023                                    sae->tmp->own_commit_element_ffc,
1024                                    sae->peer_commit_scalar,
1025                                    sae->tmp->peer_commit_element_ffc,
1026                                    wpabuf_put(buf, SHA256_MAC_LEN));
1027 }
1028
1029
1030 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
1031 {
1032         u8 verifier[SHA256_MAC_LEN];
1033
1034         if (len < 2 + SHA256_MAC_LEN) {
1035                 wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
1036                 return -1;
1037         }
1038
1039         wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data));
1040
1041         if (sae->tmp == NULL) {
1042                 wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available");
1043                 return -1;
1044         }
1045
1046         if (sae->tmp->ec)
1047                 sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar,
1048                                    sae->tmp->peer_commit_element_ecc,
1049                                    sae->tmp->own_commit_scalar,
1050                                    sae->tmp->own_commit_element_ecc,
1051                                    verifier);
1052         else
1053                 sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar,
1054                                    sae->tmp->peer_commit_element_ffc,
1055                                    sae->tmp->own_commit_scalar,
1056                                    sae->tmp->own_commit_element_ffc,
1057                                    verifier);
1058
1059         if (os_memcmp_const(verifier, data + 2, SHA256_MAC_LEN) != 0) {
1060                 wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
1061                 wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
1062                             data + 2, SHA256_MAC_LEN);
1063                 wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
1064                             verifier, SHA256_MAC_LEN);
1065                 return -1;
1066         }
1067
1068         return 0;
1069 }