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