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