1 /*
2  * Simultaneous authentication of equals
3  * Copyright (c) 2012-2016, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "common.h"
12 #include "common/defs.h"
13 #include "common/wpa_common.h"
14 #include "utils/const_time.h"
15 #include "crypto/crypto.h"
16 #include "crypto/sha256.h"
17 #include "crypto/sha384.h"
18 #include "crypto/sha512.h"
19 #include "crypto/random.h"
20 #include "crypto/dh_groups.h"
21 #include "ieee802_11_defs.h"
22 #include "dragonfly.h"
23 #include "sae.h"
24 
25 
sae_set_group(struct sae_data * sae,int group)26 int sae_set_group(struct sae_data *sae, int group)
27 {
28           struct sae_temporary_data *tmp;
29 
30 #ifdef CONFIG_TESTING_OPTIONS
31           /* Allow all groups for testing purposes in non-production builds. */
32 #else /* CONFIG_TESTING_OPTIONS */
33           if (!dragonfly_suitable_group(group, 0)) {
34                     wpa_printf(MSG_DEBUG, "SAE: Reject unsuitable group %d", group);
35                     return -1;
36           }
37 #endif /* CONFIG_TESTING_OPTIONS */
38 
39           sae_clear_data(sae);
40           tmp = sae->tmp = os_zalloc(sizeof(*tmp));
41           if (tmp == NULL)
42                     return -1;
43 
44           /* First, check if this is an ECC group */
45           tmp->ec = crypto_ec_init(group);
46           if (tmp->ec) {
47                     wpa_printf(MSG_DEBUG, "SAE: Selecting supported ECC group %d",
48                                  group);
49                     sae->group = group;
50                     tmp->prime_len = crypto_ec_prime_len(tmp->ec);
51                     tmp->prime = crypto_ec_get_prime(tmp->ec);
52                     tmp->order_len = crypto_ec_order_len(tmp->ec);
53                     tmp->order = crypto_ec_get_order(tmp->ec);
54                     return 0;
55           }
56 
57           /* Not an ECC group, check FFC */
58           tmp->dh = dh_groups_get(group);
59           if (tmp->dh) {
60                     wpa_printf(MSG_DEBUG, "SAE: Selecting supported FFC group %d",
61                                  group);
62                     sae->group = group;
63                     tmp->prime_len = tmp->dh->prime_len;
64                     if (tmp->prime_len > SAE_MAX_PRIME_LEN) {
65                               sae_clear_data(sae);
66                               return -1;
67                     }
68 
69                     tmp->prime_buf = crypto_bignum_init_set(tmp->dh->prime,
70                                                                       tmp->prime_len);
71                     if (tmp->prime_buf == NULL) {
72                               sae_clear_data(sae);
73                               return -1;
74                     }
75                     tmp->prime = tmp->prime_buf;
76 
77                     tmp->order_len = tmp->dh->order_len;
78                     tmp->order_buf = crypto_bignum_init_set(tmp->dh->order,
79                                                                       tmp->dh->order_len);
80                     if (tmp->order_buf == NULL) {
81                               sae_clear_data(sae);
82                               return -1;
83                     }
84                     tmp->order = tmp->order_buf;
85 
86                     return 0;
87           }
88 
89           /* Unsupported group */
90           wpa_printf(MSG_DEBUG,
91                        "SAE: Group %d not supported by the crypto library", group);
92           return -1;
93 }
94 
95 
sae_clear_temp_data(struct sae_data * sae)96 void sae_clear_temp_data(struct sae_data *sae)
97 {
98           struct sae_temporary_data *tmp;
99           if (sae == NULL || sae->tmp == NULL)
100                     return;
101           tmp = sae->tmp;
102           crypto_ec_deinit(tmp->ec);
103           crypto_bignum_deinit(tmp->prime_buf, 0);
104           crypto_bignum_deinit(tmp->order_buf, 0);
105           crypto_bignum_deinit(tmp->sae_rand, 1);
106           crypto_bignum_deinit(tmp->pwe_ffc, 1);
107           crypto_bignum_deinit(tmp->own_commit_scalar, 0);
108           crypto_bignum_deinit(tmp->own_commit_element_ffc, 0);
109           crypto_bignum_deinit(tmp->peer_commit_element_ffc, 0);
110           crypto_ec_point_deinit(tmp->pwe_ecc, 1);
111           crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0);
112           crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0);
113           wpabuf_free(tmp->anti_clogging_token);
114           wpabuf_free(tmp->own_rejected_groups);
115           wpabuf_free(tmp->peer_rejected_groups);
116           os_free(tmp->pw_id);
117           bin_clear_free(tmp, sizeof(*tmp));
118           sae->tmp = NULL;
119 }
120 
121 
sae_clear_data(struct sae_data * sae)122 void sae_clear_data(struct sae_data *sae)
123 {
124           if (sae == NULL)
125                     return;
126           sae_clear_temp_data(sae);
127           crypto_bignum_deinit(sae->peer_commit_scalar, 0);
128           crypto_bignum_deinit(sae->peer_commit_scalar_accepted, 0);
129           os_memset(sae, 0, sizeof(*sae));
130 }
131 
132 
sae_pwd_seed_key(const u8 * addr1,const u8 * addr2,u8 * key)133 static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key)
134 {
135           wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR
136                        " addr2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2));
137           if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) {
138                     os_memcpy(key, addr1, ETH_ALEN);
139                     os_memcpy(key + ETH_ALEN, addr2, ETH_ALEN);
140           } else {
141                     os_memcpy(key, addr2, ETH_ALEN);
142                     os_memcpy(key + ETH_ALEN, addr1, ETH_ALEN);
143           }
144 }
145 
146 
sae_test_pwd_seed_ecc(struct sae_data * sae,const u8 * pwd_seed,const u8 * prime,const u8 * qr,const u8 * qnr,u8 * pwd_value)147 static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
148                                          const u8 *prime, const u8 *qr, const u8 *qnr,
149                                          u8 *pwd_value)
150 {
151           struct crypto_bignum *y_sqr, *x_cand;
152           int res;
153           size_t bits;
154           int cmp_prime;
155           unsigned int in_range;
156 
157           wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
158 
159           /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
160           bits = crypto_ec_prime_len_bits(sae->tmp->ec);
161           if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
162                                   prime, sae->tmp->prime_len, pwd_value, bits) < 0)
163                     return -1;
164           if (bits % 8)
165                     buf_shift_right(pwd_value, sae->tmp->prime_len, 8 - bits % 8);
166           wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
167                               pwd_value, sae->tmp->prime_len);
168 
169           cmp_prime = const_time_memcmp(pwd_value, prime, sae->tmp->prime_len);
170           /* Create a const_time mask for selection based on prf result
171            * being smaller than prime. */
172           in_range = const_time_fill_msb((unsigned int) cmp_prime);
173           /* The algorithm description would skip the next steps if
174            * cmp_prime >= 0 (return 0 here), but go through them regardless to
175            * minimize externally observable differences in behavior. */
176 
177           x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
178           if (!x_cand)
179                     return -1;
180           y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand);
181           crypto_bignum_deinit(x_cand, 1);
182           if (!y_sqr)
183                     return -1;
184 
185           res = dragonfly_is_quadratic_residue_blind(sae->tmp->ec, qr, qnr,
186                                                                y_sqr);
187           crypto_bignum_deinit(y_sqr, 1);
188           if (res < 0)
189                     return res;
190           return const_time_select_int(in_range, res, 0);
191 }
192 
193 
194 /* Returns -1 on fatal failure, 0 if PWE cannot be derived from the provided
195  * pwd-seed, or 1 if a valid PWE was derived from pwd-seed. */
sae_test_pwd_seed_ffc(struct sae_data * sae,const u8 * pwd_seed,struct crypto_bignum * pwe)196 static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
197                                          struct crypto_bignum *pwe)
198 {
199           u8 pwd_value[SAE_MAX_PRIME_LEN];
200           size_t bits = sae->tmp->prime_len * 8;
201           u8 exp[1];
202           struct crypto_bignum *a, *b = NULL;
203           int res, is_val;
204           u8 pwd_value_valid;
205 
206           wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
207 
208           /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
209           if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
210                                   sae->tmp->dh->prime, sae->tmp->prime_len, pwd_value,
211                                   bits) < 0)
212                     return -1;
213           wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value,
214                               sae->tmp->prime_len);
215 
216           /* Check whether pwd-value < p */
217           res = const_time_memcmp(pwd_value, sae->tmp->dh->prime,
218                                         sae->tmp->prime_len);
219           /* pwd-value >= p is invalid, so res is < 0 for the valid cases and
220            * the negative sign can be used to fill the mask for constant time
221            * selection */
222           pwd_value_valid = const_time_fill_msb(res);
223 
224           /* If pwd-value >= p, force pwd-value to be < p and perform the
225            * calculations anyway to hide timing difference. The derived PWE will
226            * be ignored in that case. */
227           pwd_value[0] = const_time_select_u8(pwd_value_valid, pwd_value[0], 0);
228 
229           /* PWE = pwd-value^((p-1)/r) modulo p */
230 
231           res = -1;
232           a = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
233           if (!a)
234                     goto fail;
235 
236           /* This is an optimization based on the used group that does not depend
237            * on the password in any way, so it is fine to use separate branches
238            * for this step without constant time operations. */
239           if (sae->tmp->dh->safe_prime) {
240                     /*
241                      * r = (p-1)/2 for the group used here, so this becomes:
242                      * PWE = pwd-value^2 modulo p
243                      */
244                     exp[0] = 2;
245                     b = crypto_bignum_init_set(exp, sizeof(exp));
246           } else {
247                     /* Calculate exponent: (p-1)/r */
248                     exp[0] = 1;
249                     b = crypto_bignum_init_set(exp, sizeof(exp));
250                     if (b == NULL ||
251                         crypto_bignum_sub(sae->tmp->prime, b, b) < 0 ||
252                         crypto_bignum_div(b, sae->tmp->order, b) < 0)
253                               goto fail;
254           }
255 
256           if (!b)
257                     goto fail;
258 
259           res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe);
260           if (res < 0)
261                     goto fail;
262 
263           /* There were no fatal errors in calculations, so determine the return
264            * value using constant time operations. We get here for number of
265            * invalid cases which are cleared here after having performed all the
266            * computation. PWE is valid if pwd-value was less than prime and
267            * PWE > 1. Start with pwd-value check first and then use constant time
268            * operations to clear res to 0 if PWE is 0 or 1.
269            */
270           res = const_time_select_u8(pwd_value_valid, 1, 0);
271           is_val = crypto_bignum_is_zero(pwe);
272           res = const_time_select_u8(const_time_is_zero(is_val), res, 0);
273           is_val = crypto_bignum_is_one(pwe);
274           res = const_time_select_u8(const_time_is_zero(is_val), res, 0);
275 
276 fail:
277           crypto_bignum_deinit(a, 1);
278           crypto_bignum_deinit(b, 1);
279           return res;
280 }
281 
282 
sae_derive_pwe_ecc(struct sae_data * sae,const u8 * addr1,const u8 * addr2,const u8 * password,size_t password_len)283 static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
284                                     const u8 *addr2, const u8 *password,
285                                     size_t password_len)
286 {
287           u8 counter, k;
288           u8 addrs[2 * ETH_ALEN];
289           const u8 *addr[2];
290           size_t len[2];
291           u8 *stub_password, *tmp_password;
292           int pwd_seed_odd = 0;
293           u8 prime[SAE_MAX_ECC_PRIME_LEN];
294           size_t prime_len;
295           struct crypto_bignum *x = NULL, *y = NULL, *qr = NULL, *qnr = NULL;
296           u8 x_bin[SAE_MAX_ECC_PRIME_LEN];
297           u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN];
298           u8 qr_bin[SAE_MAX_ECC_PRIME_LEN];
299           u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN];
300           u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN];
301           int res = -1;
302           u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
303                            * mask */
304           unsigned int is_eq;
305 
306           os_memset(x_bin, 0, sizeof(x_bin));
307 
308           stub_password = os_malloc(password_len);
309           tmp_password = os_malloc(password_len);
310           if (!stub_password || !tmp_password ||
311               random_get_bytes(stub_password, password_len) < 0)
312                     goto fail;
313 
314           prime_len = sae->tmp->prime_len;
315           if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
316                                          prime_len) < 0)
317                     goto fail;
318 
319           /*
320            * Create a random quadratic residue (qr) and quadratic non-residue
321            * (qnr) modulo p for blinding purposes during the loop.
322            */
323           if (dragonfly_get_random_qr_qnr(sae->tmp->prime, &qr, &qnr) < 0 ||
324               crypto_bignum_to_bin(qr, qr_bin, sizeof(qr_bin), prime_len) < 0 ||
325               crypto_bignum_to_bin(qnr, qnr_bin, sizeof(qnr_bin), prime_len) < 0)
326                     goto fail;
327 
328           wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
329                                     password, password_len);
330 
331           /*
332            * H(salt, ikm) = HMAC-SHA256(salt, ikm)
333            * base = password
334            * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
335            *              base || counter)
336            */
337           sae_pwd_seed_key(addr1, addr2, addrs);
338 
339           addr[0] = tmp_password;
340           len[0] = password_len;
341           addr[1] = &counter;
342           len[1] = sizeof(counter);
343 
344           /*
345            * Continue for at least k iterations to protect against side-channel
346            * attacks that attempt to determine the number of iterations required
347            * in the loop.
348            */
349           k = dragonfly_min_pwe_loop_iter(sae->group);
350 
351           for (counter = 1; counter <= k || !found; counter++) {
352                     u8 pwd_seed[SHA256_MAC_LEN];
353 
354                     if (counter > 200) {
355                               /* This should not happen in practice */
356                               wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
357                               break;
358                     }
359 
360                     wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter);
361                     const_time_select_bin(found, stub_password, password,
362                                               password_len, tmp_password);
363                     if (hmac_sha256_vector(addrs, sizeof(addrs), 2,
364                                                addr, len, pwd_seed) < 0)
365                               break;
366 
367                     res = sae_test_pwd_seed_ecc(sae, pwd_seed,
368                                                       prime, qr_bin, qnr_bin, x_cand_bin);
369                     const_time_select_bin(found, x_bin, x_cand_bin, prime_len,
370                                               x_bin);
371                     pwd_seed_odd = const_time_select_u8(
372                               found, pwd_seed_odd,
373                               pwd_seed[SHA256_MAC_LEN - 1] & 0x01);
374                     os_memset(pwd_seed, 0, sizeof(pwd_seed));
375                     if (res < 0)
376                               goto fail;
377                     /* Need to minimize differences in handling res == 0 and 1 here
378                      * to avoid differences in timing and instruction cache access,
379                      * so use const_time_select_*() to make local copies of the
380                      * values based on whether this loop iteration was the one that
381                      * found the pwd-seed/x. */
382 
383                     /* found is 0 or 0xff here and res is 0 or 1. Bitwise OR of them
384                      * (with res converted to 0/0xff) handles this in constant time.
385                      */
386                     found |= res * 0xff;
387                     wpa_printf(MSG_DEBUG, "SAE: pwd-seed result %d found=0x%02x",
388                                  res, found);
389           }
390 
391           if (!found) {
392                     wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
393                     res = -1;
394                     goto fail;
395           }
396 
397           x = crypto_bignum_init_set(x_bin, prime_len);
398           if (!x) {
399                     res = -1;
400                     goto fail;
401           }
402 
403           /* y = sqrt(x^3 + ax + b) mod p
404            * if LSB(save) == LSB(y): PWE = (x, y)
405            * else: PWE = (x, p - y)
406            *
407            * Calculate y and the two possible values for PWE and after that,
408            * use constant time selection to copy the correct alternative.
409            */
410           y = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x);
411           if (!y ||
412               dragonfly_sqrt(sae->tmp->ec, y, y) < 0 ||
413               crypto_bignum_to_bin(y, x_y, SAE_MAX_ECC_PRIME_LEN,
414                                          prime_len) < 0 ||
415               crypto_bignum_sub(sae->tmp->prime, y, y) < 0 ||
416               crypto_bignum_to_bin(y, x_y + SAE_MAX_ECC_PRIME_LEN,
417                                          SAE_MAX_ECC_PRIME_LEN, prime_len) < 0) {
418                     wpa_printf(MSG_DEBUG, "SAE: Could not solve y");
419                     goto fail;
420           }
421 
422           is_eq = const_time_eq(pwd_seed_odd, x_y[prime_len - 1] & 0x01);
423           const_time_select_bin(is_eq, x_y, x_y + SAE_MAX_ECC_PRIME_LEN,
424                                     prime_len, x_y + prime_len);
425           os_memcpy(x_y, x_bin, prime_len);
426           wpa_hexdump_key(MSG_DEBUG, "SAE: PWE", x_y, 2 * prime_len);
427           crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1);
428           sae->tmp->pwe_ecc = crypto_ec_point_from_bin(sae->tmp->ec, x_y);
429           if (!sae->tmp->pwe_ecc) {
430                     wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
431                     res = -1;
432           }
433 
434 fail:
435           forced_memzero(x_y, sizeof(x_y));
436           crypto_bignum_deinit(qr, 0);
437           crypto_bignum_deinit(qnr, 0);
438           crypto_bignum_deinit(y, 1);
439           os_free(stub_password);
440           bin_clear_free(tmp_password, password_len);
441           crypto_bignum_deinit(x, 1);
442           os_memset(x_bin, 0, sizeof(x_bin));
443           os_memset(x_cand_bin, 0, sizeof(x_cand_bin));
444 
445           return res;
446 }
447 
448 
sae_modp_group_require_masking(int group)449 static int sae_modp_group_require_masking(int group)
450 {
451           /* Groups for which pwd-value is likely to be >= p frequently */
452           return group == 22 || group == 23 || group == 24;
453 }
454 
455 
sae_derive_pwe_ffc(struct sae_data * sae,const u8 * addr1,const u8 * addr2,const u8 * password,size_t password_len)456 static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
457                                     const u8 *addr2, const u8 *password,
458                                     size_t password_len)
459 {
460           u8 counter, k, sel_counter = 0;
461           u8 addrs[2 * ETH_ALEN];
462           const u8 *addr[2];
463           size_t len[2];
464           u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
465                            * mask */
466           u8 mask;
467           struct crypto_bignum *pwe;
468           size_t prime_len = sae->tmp->prime_len;
469           u8 *pwe_buf;
470 
471           crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
472           sae->tmp->pwe_ffc = NULL;
473 
474           /* Allocate a buffer to maintain selected and candidate PWE for constant
475            * time selection. */
476           pwe_buf = os_zalloc(prime_len * 2);
477           pwe = crypto_bignum_init();
478           if (!pwe_buf || !pwe)
479                     goto fail;
480 
481           wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
482                                     password, password_len);
483 
484           /*
485            * H(salt, ikm) = HMAC-SHA256(salt, ikm)
486            * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
487            *              password || counter)
488            */
489           sae_pwd_seed_key(addr1, addr2, addrs);
490 
491           addr[0] = password;
492           len[0] = password_len;
493           addr[1] = &counter;
494           len[1] = sizeof(counter);
495 
496           k = dragonfly_min_pwe_loop_iter(sae->group);
497 
498           for (counter = 1; counter <= k || !found; counter++) {
499                     u8 pwd_seed[SHA256_MAC_LEN];
500                     int res;
501 
502                     if (counter > 200) {
503                               /* This should not happen in practice */
504                               wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
505                               break;
506                     }
507 
508                     wpa_printf(MSG_DEBUG, "SAE: counter = %02u", counter);
509                     if (hmac_sha256_vector(addrs, sizeof(addrs), 2,
510                                                addr, len, pwd_seed) < 0)
511                               break;
512                     res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
513                     /* res is -1 for fatal failure, 0 if a valid PWE was not found,
514                      * or 1 if a valid PWE was found. */
515                     if (res < 0)
516                               break;
517                     /* Store the candidate PWE into the second half of pwe_buf and
518                      * the selected PWE in the beginning of pwe_buf using constant
519                      * time selection. */
520                     if (crypto_bignum_to_bin(pwe, pwe_buf + prime_len, prime_len,
521                                                    prime_len) < 0)
522                               break;
523                     const_time_select_bin(found, pwe_buf, pwe_buf + prime_len,
524                                               prime_len, pwe_buf);
525                     sel_counter = const_time_select_u8(found, sel_counter, counter);
526                     mask = const_time_eq_u8(res, 1);
527                     found = const_time_select_u8(found, found, mask);
528           }
529 
530           if (!found)
531                     goto fail;
532 
533           wpa_printf(MSG_DEBUG, "SAE: Use PWE from counter = %02u", sel_counter);
534           sae->tmp->pwe_ffc = crypto_bignum_init_set(pwe_buf, prime_len);
535 fail:
536           crypto_bignum_deinit(pwe, 1);
537           bin_clear_free(pwe_buf, prime_len * 2);
538           return sae->tmp->pwe_ffc ? 0 : -1;
539 }
540 
541 
hkdf_extract(size_t hash_len,const u8 * salt,size_t salt_len,size_t num_elem,const u8 * addr[],const size_t len[],u8 * prk)542 static int hkdf_extract(size_t hash_len, const u8 *salt, size_t salt_len,
543                               size_t num_elem, const u8 *addr[], const size_t len[],
544                               u8 *prk)
545 {
546           if (hash_len == 32)
547                     return hmac_sha256_vector(salt, salt_len, num_elem, addr, len,
548                                                     prk);
549 #ifdef CONFIG_SHA384
550           if (hash_len == 48)
551                     return hmac_sha384_vector(salt, salt_len, num_elem, addr, len,
552                                                     prk);
553 #endif /* CONFIG_SHA384 */
554 #ifdef CONFIG_SHA512
555           if (hash_len == 64)
556                     return hmac_sha512_vector(salt, salt_len, num_elem, addr, len,
557                                                     prk);
558 #endif /* CONFIG_SHA512 */
559           return -1;
560 }
561 
562 
hkdf_expand(size_t hash_len,const u8 * prk,size_t prk_len,const char * info,u8 * okm,size_t okm_len)563 static int hkdf_expand(size_t hash_len, const u8 *prk, size_t prk_len,
564                            const char *info, u8 *okm, size_t okm_len)
565 {
566           size_t info_len = os_strlen(info);
567 
568           if (hash_len == 32)
569                     return hmac_sha256_kdf(prk, prk_len, NULL,
570                                                (const u8 *) info, info_len,
571                                                okm, okm_len);
572 #ifdef CONFIG_SHA384
573           if (hash_len == 48)
574                     return hmac_sha384_kdf(prk, prk_len, NULL,
575                                                (const u8 *) info, info_len,
576                                                okm, okm_len);
577 #endif /* CONFIG_SHA384 */
578 #ifdef CONFIG_SHA512
579           if (hash_len == 64)
580                     return hmac_sha512_kdf(prk, prk_len, NULL,
581                                                (const u8 *) info, info_len,
582                                                okm, okm_len);
583 #endif /* CONFIG_SHA512 */
584           return -1;
585 }
586 
587 
sswu_curve_param(int group,int * z)588 static int sswu_curve_param(int group, int *z)
589 {
590           switch (group) {
591           case 19:
592                     *z = -10;
593                     return 0;
594           case 20:
595                     *z = -12;
596                     return 0;
597           case 21:
598                     *z = -4;
599                     return 0;
600           case 25:
601           case 29:
602                     *z = -5;
603                     return 0;
604           case 26:
605                     *z = 31;
606                     return 0;
607           case 28:
608                     *z = -2;
609                     return 0;
610           case 30:
611                     *z = 7;
612                     return 0;
613           default:
614                     return -1;
615           }
616 }
617 
618 
debug_print_bignum(const char * title,const struct crypto_bignum * a,size_t prime_len)619 static void debug_print_bignum(const char *title, const struct crypto_bignum *a,
620                                      size_t prime_len)
621 {
622           u8 *bin;
623 
624           bin = os_malloc(prime_len);
625           if (bin && crypto_bignum_to_bin(a, bin, prime_len, prime_len) >= 0)
626                     wpa_hexdump_key(MSG_DEBUG, title, bin, prime_len);
627           else
628                     wpa_printf(MSG_DEBUG, "Could not print bignum (%s)", title);
629           bin_clear_free(bin, prime_len);
630 }
631 
632 
sswu(struct crypto_ec * ec,int group,const struct crypto_bignum * u)633 static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group,
634                                              const struct crypto_bignum *u)
635 {
636           int z_int;
637           const struct crypto_bignum *a, *b, *prime;
638           struct crypto_bignum *u2, *t1, *t2, *z, *t, *zero, *one, *two, *three,
639                     *x1a, *x1b, *y = NULL;
640           struct crypto_bignum *x1 = NULL, *x2, *gx1, *gx2, *v = NULL;
641           unsigned int m_is_zero, is_qr, is_eq;
642           size_t prime_len;
643           u8 bin[SAE_MAX_ECC_PRIME_LEN];
644           u8 bin1[SAE_MAX_ECC_PRIME_LEN];
645           u8 bin2[SAE_MAX_ECC_PRIME_LEN];
646           u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN];
647           struct crypto_ec_point *p = NULL;
648 
649           if (sswu_curve_param(group, &z_int) < 0)
650                     return NULL;
651 
652           prime = crypto_ec_get_prime(ec);
653           prime_len = crypto_ec_prime_len(ec);
654           a = crypto_ec_get_a(ec);
655           b = crypto_ec_get_b(ec);
656 
657           u2 = crypto_bignum_init();
658           t1 = crypto_bignum_init();
659           t2 = crypto_bignum_init();
660           z = crypto_bignum_init_uint(abs(z_int));
661           t = crypto_bignum_init();
662           zero = crypto_bignum_init_uint(0);
663           one = crypto_bignum_init_uint(1);
664           two = crypto_bignum_init_uint(2);
665           three = crypto_bignum_init_uint(3);
666           x1a = crypto_bignum_init();
667           x1b = crypto_bignum_init();
668           x2 = crypto_bignum_init();
669           gx1 = crypto_bignum_init();
670           gx2 = crypto_bignum_init();
671           if (!u2 || !t1 || !t2 || !z || !t || !zero || !one || !two || !three ||
672               !x1a || !x1b || !x2 || !gx1 || !gx2)
673                     goto fail;
674 
675           if (z_int < 0 && crypto_bignum_sub(prime, z, z) < 0)
676                     goto fail;
677 
678           /* m = z^2 * u^4 + z * u^2 */
679           /* --> tmp = z * u^2, m = tmp^2 + tmp */
680 
681           /* u2 = u^2
682            * t1 = z * u2
683            * t2 = t1^2
684            * m = t1 = t1 + t2 */
685           if (crypto_bignum_sqrmod(u, prime, u2) < 0 ||
686               crypto_bignum_mulmod(z, u2, prime, t1) < 0 ||
687               crypto_bignum_sqrmod(t1, prime, t2) < 0 ||
688               crypto_bignum_addmod(t1, t2, prime, t1) < 0)
689                     goto fail;
690           debug_print_bignum("SSWU: m", t1, prime_len);
691 
692           /* l = CEQ(m, 0)
693            * t = CSEL(l, 0, inverse(m); where inverse(x) is calculated as
694            * x^(p-2) modulo p which will handle m == 0 case correctly */
695           /* TODO: Make sure crypto_bignum_is_zero() is constant time */
696           m_is_zero = const_time_eq(crypto_bignum_is_zero(t1), 1);
697           /* t = m^(p-2) modulo p */
698           if (crypto_bignum_sub(prime, two, t2) < 0 ||
699               crypto_bignum_exptmod(t1, t2, prime, t) < 0)
700                     goto fail;
701           debug_print_bignum("SSWU: t", t, prime_len);
702 
703           /* b / (z * a) */
704           if (crypto_bignum_mulmod(z, a, prime, t1) < 0 ||
705               crypto_bignum_inverse(t1, prime, t1) < 0 ||
706               crypto_bignum_mulmod(b, t1, prime, x1a) < 0)
707                     goto fail;
708           debug_print_bignum("SSWU: x1a = b / (z * a)", x1a, prime_len);
709 
710           /* (-b/a) * (1 + t) */
711           if (crypto_bignum_sub(prime, b, t1) < 0 ||
712               crypto_bignum_inverse(a, prime, t2) < 0 ||
713               crypto_bignum_mulmod(t1, t2, prime, t1) < 0 ||
714               crypto_bignum_addmod(one, t, prime, t2) < 0 ||
715               crypto_bignum_mulmod(t1, t2, prime, x1b) < 0)
716                     goto fail;
717           debug_print_bignum("SSWU: x1b = (-b/a) * (1 + t)", x1b, prime_len);
718 
719           /* x1 = CSEL(CEQ(m, 0), x1a, x1b) */
720           if (crypto_bignum_to_bin(x1a, bin1, sizeof(bin1), prime_len) < 0 ||
721               crypto_bignum_to_bin(x1b, bin2, sizeof(bin2), prime_len) < 0)
722                     goto fail;
723           const_time_select_bin(m_is_zero, bin1, bin2, prime_len, bin);
724           x1 = crypto_bignum_init_set(bin, prime_len);
725           if (!x1)
726                     goto fail;
727           debug_print_bignum("SSWU: x1 = CSEL(l, x1a, x1b)", x1, prime_len);
728 
729           /* gx1 = x1^3 + a * x1 + b */
730           if (crypto_bignum_exptmod(x1, three, prime, t1) < 0 ||
731               crypto_bignum_mulmod(a, x1, prime, t2) < 0 ||
732               crypto_bignum_addmod(t1, t2, prime, t1) < 0 ||
733               crypto_bignum_addmod(t1, b, prime, gx1) < 0)
734                     goto fail;
735           debug_print_bignum("SSWU: gx1 = x1^3 + a * x1 + b", gx1, prime_len);
736 
737           /* x2 = z * u^2 * x1 */
738           if (crypto_bignum_mulmod(z, u2, prime, t1) < 0 ||
739               crypto_bignum_mulmod(t1, x1, prime, x2) < 0)
740                     goto fail;
741           debug_print_bignum("SSWU: x2 = z * u^2 * x1", x2, prime_len);
742 
743           /* gx2 = x2^3 + a * x2 + b */
744           if (crypto_bignum_exptmod(x2, three, prime, t1) < 0 ||
745               crypto_bignum_mulmod(a, x2, prime, t2) < 0 ||
746               crypto_bignum_addmod(t1, t2, prime, t1) < 0 ||
747               crypto_bignum_addmod(t1, b, prime, gx2) < 0)
748                     goto fail;
749           debug_print_bignum("SSWU: gx2 = x2^3 + a * x2 + b", gx2, prime_len);
750 
751           /* l = gx1 is a quadratic residue modulo p
752            * --> gx1^((p-1)/2) modulo p is zero or one */
753           if (crypto_bignum_sub(prime, one, t1) < 0 ||
754               crypto_bignum_rshift(t1, 1, t1) < 0 ||
755               crypto_bignum_exptmod(gx1, t1, prime, t1) < 0)
756                     goto fail;
757           debug_print_bignum("SSWU: gx1^((p-1)/2) modulo p", t1, prime_len);
758           is_qr = const_time_eq(crypto_bignum_is_zero(t1) |
759                                     crypto_bignum_is_one(t1), 1);
760 
761           /* v = CSEL(l, gx1, gx2) */
762           if (crypto_bignum_to_bin(gx1, bin1, sizeof(bin1), prime_len) < 0 ||
763               crypto_bignum_to_bin(gx2, bin2, sizeof(bin2), prime_len) < 0)
764                     goto fail;
765           const_time_select_bin(is_qr, bin1, bin2, prime_len, bin);
766           v = crypto_bignum_init_set(bin, prime_len);
767           if (!v)
768                     goto fail;
769           debug_print_bignum("SSWU: v = CSEL(l, gx1, gx2)", v, prime_len);
770 
771           /* x = CSEL(l, x1, x2) */
772           if (crypto_bignum_to_bin(x1, bin1, sizeof(bin1), prime_len) < 0 ||
773               crypto_bignum_to_bin(x2, bin2, sizeof(bin2), prime_len) < 0)
774                     goto fail;
775           const_time_select_bin(is_qr, bin1, bin2, prime_len, x_y);
776           wpa_hexdump_key(MSG_DEBUG, "SSWU: x = CSEL(l, x1, x2)", x_y, prime_len);
777 
778           /* y = sqrt(v) */
779           y = crypto_bignum_init();
780           if (!y || dragonfly_sqrt(ec, v, y) < 0)
781                     goto fail;
782           debug_print_bignum("SSWU: y = sqrt(v)", y, prime_len);
783 
784           /* l = CEQ(LSB(u), LSB(y)) */
785           if (crypto_bignum_to_bin(u, bin1, sizeof(bin1), prime_len) < 0 ||
786               crypto_bignum_to_bin(y, bin2, sizeof(bin2), prime_len) < 0)
787                     goto fail;
788           is_eq = const_time_eq(bin1[prime_len - 1] & 0x01,
789                                     bin2[prime_len - 1] & 0x01);
790 
791           /* P = CSEL(l, (x,y), (x, p-y)) */
792           if (crypto_bignum_sub(prime, y, t1) < 0)
793                     goto fail;
794           debug_print_bignum("SSWU: p - y", t1, prime_len);
795           if (crypto_bignum_to_bin(y, bin1, sizeof(bin1), prime_len) < 0 ||
796               crypto_bignum_to_bin(t1, bin2, sizeof(bin2), prime_len) < 0)
797                     goto fail;
798           const_time_select_bin(is_eq, bin1, bin2, prime_len, &x_y[prime_len]);
799 
800           /* output P */
801           wpa_hexdump_key(MSG_DEBUG, "SSWU: P.x", x_y, prime_len);
802           wpa_hexdump_key(MSG_DEBUG, "SSWU: P.y", &x_y[prime_len], prime_len);
803           p = crypto_ec_point_from_bin(ec, x_y);
804 
805 fail:
806           crypto_bignum_deinit(u2, 1);
807           crypto_bignum_deinit(t1, 1);
808           crypto_bignum_deinit(t2, 1);
809           crypto_bignum_deinit(z, 0);
810           crypto_bignum_deinit(t, 1);
811           crypto_bignum_deinit(x1a, 1);
812           crypto_bignum_deinit(x1b, 1);
813           crypto_bignum_deinit(x1, 1);
814           crypto_bignum_deinit(x2, 1);
815           crypto_bignum_deinit(gx1, 1);
816           crypto_bignum_deinit(gx2, 1);
817           crypto_bignum_deinit(y, 1);
818           crypto_bignum_deinit(v, 1);
819           crypto_bignum_deinit(zero, 0);
820           crypto_bignum_deinit(one, 0);
821           crypto_bignum_deinit(two, 0);
822           crypto_bignum_deinit(three, 0);
823           forced_memzero(bin, sizeof(bin));
824           forced_memzero(bin1, sizeof(bin1));
825           forced_memzero(bin2, sizeof(bin2));
826           forced_memzero(x_y, sizeof(x_y));
827           return p;
828 }
829 
830 
sae_pwd_seed(size_t hash_len,const u8 * ssid,size_t ssid_len,const u8 * password,size_t password_len,const char * identifier,u8 * pwd_seed)831 static int sae_pwd_seed(size_t hash_len, const u8 *ssid, size_t ssid_len,
832                               const u8 *password, size_t password_len,
833                               const char *identifier, u8 *pwd_seed)
834 {
835           const u8 *addr[2];
836           size_t len[2];
837           size_t num_elem;
838 
839           /* pwd-seed = HKDF-Extract(ssid, password [ || identifier ]) */
840           addr[0] = password;
841           len[0] = password_len;
842           num_elem = 1;
843           wpa_hexdump_ascii(MSG_DEBUG, "SAE: SSID", ssid, ssid_len);
844           wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
845                                     password, password_len);
846           if (identifier) {
847                     wpa_printf(MSG_DEBUG, "SAE: password identifier: %s",
848                                  identifier);
849                     addr[num_elem] = (const u8 *) identifier;
850                     len[num_elem] = os_strlen(identifier);
851                     num_elem++;
852           }
853           if (hkdf_extract(hash_len, ssid, ssid_len, num_elem, addr, len,
854                                pwd_seed) < 0)
855                     return -1;
856           wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, hash_len);
857           return 0;
858 }
859 
860 
sae_ecc_prime_len_2_hash_len(size_t prime_len)861 size_t sae_ecc_prime_len_2_hash_len(size_t prime_len)
862 {
863           if (prime_len <= 256 / 8)
864                     return 32;
865           if (prime_len <= 384 / 8)
866                     return 48;
867           return 64;
868 }
869 
870 
871 static struct crypto_ec_point *
sae_derive_pt_ecc(struct crypto_ec * ec,int group,const u8 * ssid,size_t ssid_len,const u8 * password,size_t password_len,const char * identifier)872 sae_derive_pt_ecc(struct crypto_ec *ec, int group,
873                       const u8 *ssid, size_t ssid_len,
874                       const u8 *password, size_t password_len,
875                       const char *identifier)
876 {
877           u8 pwd_seed[64];
878           u8 pwd_value[SAE_MAX_ECC_PRIME_LEN * 2];
879           size_t pwd_value_len, hash_len, prime_len;
880           const struct crypto_bignum *prime;
881           struct crypto_bignum *bn = NULL;
882           struct crypto_ec_point *p1 = NULL, *p2 = NULL, *pt = NULL;
883 
884           prime = crypto_ec_get_prime(ec);
885           prime_len = crypto_ec_prime_len(ec);
886           if (prime_len > SAE_MAX_ECC_PRIME_LEN)
887                     goto fail;
888           hash_len = sae_ecc_prime_len_2_hash_len(prime_len);
889 
890           /* len = olen(p) + ceil(olen(p)/2) */
891           pwd_value_len = prime_len + (prime_len + 1) / 2;
892 
893           if (sae_pwd_seed(hash_len, ssid, ssid_len, password, password_len,
894                                identifier, pwd_seed) < 0)
895                     goto fail;
896 
897           /* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element u1 P1", len)
898            */
899           if (hkdf_expand(hash_len, pwd_seed, hash_len,
900                               "SAE Hash to Element u1 P1", pwd_value, pwd_value_len) <
901               0)
902                     goto fail;
903           wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value (u1 P1)",
904                               pwd_value, pwd_value_len);
905 
906           /* u1 = pwd-value modulo p */
907           bn = crypto_bignum_init_set(pwd_value, pwd_value_len);
908           if (!bn || crypto_bignum_mod(bn, prime, bn) < 0 ||
909               crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value),
910                                          prime_len) < 0)
911                     goto fail;
912           wpa_hexdump_key(MSG_DEBUG, "SAE: u1", pwd_value, prime_len);
913 
914           /* P1 = SSWU(u1) */
915           p1 = sswu(ec, group, bn);
916           if (!p1)
917                     goto fail;
918 
919           /* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element u2 P2", len)
920            */
921           if (hkdf_expand(hash_len, pwd_seed, hash_len,
922                               "SAE Hash to Element u2 P2", pwd_value,
923                               pwd_value_len) < 0)
924                     goto fail;
925           wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value (u2 P2)",
926                               pwd_value, pwd_value_len);
927 
928           /* u2 = pwd-value modulo p */
929           crypto_bignum_deinit(bn, 1);
930           bn = crypto_bignum_init_set(pwd_value, pwd_value_len);
931           if (!bn || crypto_bignum_mod(bn, prime, bn) < 0 ||
932               crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value),
933                                          prime_len) < 0)
934                     goto fail;
935           wpa_hexdump_key(MSG_DEBUG, "SAE: u2", pwd_value, prime_len);
936 
937           /* P2 = SSWU(u2) */
938           p2 = sswu(ec, group, bn);
939           if (!p2)
940                     goto fail;
941 
942           /* PT = elem-op(P1, P2) */
943           pt = crypto_ec_point_init(ec);
944           if (!pt)
945                     goto fail;
946           if (crypto_ec_point_add(ec, p1, p2, pt) < 0) {
947                     crypto_ec_point_deinit(pt, 1);
948                     pt = NULL;
949           }
950 
951 fail:
952           forced_memzero(pwd_seed, sizeof(pwd_seed));
953           forced_memzero(pwd_value, sizeof(pwd_value));
954           crypto_bignum_deinit(bn, 1);
955           crypto_ec_point_deinit(p1, 1);
956           crypto_ec_point_deinit(p2, 1);
957           return pt;
958 }
959 
960 
sae_ffc_prime_len_2_hash_len(size_t prime_len)961 size_t sae_ffc_prime_len_2_hash_len(size_t prime_len)
962 {
963           if (prime_len <= 2048 / 8)
964                     return 32;
965           if (prime_len <= 3072 / 8)
966                     return 48;
967           return 64;
968 }
969 
970 
971 static struct crypto_bignum *
sae_derive_pt_ffc(const struct dh_group * dh,int group,const u8 * ssid,size_t ssid_len,const u8 * password,size_t password_len,const char * identifier)972 sae_derive_pt_ffc(const struct dh_group *dh, int group,
973                       const u8 *ssid, size_t ssid_len,
974                       const u8 *password, size_t password_len,
975                       const char *identifier)
976 {
977           size_t hash_len, prime_len, pwd_value_len;
978           struct crypto_bignum *prime, *order;
979           struct crypto_bignum *one = NULL, *two = NULL, *bn = NULL, *tmp = NULL,
980                     *pt = NULL;
981           u8 pwd_seed[64];
982           u8 pwd_value[SAE_MAX_PRIME_LEN + SAE_MAX_PRIME_LEN / 2];
983 
984           prime = crypto_bignum_init_set(dh->prime, dh->prime_len);
985           order = crypto_bignum_init_set(dh->order, dh->order_len);
986           if (!prime || !order)
987                     goto fail;
988           prime_len = dh->prime_len;
989           if (prime_len > SAE_MAX_PRIME_LEN)
990                     goto fail;
991           hash_len = sae_ffc_prime_len_2_hash_len(prime_len);
992 
993           /* len = olen(p) + ceil(olen(p)/2) */
994           pwd_value_len = prime_len + (prime_len + 1) / 2;
995           if (pwd_value_len > sizeof(pwd_value))
996                     goto fail;
997 
998           if (sae_pwd_seed(hash_len, ssid, ssid_len, password, password_len,
999                                identifier, pwd_seed) < 0)
1000                     goto fail;
1001 
1002           /* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element", len) */
1003           if (hkdf_expand(hash_len, pwd_seed, hash_len,
1004                               "SAE Hash to Element", pwd_value, pwd_value_len) < 0)
1005                     goto fail;
1006           wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
1007                               pwd_value, pwd_value_len);
1008 
1009           /* pwd-value = (pwd-value modulo (p-2)) + 2 */
1010           bn = crypto_bignum_init_set(pwd_value, pwd_value_len);
1011           one = crypto_bignum_init_uint(1);
1012           two = crypto_bignum_init_uint(2);
1013           tmp = crypto_bignum_init();
1014           if (!bn || !one || !two || !tmp ||
1015               crypto_bignum_sub(prime, two, tmp) < 0 ||
1016               crypto_bignum_mod(bn, tmp, bn) < 0 ||
1017               crypto_bignum_add(bn, two, bn) < 0 ||
1018               crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value),
1019                                          prime_len) < 0)
1020                     goto fail;
1021           wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value(reduced)",
1022                               pwd_value, prime_len);
1023 
1024           /* PT = pwd-value^((p-1)/q) modulo p */
1025           pt = crypto_bignum_init();
1026           if (!pt ||
1027               crypto_bignum_sub(prime, one, tmp) < 0 ||
1028               crypto_bignum_div(tmp, order, tmp) < 0 ||
1029               crypto_bignum_exptmod(bn, tmp, prime, pt) < 0) {
1030                     crypto_bignum_deinit(pt, 1);
1031                     pt = NULL;
1032                     goto fail;
1033           }
1034           debug_print_bignum("SAE: PT", pt, prime_len);
1035 
1036 fail:
1037           forced_memzero(pwd_seed, sizeof(pwd_seed));
1038           forced_memzero(pwd_value, sizeof(pwd_value));
1039           crypto_bignum_deinit(bn, 1);
1040           crypto_bignum_deinit(tmp, 1);
1041           crypto_bignum_deinit(one, 0);
1042           crypto_bignum_deinit(two, 0);
1043           crypto_bignum_deinit(prime, 0);
1044           crypto_bignum_deinit(order, 0);
1045           return pt;
1046 }
1047 
1048 
1049 static struct sae_pt *
sae_derive_pt_group(int group,const u8 * ssid,size_t ssid_len,const u8 * password,size_t password_len,const char * identifier)1050 sae_derive_pt_group(int group, const u8 *ssid, size_t ssid_len,
1051                         const u8 *password, size_t password_len,
1052                         const char *identifier)
1053 {
1054           struct sae_pt *pt;
1055 
1056           wpa_printf(MSG_DEBUG, "SAE: Derive PT - group %d", group);
1057 
1058           if (ssid_len > 32)
1059                     return NULL;
1060 
1061           pt = os_zalloc(sizeof(*pt));
1062           if (!pt)
1063                     return NULL;
1064 
1065 #ifdef CONFIG_SAE_PK
1066           os_memcpy(pt->ssid, ssid, ssid_len);
1067           pt->ssid_len = ssid_len;
1068 #endif /* CONFIG_SAE_PK */
1069           pt->group = group;
1070           pt->ec = crypto_ec_init(group);
1071           if (pt->ec) {
1072                     pt->ecc_pt = sae_derive_pt_ecc(pt->ec, group, ssid, ssid_len,
1073                                                          password, password_len,
1074                                                          identifier);
1075                     if (!pt->ecc_pt) {
1076                               wpa_printf(MSG_DEBUG, "SAE: Failed to derive PT");
1077                               goto fail;
1078                     }
1079 
1080                     return pt;
1081           }
1082 
1083           pt->dh = dh_groups_get(group);
1084           if (!pt->dh) {
1085                     wpa_printf(MSG_DEBUG, "SAE: Unsupported group %d", group);
1086                     goto fail;
1087           }
1088 
1089           pt->ffc_pt = sae_derive_pt_ffc(pt->dh, group, ssid, ssid_len,
1090                                                password, password_len, identifier);
1091           if (!pt->ffc_pt) {
1092                     wpa_printf(MSG_DEBUG, "SAE: Failed to derive PT");
1093                     goto fail;
1094           }
1095 
1096           return pt;
1097 fail:
1098           sae_deinit_pt(pt);
1099           return NULL;
1100 }
1101 
1102 
sae_derive_pt(int * groups,const u8 * ssid,size_t ssid_len,const u8 * password,size_t password_len,const char * identifier)1103 struct sae_pt * sae_derive_pt(int *groups, const u8 *ssid, size_t ssid_len,
1104                                     const u8 *password, size_t password_len,
1105                                     const char *identifier)
1106 {
1107           struct sae_pt *pt = NULL, *last = NULL, *tmp;
1108           int default_groups[] = { 19, 0 };
1109           int i;
1110 
1111           if (!groups)
1112                     groups = default_groups;
1113           for (i = 0; groups[i] > 0; i++) {
1114                     tmp = sae_derive_pt_group(groups[i], ssid, ssid_len, password,
1115                                                     password_len, identifier);
1116                     if (!tmp)
1117                               continue;
1118 
1119                     if (last)
1120                               last->next = tmp;
1121                     else
1122                               pt = tmp;
1123                     last = tmp;
1124           }
1125 
1126           return pt;
1127 }
1128 
1129 
sae_max_min_addr(const u8 * addr[],size_t len[],const u8 * addr1,const u8 * addr2)1130 static void sae_max_min_addr(const u8 *addr[], size_t len[],
1131                                    const u8 *addr1, const u8 *addr2)
1132 {
1133           len[0] = ETH_ALEN;
1134           len[1] = ETH_ALEN;
1135           if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) {
1136                     addr[0] = addr1;
1137                     addr[1] = addr2;
1138           } else {
1139                     addr[0] = addr2;
1140                     addr[1] = addr1;
1141           }
1142 }
1143 
1144 
1145 struct crypto_ec_point *
sae_derive_pwe_from_pt_ecc(const struct sae_pt * pt,const u8 * addr1,const u8 * addr2)1146 sae_derive_pwe_from_pt_ecc(const struct sae_pt *pt,
1147                                  const u8 *addr1, const u8 *addr2)
1148 {
1149           u8 bin[SAE_MAX_ECC_PRIME_LEN * 2];
1150           size_t prime_len;
1151           const u8 *addr[2];
1152           size_t len[2];
1153           u8 salt[64], hash[64];
1154           size_t hash_len;
1155           const struct crypto_bignum *order;
1156           struct crypto_bignum *tmp = NULL, *val = NULL, *one = NULL;
1157           struct crypto_ec_point *pwe = NULL;
1158 
1159           wpa_printf(MSG_DEBUG, "SAE: Derive PWE from PT");
1160           prime_len = crypto_ec_prime_len(pt->ec);
1161           if (crypto_ec_point_to_bin(pt->ec, pt->ecc_pt,
1162                                            bin, bin + prime_len) < 0)
1163                     return NULL;
1164           wpa_hexdump_key(MSG_DEBUG, "SAE: PT.x", bin, prime_len);
1165           wpa_hexdump_key(MSG_DEBUG, "SAE: PT.y", bin + prime_len, prime_len);
1166 
1167           sae_max_min_addr(addr, len, addr1, addr2);
1168 
1169           /* val = H(0^n,
1170            *         MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC)) */
1171           wpa_printf(MSG_DEBUG, "SAE: val = H(0^n, MAX(addrs) || MIN(addrs))");
1172           hash_len = sae_ecc_prime_len_2_hash_len(prime_len);
1173           os_memset(salt, 0, hash_len);
1174           if (hkdf_extract(hash_len, salt, hash_len, 2, addr, len, hash) < 0)
1175                     goto fail;
1176           wpa_hexdump(MSG_DEBUG, "SAE: val", hash, hash_len);
1177 
1178           /* val = val modulo (q - 1) + 1 */
1179           order = crypto_ec_get_order(pt->ec);
1180           tmp = crypto_bignum_init();
1181           val = crypto_bignum_init_set(hash, hash_len);
1182           one = crypto_bignum_init_uint(1);
1183           if (!tmp || !val || !one ||
1184               crypto_bignum_sub(order, one, tmp) < 0 ||
1185               crypto_bignum_mod(val, tmp, val) < 0 ||
1186               crypto_bignum_add(val, one, val) < 0)
1187                     goto fail;
1188           debug_print_bignum("SAE: val(reduced to 1..q-1)", val, prime_len);
1189 
1190           /* PWE = scalar-op(val, PT) */
1191           pwe = crypto_ec_point_init(pt->ec);
1192           if (!pwe ||
1193               crypto_ec_point_mul(pt->ec, pt->ecc_pt, val, pwe) < 0 ||
1194               crypto_ec_point_to_bin(pt->ec, pwe, bin, bin + prime_len) < 0) {
1195                     crypto_ec_point_deinit(pwe, 1);
1196                     pwe = NULL;
1197                     goto fail;
1198           }
1199           wpa_hexdump_key(MSG_DEBUG, "SAE: PWE.x", bin, prime_len);
1200           wpa_hexdump_key(MSG_DEBUG, "SAE: PWE.y", bin + prime_len, prime_len);
1201 
1202 fail:
1203           crypto_bignum_deinit(tmp, 1);
1204           crypto_bignum_deinit(val, 1);
1205           crypto_bignum_deinit(one, 0);
1206           return pwe;
1207 }
1208 
1209 
1210 struct crypto_bignum *
sae_derive_pwe_from_pt_ffc(const struct sae_pt * pt,const u8 * addr1,const u8 * addr2)1211 sae_derive_pwe_from_pt_ffc(const struct sae_pt *pt,
1212                                  const u8 *addr1, const u8 *addr2)
1213 {
1214           size_t prime_len;
1215           const u8 *addr[2];
1216           size_t len[2];
1217           u8 salt[64], hash[64];
1218           size_t hash_len;
1219           struct crypto_bignum *tmp = NULL, *val = NULL, *one = NULL;
1220           struct crypto_bignum *pwe = NULL, *order = NULL, *prime = NULL;
1221 
1222           wpa_printf(MSG_DEBUG, "SAE: Derive PWE from PT");
1223           prime = crypto_bignum_init_set(pt->dh->prime, pt->dh->prime_len);
1224           order = crypto_bignum_init_set(pt->dh->order, pt->dh->order_len);
1225           if (!prime || !order)
1226                     goto fail;
1227           prime_len = pt->dh->prime_len;
1228 
1229           sae_max_min_addr(addr, len, addr1, addr2);
1230 
1231           /* val = H(0^n,
1232            *         MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC)) */
1233           wpa_printf(MSG_DEBUG, "SAE: val = H(0^n, MAX(addrs) || MIN(addrs))");
1234           hash_len = sae_ffc_prime_len_2_hash_len(prime_len);
1235           os_memset(salt, 0, hash_len);
1236           if (hkdf_extract(hash_len, salt, hash_len, 2, addr, len, hash) < 0)
1237                     goto fail;
1238           wpa_hexdump(MSG_DEBUG, "SAE: val", hash, hash_len);
1239 
1240           /* val = val modulo (q - 1) + 1 */
1241           tmp = crypto_bignum_init();
1242           val = crypto_bignum_init_set(hash, hash_len);
1243           one = crypto_bignum_init_uint(1);
1244           if (!tmp || !val || !one ||
1245               crypto_bignum_sub(order, one, tmp) < 0 ||
1246               crypto_bignum_mod(val, tmp, val) < 0 ||
1247               crypto_bignum_add(val, one, val) < 0)
1248                     goto fail;
1249           debug_print_bignum("SAE: val(reduced to 1..q-1)", val, prime_len);
1250 
1251           /* PWE = scalar-op(val, PT) */
1252           pwe = crypto_bignum_init();
1253           if (!pwe || crypto_bignum_exptmod(pt->ffc_pt, val, prime, pwe) < 0) {
1254                     crypto_bignum_deinit(pwe, 1);
1255                     pwe = NULL;
1256                     goto fail;
1257           }
1258           debug_print_bignum("SAE: PWE", pwe, prime_len);
1259 
1260 fail:
1261           crypto_bignum_deinit(tmp, 1);
1262           crypto_bignum_deinit(val, 1);
1263           crypto_bignum_deinit(one, 0);
1264           crypto_bignum_deinit(prime, 0);
1265           crypto_bignum_deinit(order, 0);
1266           return pwe;
1267 }
1268 
1269 
sae_deinit_pt(struct sae_pt * pt)1270 void sae_deinit_pt(struct sae_pt *pt)
1271 {
1272           struct sae_pt *prev;
1273 
1274           while (pt) {
1275                     crypto_ec_point_deinit(pt->ecc_pt, 1);
1276                     crypto_bignum_deinit(pt->ffc_pt, 1);
1277                     crypto_ec_deinit(pt->ec);
1278                     prev = pt;
1279                     pt = pt->next;
1280                     os_free(prev);
1281           }
1282 }
1283 
1284 
sae_derive_commit_element_ecc(struct sae_data * sae,struct crypto_bignum * mask)1285 static int sae_derive_commit_element_ecc(struct sae_data *sae,
1286                                                    struct crypto_bignum *mask)
1287 {
1288           /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
1289           if (!sae->tmp->own_commit_element_ecc) {
1290                     sae->tmp->own_commit_element_ecc =
1291                               crypto_ec_point_init(sae->tmp->ec);
1292                     if (!sae->tmp->own_commit_element_ecc)
1293                               return -1;
1294           }
1295 
1296           if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, mask,
1297                                         sae->tmp->own_commit_element_ecc) < 0 ||
1298               crypto_ec_point_invert(sae->tmp->ec,
1299                                            sae->tmp->own_commit_element_ecc) < 0) {
1300                     wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
1301                     return -1;
1302           }
1303 
1304           return 0;
1305 }
1306 
1307 
sae_derive_commit_element_ffc(struct sae_data * sae,struct crypto_bignum * mask)1308 static int sae_derive_commit_element_ffc(struct sae_data *sae,
1309                                                    struct crypto_bignum *mask)
1310 {
1311           /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
1312           if (!sae->tmp->own_commit_element_ffc) {
1313                     sae->tmp->own_commit_element_ffc = crypto_bignum_init();
1314                     if (!sae->tmp->own_commit_element_ffc)
1315                               return -1;
1316           }
1317 
1318           if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, mask, sae->tmp->prime,
1319                                           sae->tmp->own_commit_element_ffc) < 0 ||
1320               crypto_bignum_inverse(sae->tmp->own_commit_element_ffc,
1321                                           sae->tmp->prime,
1322                                           sae->tmp->own_commit_element_ffc) < 0) {
1323                     wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
1324                     return -1;
1325           }
1326 
1327           return 0;
1328 }
1329 
1330 
sae_derive_commit(struct sae_data * sae)1331 static int sae_derive_commit(struct sae_data *sae)
1332 {
1333           struct crypto_bignum *mask;
1334           int ret;
1335 
1336           mask = crypto_bignum_init();
1337           if (!sae->tmp->sae_rand)
1338                     sae->tmp->sae_rand = crypto_bignum_init();
1339           if (!sae->tmp->own_commit_scalar)
1340                     sae->tmp->own_commit_scalar = crypto_bignum_init();
1341           ret = !mask || !sae->tmp->sae_rand || !sae->tmp->own_commit_scalar ||
1342                     dragonfly_generate_scalar(sae->tmp->order, sae->tmp->sae_rand,
1343                                                     mask,
1344                                                     sae->tmp->own_commit_scalar) < 0 ||
1345                     (sae->tmp->ec &&
1346                      sae_derive_commit_element_ecc(sae, mask) < 0) ||
1347                     (sae->tmp->dh &&
1348                      sae_derive_commit_element_ffc(sae, mask) < 0);
1349           crypto_bignum_deinit(mask, 1);
1350           return ret ? -1 : 0;
1351 }
1352 
1353 
sae_prepare_commit(const u8 * addr1,const u8 * addr2,const u8 * password,size_t password_len,struct sae_data * sae)1354 int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
1355                            const u8 *password, size_t password_len,
1356                            struct sae_data *sae)
1357 {
1358           if (sae->tmp == NULL ||
1359               (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
1360                                                             password_len) < 0) ||
1361               (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
1362                                                             password_len) < 0))
1363                     return -1;
1364 
1365           sae->h2e = 0;
1366           sae->pk = 0;
1367           return sae_derive_commit(sae);
1368 }
1369 
1370 
sae_prepare_commit_pt(struct sae_data * sae,const struct sae_pt * pt,const u8 * addr1,const u8 * addr2,int * rejected_groups,const struct sae_pk * pk)1371 int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
1372                                 const u8 *addr1, const u8 *addr2,
1373                                 int *rejected_groups, const struct sae_pk *pk)
1374 {
1375           if (!sae->tmp)
1376                     return -1;
1377 
1378           while (pt) {
1379                     if (pt->group == sae->group)
1380                               break;
1381                     pt = pt->next;
1382           }
1383           if (!pt) {
1384                     wpa_printf(MSG_INFO, "SAE: Could not find PT for group %u",
1385                                  sae->group);
1386                     return -1;
1387           }
1388 
1389 #ifdef CONFIG_SAE_PK
1390           os_memcpy(sae->tmp->ssid, pt->ssid, pt->ssid_len);
1391           sae->tmp->ssid_len = pt->ssid_len;
1392           sae->tmp->ap_pk = pk;
1393 #endif /* CONFIG_SAE_PK */
1394           sae->tmp->own_addr_higher = os_memcmp(addr1, addr2, ETH_ALEN) > 0;
1395           wpabuf_free(sae->tmp->own_rejected_groups);
1396           sae->tmp->own_rejected_groups = NULL;
1397           if (rejected_groups) {
1398                     int count, i;
1399                     struct wpabuf *groups;
1400 
1401                     count = int_array_len(rejected_groups);
1402                     groups = wpabuf_alloc(count * 2);
1403                     if (!groups)
1404                               return -1;
1405                     for (i = 0; i < count; i++)
1406                               wpabuf_put_le16(groups, rejected_groups[i]);
1407                     sae->tmp->own_rejected_groups = groups;
1408           }
1409 
1410           if (pt->ec) {
1411                     crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1);
1412                     sae->tmp->pwe_ecc = sae_derive_pwe_from_pt_ecc(pt, addr1,
1413                                                                              addr2);
1414                     if (!sae->tmp->pwe_ecc)
1415                               return -1;
1416           }
1417 
1418           if (pt->dh) {
1419                     crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
1420                     sae->tmp->pwe_ffc = sae_derive_pwe_from_pt_ffc(pt, addr1,
1421                                                                              addr2);
1422                     if (!sae->tmp->pwe_ffc)
1423                               return -1;
1424           }
1425 
1426           sae->h2e = 1;
1427           return sae_derive_commit(sae);
1428 }
1429 
1430 
sae_derive_k_ecc(struct sae_data * sae,u8 * k)1431 static int sae_derive_k_ecc(struct sae_data *sae, u8 *k)
1432 {
1433           struct crypto_ec_point *K;
1434           int ret = -1;
1435 
1436           K = crypto_ec_point_init(sae->tmp->ec);
1437           if (K == NULL)
1438                     goto fail;
1439 
1440           /*
1441            * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
1442            *                                        PEER-COMMIT-ELEMENT)))
1443            * If K is identity element (point-at-infinity), reject
1444            * k = F(K) (= x coordinate)
1445            */
1446 
1447           if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc,
1448                                         sae->peer_commit_scalar, K) < 0 ||
1449               crypto_ec_point_add(sae->tmp->ec, K,
1450                                         sae->tmp->peer_commit_element_ecc, K) < 0 ||
1451               crypto_ec_point_mul(sae->tmp->ec, K, sae->tmp->sae_rand, K) < 0 ||
1452               crypto_ec_point_is_at_infinity(sae->tmp->ec, K) ||
1453               crypto_ec_point_to_bin(sae->tmp->ec, K, k, NULL) < 0) {
1454                     wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
1455                     goto fail;
1456           }
1457 
1458           wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len);
1459 
1460           ret = 0;
1461 fail:
1462           crypto_ec_point_deinit(K, 1);
1463           return ret;
1464 }
1465 
1466 
sae_derive_k_ffc(struct sae_data * sae,u8 * k)1467 static int sae_derive_k_ffc(struct sae_data *sae, u8 *k)
1468 {
1469           struct crypto_bignum *K;
1470           int ret = -1;
1471 
1472           K = crypto_bignum_init();
1473           if (K == NULL)
1474                     goto fail;
1475 
1476           /*
1477            * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
1478            *                                        PEER-COMMIT-ELEMENT)))
1479            * If K is identity element (one), reject.
1480            * k = F(K) (= x coordinate)
1481            */
1482 
1483           if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, sae->peer_commit_scalar,
1484                                           sae->tmp->prime, K) < 0 ||
1485               crypto_bignum_mulmod(K, sae->tmp->peer_commit_element_ffc,
1486                                          sae->tmp->prime, K) < 0 ||
1487               crypto_bignum_exptmod(K, sae->tmp->sae_rand, sae->tmp->prime, K) < 0
1488               ||
1489               crypto_bignum_is_one(K) ||
1490               crypto_bignum_to_bin(K, k, SAE_MAX_PRIME_LEN, sae->tmp->prime_len) <
1491               0) {
1492                     wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
1493                     goto fail;
1494           }
1495 
1496           wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len);
1497 
1498           ret = 0;
1499 fail:
1500           crypto_bignum_deinit(K, 1);
1501           return ret;
1502 }
1503 
1504 
sae_kdf_hash(size_t hash_len,const u8 * k,const char * label,const u8 * context,size_t context_len,u8 * out,size_t out_len)1505 static int sae_kdf_hash(size_t hash_len, const u8 *k, const char *label,
1506                               const u8 *context, size_t context_len,
1507                               u8 *out, size_t out_len)
1508 {
1509           if (hash_len == 32)
1510                     return sha256_prf(k, hash_len, label,
1511                                           context, context_len, out, out_len);
1512 #ifdef CONFIG_SHA384
1513           if (hash_len == 48)
1514                     return sha384_prf(k, hash_len, label,
1515                                           context, context_len, out, out_len);
1516 #endif /* CONFIG_SHA384 */
1517 #ifdef CONFIG_SHA512
1518           if (hash_len == 64)
1519                     return sha512_prf(k, hash_len, label,
1520                                           context, context_len, out, out_len);
1521 #endif /* CONFIG_SHA512 */
1522           return -1;
1523 }
1524 
1525 
sae_derive_keys(struct sae_data * sae,const u8 * k)1526 static int sae_derive_keys(struct sae_data *sae, const u8 *k)
1527 {
1528           u8 zero[SAE_MAX_HASH_LEN], val[SAE_MAX_PRIME_LEN];
1529           const u8 *salt;
1530           struct wpabuf *rejected_groups = NULL;
1531           u8 keyseed[SAE_MAX_HASH_LEN];
1532           u8 keys[2 * SAE_MAX_HASH_LEN + SAE_PMK_LEN_MAX];
1533           struct crypto_bignum *tmp;
1534           int ret = -1;
1535           size_t hash_len, salt_len, prime_len = sae->tmp->prime_len;
1536           size_t pmk_len;
1537           const u8 *addr[1];
1538           size_t len[1];
1539 
1540           tmp = crypto_bignum_init();
1541           if (tmp == NULL)
1542                     goto fail;
1543 
1544           /* keyseed = H(salt, k)
1545            * KCK || PMK = KDF-Hash-Length(keyseed, "SAE KCK and PMK",
1546            *                      (commit-scalar + peer-commit-scalar) modulo r)
1547            * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128)
1548            *
1549            * When SAE-PK is used,
1550            * KCK || PMK || KEK = KDF-Hash-Length(keyseed, "SAE-PK keys", context)
1551            */
1552           if (!sae->h2e)
1553                     hash_len = SHA256_MAC_LEN;
1554           else if (sae->tmp->dh)
1555                     hash_len = sae_ffc_prime_len_2_hash_len(prime_len);
1556           else
1557                     hash_len = sae_ecc_prime_len_2_hash_len(prime_len);
1558           if (wpa_key_mgmt_sae_ext_key(sae->akmp))
1559                     pmk_len = hash_len;
1560           else
1561                     pmk_len = SAE_PMK_LEN;
1562           wpa_printf(MSG_DEBUG, "SAE: Derive keys - H2E=%d AKMP=0x%x = %08x (%s)",
1563                        sae->h2e, sae->akmp,
1564                        wpa_akm_to_suite(sae->akmp),
1565                        wpa_key_mgmt_txt(sae->akmp, WPA_PROTO_RSN));
1566           if (sae->h2e && (sae->tmp->own_rejected_groups ||
1567                                sae->tmp->peer_rejected_groups)) {
1568                     struct wpabuf *own, *peer;
1569 
1570                     own = sae->tmp->own_rejected_groups;
1571                     peer = sae->tmp->peer_rejected_groups;
1572                     salt_len = 0;
1573                     if (own)
1574                               salt_len += wpabuf_len(own);
1575                     if (peer)
1576                               salt_len += wpabuf_len(peer);
1577                     rejected_groups = wpabuf_alloc(salt_len);
1578                     if (!rejected_groups)
1579                               goto fail;
1580                     if (sae->tmp->own_addr_higher) {
1581                               if (own)
1582                                         wpabuf_put_buf(rejected_groups, own);
1583                               if (peer)
1584                                         wpabuf_put_buf(rejected_groups, peer);
1585                     } else {
1586                               if (peer)
1587                                         wpabuf_put_buf(rejected_groups, peer);
1588                               if (own)
1589                                         wpabuf_put_buf(rejected_groups, own);
1590                     }
1591                     salt = wpabuf_head(rejected_groups);
1592                     salt_len = wpabuf_len(rejected_groups);
1593           } else {
1594                     os_memset(zero, 0, hash_len);
1595                     salt = zero;
1596                     salt_len = hash_len;
1597           }
1598           wpa_hexdump(MSG_DEBUG, "SAE: salt for keyseed derivation",
1599                         salt, salt_len);
1600           addr[0] = k;
1601           len[0] = prime_len;
1602           if (hkdf_extract(hash_len, salt, salt_len, 1, addr, len, keyseed) < 0)
1603                     goto fail;
1604           wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, hash_len);
1605 
1606           if (crypto_bignum_add(sae->tmp->own_commit_scalar,
1607                                     sae->peer_commit_scalar, tmp) < 0 ||
1608               crypto_bignum_mod(tmp, sae->tmp->order, tmp) < 0)
1609                     goto fail;
1610           /* IEEE Std 802.11-2016 is not exactly clear on the encoding of the bit
1611            * string that is needed for KCK, PMK, and PMKID derivation, but it
1612            * seems to make most sense to encode the
1613            * (commit-scalar + peer-commit-scalar) mod r part as a bit string by
1614            * zero padding it from left to the length of the order (in full
1615            * octets). */
1616           if (crypto_bignum_to_bin(tmp, val, sizeof(val),
1617                                          sae->tmp->order_len) < 0)
1618                     goto fail;
1619           wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
1620 
1621 #ifdef CONFIG_SAE_PK
1622           if (sae->pk) {
1623                     if (sae_kdf_hash(hash_len, keyseed, "SAE-PK keys",
1624                                          val, sae->tmp->order_len,
1625                                          keys, 2 * hash_len + pmk_len) < 0)
1626                               goto fail;
1627           } else {
1628                     if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK",
1629                                          val, sae->tmp->order_len,
1630                                          keys, hash_len + pmk_len) < 0)
1631                               goto fail;
1632           }
1633 #else /* CONFIG_SAE_PK */
1634           if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK",
1635                                val, sae->tmp->order_len,
1636                                keys, hash_len + pmk_len) < 0)
1637                     goto fail;
1638 #endif /* !CONFIG_SAE_PK */
1639 
1640           forced_memzero(keyseed, sizeof(keyseed));
1641           os_memcpy(sae->tmp->kck, keys, hash_len);
1642           sae->tmp->kck_len = hash_len;
1643           os_memcpy(sae->pmk, keys + hash_len, pmk_len);
1644           sae->pmk_len = pmk_len;
1645           os_memcpy(sae->pmkid, val, SAE_PMKID_LEN);
1646 #ifdef CONFIG_SAE_PK
1647           if (sae->pk) {
1648                     os_memcpy(sae->tmp->kek, keys + hash_len + SAE_PMK_LEN,
1649                                 hash_len);
1650                     sae->tmp->kek_len = hash_len;
1651                     wpa_hexdump_key(MSG_DEBUG, "SAE: KEK for SAE-PK",
1652                                         sae->tmp->kek, sae->tmp->kek_len);
1653           }
1654 #endif /* CONFIG_SAE_PK */
1655           forced_memzero(keys, sizeof(keys));
1656           wpa_hexdump_key(MSG_DEBUG, "SAE: KCK",
1657                               sae->tmp->kck, sae->tmp->kck_len);
1658           wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, sae->pmk_len);
1659 
1660           ret = 0;
1661 fail:
1662           wpabuf_free(rejected_groups);
1663           crypto_bignum_deinit(tmp, 0);
1664           return ret;
1665 }
1666 
1667 
sae_process_commit(struct sae_data * sae)1668 int sae_process_commit(struct sae_data *sae)
1669 {
1670           u8 k[SAE_MAX_PRIME_LEN];
1671           if (sae->tmp == NULL ||
1672               (sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) ||
1673               (sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) ||
1674               sae_derive_keys(sae, k) < 0)
1675                     return -1;
1676           return 0;
1677 }
1678 
1679 
sae_write_commit(struct sae_data * sae,struct wpabuf * buf,const struct wpabuf * token,const char * identifier)1680 int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
1681                          const struct wpabuf *token, const char *identifier)
1682 {
1683           u8 *pos;
1684 
1685           if (sae->tmp == NULL)
1686                     return -1;
1687 
1688           wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
1689           if (!sae->h2e && token) {
1690                     wpabuf_put_buf(buf, token);
1691                     wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token",
1692                                   wpabuf_head(token), wpabuf_len(token));
1693           }
1694           pos = wpabuf_put(buf, sae->tmp->prime_len);
1695           if (crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
1696                                          sae->tmp->prime_len, sae->tmp->prime_len) < 0)
1697                     return -1;
1698           wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar",
1699                         pos, sae->tmp->prime_len);
1700           if (sae->tmp->ec) {
1701                     pos = wpabuf_put(buf, 2 * sae->tmp->prime_len);
1702                     if (crypto_ec_point_to_bin(sae->tmp->ec,
1703                                                      sae->tmp->own_commit_element_ecc,
1704                                                      pos, pos + sae->tmp->prime_len) < 0)
1705                               return -1;
1706                     wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)",
1707                                   pos, sae->tmp->prime_len);
1708                     wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)",
1709                                   pos + sae->tmp->prime_len, sae->tmp->prime_len);
1710           } else {
1711                     pos = wpabuf_put(buf, sae->tmp->prime_len);
1712                     if (crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos,
1713                                                    sae->tmp->prime_len,
1714                                                    sae->tmp->prime_len) < 0)
1715                               return -1;
1716                     wpa_hexdump(MSG_DEBUG, "SAE: own commit-element",
1717                                   pos, sae->tmp->prime_len);
1718           }
1719 
1720           if (identifier) {
1721                     /* Password Identifier element */
1722                     wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1723                     wpabuf_put_u8(buf, 1 + os_strlen(identifier));
1724                     wpabuf_put_u8(buf, WLAN_EID_EXT_PASSWORD_IDENTIFIER);
1725                     wpabuf_put_str(buf, identifier);
1726                     wpa_printf(MSG_DEBUG, "SAE: own Password Identifier: %s",
1727                                  identifier);
1728           }
1729 
1730           if (sae->h2e && sae->tmp->own_rejected_groups) {
1731                     wpa_hexdump_buf(MSG_DEBUG, "SAE: own Rejected Groups",
1732                                         sae->tmp->own_rejected_groups);
1733                     wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1734                     wpabuf_put_u8(buf,
1735                                     1 + wpabuf_len(sae->tmp->own_rejected_groups));
1736                     wpabuf_put_u8(buf, WLAN_EID_EXT_REJECTED_GROUPS);
1737                     wpabuf_put_buf(buf, sae->tmp->own_rejected_groups);
1738           }
1739 
1740           if (sae->h2e && token) {
1741                     wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1742                     wpabuf_put_u8(buf, 1 + wpabuf_len(token));
1743                     wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN);
1744                     wpabuf_put_buf(buf, token);
1745                     wpa_hexdump_buf(MSG_DEBUG,
1746                                         "SAE: Anti-clogging token (in container)",
1747                                         token);
1748           }
1749 
1750           if (wpa_key_mgmt_sae_ext_key(sae->akmp)) {
1751                     u32 suite = wpa_akm_to_suite(sae->akmp);
1752 
1753                     wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1754                     wpabuf_put_u8(buf, 1 + RSN_SELECTOR_LEN);
1755                     wpabuf_put_u8(buf, WLAN_EID_EXT_AKM_SUITE_SELECTOR);
1756                     RSN_SELECTOR_PUT(wpabuf_put(buf, RSN_SELECTOR_LEN), suite);
1757                     wpa_printf(MSG_DEBUG, "SAE: AKM Suite Selector: %08x", suite);
1758                     sae->own_akm_suite_selector = suite;
1759           }
1760 
1761           return 0;
1762 }
1763 
1764 
sae_group_allowed(struct sae_data * sae,int * allowed_groups,u16 group)1765 u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group)
1766 {
1767           if (allowed_groups) {
1768                     int i;
1769                     for (i = 0; allowed_groups[i] > 0; i++) {
1770                               if (allowed_groups[i] == group)
1771                                         break;
1772                     }
1773                     if (allowed_groups[i] != group) {
1774                               wpa_printf(MSG_DEBUG, "SAE: Proposed group %u not "
1775                                            "enabled in the current configuration",
1776                                            group);
1777                               return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1778                     }
1779           }
1780 
1781           if (sae->state == SAE_COMMITTED && group != sae->group) {
1782                     wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed");
1783                     return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1784           }
1785 
1786           if (group != sae->group && sae_set_group(sae, group) < 0) {
1787                     wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
1788                                  group);
1789                     return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1790           }
1791 
1792           if (sae->tmp == NULL) {
1793                     wpa_printf(MSG_DEBUG, "SAE: Group information not yet initialized");
1794                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
1795           }
1796 
1797           if (sae->tmp->dh && !allowed_groups) {
1798                     wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without "
1799                                  "explicit configuration enabling it", group);
1800                     return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1801           }
1802 
1803           return WLAN_STATUS_SUCCESS;
1804 }
1805 
1806 
sae_is_password_id_elem(const u8 * pos,const u8 * end)1807 static int sae_is_password_id_elem(const u8 *pos, const u8 *end)
1808 {
1809           return end - pos >= 3 &&
1810                     pos[0] == WLAN_EID_EXTENSION &&
1811                     pos[1] >= 1 &&
1812                     end - pos - 2 >= pos[1] &&
1813                     pos[2] == WLAN_EID_EXT_PASSWORD_IDENTIFIER;
1814 }
1815 
1816 
sae_is_rejected_groups_elem(const u8 * pos,const u8 * end)1817 static int sae_is_rejected_groups_elem(const u8 *pos, const u8 *end)
1818 {
1819           return end - pos >= 3 &&
1820                     pos[0] == WLAN_EID_EXTENSION &&
1821                     pos[1] >= 2 &&
1822                     end - pos - 2 >= pos[1] &&
1823                     pos[2] == WLAN_EID_EXT_REJECTED_GROUPS;
1824 }
1825 
1826 
sae_is_token_container_elem(const u8 * pos,const u8 * end)1827 static int sae_is_token_container_elem(const u8 *pos, const u8 *end)
1828 {
1829           return end - pos >= 3 &&
1830                     pos[0] == WLAN_EID_EXTENSION &&
1831                     pos[1] >= 1 &&
1832                     end - pos - 2 >= pos[1] &&
1833                     pos[2] == WLAN_EID_EXT_ANTI_CLOGGING_TOKEN;
1834 }
1835 
1836 
sae_is_akm_suite_selector_elem(const u8 * pos,const u8 * end)1837 static int sae_is_akm_suite_selector_elem(const u8 *pos, const u8 *end)
1838 {
1839           return end - pos >= 2 + 1 + RSN_SELECTOR_LEN &&
1840                     pos[0] == WLAN_EID_EXTENSION &&
1841                     pos[1] >= 1 + RSN_SELECTOR_LEN &&
1842                     end - pos - 2 >= pos[1] &&
1843                     pos[2] == WLAN_EID_EXT_AKM_SUITE_SELECTOR;
1844 }
1845 
1846 
sae_parse_commit_token(struct sae_data * sae,const u8 ** pos,const u8 * end,const u8 ** token,size_t * token_len,int h2e)1847 static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
1848                                            const u8 *end, const u8 **token,
1849                                            size_t *token_len, int h2e)
1850 {
1851           size_t scalar_elem_len, tlen;
1852 
1853           if (token)
1854                     *token = NULL;
1855           if (token_len)
1856                     *token_len = 0;
1857 
1858           if (h2e)
1859                     return; /* No Anti-Clogging Token field outside container IE */
1860 
1861           scalar_elem_len = (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len;
1862           if (scalar_elem_len >= (size_t) (end - *pos))
1863                     return; /* No extra data beyond peer scalar and element */
1864 
1865           tlen = end - (*pos + scalar_elem_len);
1866 
1867           if (tlen < SHA256_MAC_LEN) {
1868                     wpa_printf(MSG_DEBUG,
1869                                  "SAE: Too short optional data (%u octets) to include our Anti-Clogging Token",
1870                                  (unsigned int) tlen);
1871                     return;
1872           }
1873 
1874           wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
1875           if (token)
1876                     *token = *pos;
1877           if (token_len)
1878                     *token_len = tlen;
1879           *pos += tlen;
1880 }
1881 
1882 
sae_parse_token_container(struct sae_data * sae,const u8 * pos,const u8 * end,const u8 ** token,size_t * token_len)1883 static void sae_parse_token_container(struct sae_data *sae,
1884                                               const u8 *pos, const u8 *end,
1885                                               const u8 **token, size_t *token_len)
1886 {
1887           wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
1888                         pos, end - pos);
1889           if (!sae_is_token_container_elem(pos, end))
1890                     return;
1891           *token = pos + 3;
1892           *token_len = pos[1] - 1;
1893           wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token (in container)",
1894                         *token, *token_len);
1895 }
1896 
1897 
sae_parse_commit_scalar(struct sae_data * sae,const u8 ** pos,const u8 * end)1898 static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos,
1899                                            const u8 *end)
1900 {
1901           struct crypto_bignum *peer_scalar;
1902 
1903           if (sae->tmp->prime_len > end - *pos) {
1904                     wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar");
1905                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
1906           }
1907 
1908           peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len);
1909           if (peer_scalar == NULL)
1910                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
1911 
1912           /*
1913            * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for
1914            * the peer and it is in Authenticated state, the new Commit Message
1915            * shall be dropped if the peer-scalar is identical to the one used in
1916            * the existing protocol instance.
1917            */
1918           if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar_accepted &&
1919               crypto_bignum_cmp(sae->peer_commit_scalar_accepted,
1920                                     peer_scalar) == 0) {
1921                     wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous "
1922                                  "peer-commit-scalar");
1923                     crypto_bignum_deinit(peer_scalar, 0);
1924                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
1925           }
1926 
1927           /* 1 < scalar < r */
1928           if (crypto_bignum_is_zero(peer_scalar) ||
1929               crypto_bignum_is_one(peer_scalar) ||
1930               crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) {
1931                     wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar");
1932                     crypto_bignum_deinit(peer_scalar, 0);
1933                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
1934           }
1935 
1936 
1937           crypto_bignum_deinit(sae->peer_commit_scalar, 0);
1938           sae->peer_commit_scalar = peer_scalar;
1939           wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar",
1940                         *pos, sae->tmp->prime_len);
1941           *pos += sae->tmp->prime_len;
1942 
1943           return WLAN_STATUS_SUCCESS;
1944 }
1945 
1946 
sae_parse_commit_element_ecc(struct sae_data * sae,const u8 ** pos,const u8 * end)1947 static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 **pos,
1948                                                   const u8 *end)
1949 {
1950           u8 prime[SAE_MAX_ECC_PRIME_LEN];
1951 
1952           if (2 * sae->tmp->prime_len > end - *pos) {
1953                     wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
1954                                  "commit-element");
1955                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
1956           }
1957 
1958           if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
1959                                          sae->tmp->prime_len) < 0)
1960                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
1961 
1962           /* element x and y coordinates < p */
1963           if (os_memcmp(*pos, prime, sae->tmp->prime_len) >= 0 ||
1964               os_memcmp(*pos + sae->tmp->prime_len, prime,
1965                           sae->tmp->prime_len) >= 0) {
1966                     wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer "
1967                                  "element");
1968                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
1969           }
1970 
1971           wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)",
1972                         *pos, sae->tmp->prime_len);
1973           wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)",
1974                         *pos + sae->tmp->prime_len, sae->tmp->prime_len);
1975 
1976           crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0);
1977           sae->tmp->peer_commit_element_ecc =
1978                     crypto_ec_point_from_bin(sae->tmp->ec, *pos);
1979           if (!sae->tmp->peer_commit_element_ecc) {
1980                     wpa_printf(MSG_DEBUG, "SAE: Peer element is not a valid point");
1981                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
1982           }
1983 
1984           if (!crypto_ec_point_is_on_curve(sae->tmp->ec,
1985                                                    sae->tmp->peer_commit_element_ecc)) {
1986                     wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve");
1987                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
1988           }
1989 
1990           *pos += 2 * sae->tmp->prime_len;
1991 
1992           return WLAN_STATUS_SUCCESS;
1993 }
1994 
1995 
sae_parse_commit_element_ffc(struct sae_data * sae,const u8 ** pos,const u8 * end)1996 static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 **pos,
1997                                                   const u8 *end)
1998 {
1999           struct crypto_bignum *res, *one;
2000           const u8 one_bin[1] = { 0x01 };
2001 
2002           if (sae->tmp->prime_len > end - *pos) {
2003                     wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
2004                                  "commit-element");
2005                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
2006           }
2007           wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", *pos,
2008                         sae->tmp->prime_len);
2009 
2010           crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0);
2011           sae->tmp->peer_commit_element_ffc =
2012                     crypto_bignum_init_set(*pos, sae->tmp->prime_len);
2013           if (sae->tmp->peer_commit_element_ffc == NULL)
2014                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
2015           /* 1 < element < p - 1 */
2016           res = crypto_bignum_init();
2017           one = crypto_bignum_init_set(one_bin, sizeof(one_bin));
2018           if (!res || !one ||
2019               crypto_bignum_sub(sae->tmp->prime, one, res) ||
2020               crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) ||
2021               crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) ||
2022               crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc, res) >= 0) {
2023                     crypto_bignum_deinit(res, 0);
2024                     crypto_bignum_deinit(one, 0);
2025                     wpa_printf(MSG_DEBUG, "SAE: Invalid peer element");
2026                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
2027           }
2028           crypto_bignum_deinit(one, 0);
2029 
2030           /* scalar-op(r, ELEMENT) = 1 modulo p */
2031           if (crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc,
2032                                           sae->tmp->order, sae->tmp->prime, res) < 0 ||
2033               !crypto_bignum_is_one(res)) {
2034                     wpa_printf(MSG_DEBUG, "SAE: Invalid peer element (scalar-op)");
2035                     crypto_bignum_deinit(res, 0);
2036                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
2037           }
2038           crypto_bignum_deinit(res, 0);
2039 
2040           *pos += sae->tmp->prime_len;
2041 
2042           return WLAN_STATUS_SUCCESS;
2043 }
2044 
2045 
sae_parse_commit_element(struct sae_data * sae,const u8 ** pos,const u8 * end)2046 static u16 sae_parse_commit_element(struct sae_data *sae, const u8 **pos,
2047                                             const u8 *end)
2048 {
2049           if (sae->tmp->dh)
2050                     return sae_parse_commit_element_ffc(sae, pos, end);
2051           return sae_parse_commit_element_ecc(sae, pos, end);
2052 }
2053 
2054 
sae_parse_password_identifier(struct sae_data * sae,const u8 ** pos,const u8 * end)2055 static int sae_parse_password_identifier(struct sae_data *sae,
2056                                                    const u8 **pos, const u8 *end)
2057 {
2058           const u8 *epos;
2059           u8 len;
2060 
2061           wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
2062                         *pos, end - *pos);
2063           if (!sae_is_password_id_elem(*pos, end)) {
2064                     if (sae->tmp->pw_id) {
2065                               wpa_printf(MSG_DEBUG,
2066                                            "SAE: No Password Identifier included, but expected one (%s)",
2067                                            sae->tmp->pw_id);
2068                               return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
2069                     }
2070                     os_free(sae->tmp->pw_id);
2071                     sae->tmp->pw_id = NULL;
2072                     return WLAN_STATUS_SUCCESS; /* No Password Identifier */
2073           }
2074 
2075           epos = *pos;
2076           epos++; /* skip IE type */
2077           len = *epos++; /* IE length */
2078           if (len > end - epos || len < 1)
2079                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
2080           epos++; /* skip ext ID */
2081           len--;
2082 
2083           if (sae->tmp->pw_id &&
2084               (len != os_strlen(sae->tmp->pw_id) ||
2085                os_memcmp(sae->tmp->pw_id, epos, len) != 0)) {
2086                     wpa_printf(MSG_DEBUG,
2087                                  "SAE: The included Password Identifier does not match the expected one (%s)",
2088                                  sae->tmp->pw_id);
2089                     return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
2090           }
2091 
2092           os_free(sae->tmp->pw_id);
2093           sae->tmp->pw_id = os_malloc(len + 1);
2094           if (!sae->tmp->pw_id)
2095                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
2096           os_memcpy(sae->tmp->pw_id, epos, len);
2097           sae->tmp->pw_id[len] = '\0';
2098           wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier",
2099                                 sae->tmp->pw_id, len);
2100           *pos = epos + len;
2101           return WLAN_STATUS_SUCCESS;
2102 }
2103 
2104 
sae_parse_rejected_groups(struct sae_data * sae,const u8 ** pos,const u8 * end)2105 static int sae_parse_rejected_groups(struct sae_data *sae,
2106                                              const u8 **pos, const u8 *end)
2107 {
2108           const u8 *epos;
2109           u8 len;
2110 
2111           wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
2112                         *pos, end - *pos);
2113           if (!sae_is_rejected_groups_elem(*pos, end)) {
2114                     wpabuf_free(sae->tmp->peer_rejected_groups);
2115                     sae->tmp->peer_rejected_groups = NULL;
2116                     return WLAN_STATUS_SUCCESS;
2117           }
2118 
2119           epos = *pos;
2120           epos++; /* skip IE type */
2121           len = *epos++; /* IE length */
2122           if (len > end - epos || len < 1)
2123                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
2124           epos++; /* skip ext ID */
2125           len--;
2126           if (len & 1) {
2127                     wpa_printf(MSG_DEBUG,
2128                                  "SAE: Invalid length of the Rejected Groups element payload: %u",
2129                                  len);
2130                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
2131           }
2132 
2133           wpabuf_free(sae->tmp->peer_rejected_groups);
2134           sae->tmp->peer_rejected_groups = wpabuf_alloc(len);
2135           if (!sae->tmp->peer_rejected_groups)
2136                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
2137           wpabuf_put_data(sae->tmp->peer_rejected_groups, epos, len);
2138           wpa_hexdump_buf(MSG_DEBUG, "SAE: Received Rejected Groups list",
2139                               sae->tmp->peer_rejected_groups);
2140           *pos = epos + len;
2141           return WLAN_STATUS_SUCCESS;
2142 }
2143 
2144 
sae_parse_akm_suite_selector(struct sae_data * sae,const u8 ** pos,const u8 * end)2145 static int sae_parse_akm_suite_selector(struct sae_data *sae,
2146                                                   const u8 **pos, const u8 *end)
2147 {
2148           const u8 *epos;
2149           u8 len;
2150 
2151           wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
2152                         *pos, end - *pos);
2153           if (!sae_is_akm_suite_selector_elem(*pos, end))
2154                     return WLAN_STATUS_SUCCESS;
2155 
2156           epos = *pos;
2157           epos++; /* skip IE type */
2158           len = *epos++; /* IE length */
2159           if (len > end - epos || len < 1)
2160                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
2161           epos++; /* skip ext ID */
2162           len--;
2163 
2164           if (len < RSN_SELECTOR_LEN)
2165                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
2166           sae->peer_akm_suite_selector = RSN_SELECTOR_GET(epos);
2167           wpa_printf(MSG_DEBUG, "SAE: Received AKM Suite Selector: %08x",
2168                        sae->peer_akm_suite_selector);
2169           *pos = epos + len;
2170           return WLAN_STATUS_SUCCESS;
2171 }
2172 
2173 
sae_parse_commit(struct sae_data * sae,const u8 * data,size_t len,const u8 ** token,size_t * token_len,int * allowed_groups,int h2e,int * ie_offset)2174 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
2175                          const u8 **token, size_t *token_len, int *allowed_groups,
2176                          int h2e, int *ie_offset)
2177 {
2178           const u8 *pos = data, *end = data + len;
2179           u16 res;
2180 
2181           /* Check Finite Cyclic Group */
2182           if (end - pos < 2)
2183                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
2184           res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos));
2185           if (res != WLAN_STATUS_SUCCESS)
2186                     return res;
2187           pos += 2;
2188 
2189           /* Optional Anti-Clogging Token */
2190           sae_parse_commit_token(sae, &pos, end, token, token_len, h2e);
2191 
2192           /* commit-scalar */
2193           res = sae_parse_commit_scalar(sae, &pos, end);
2194           if (res != WLAN_STATUS_SUCCESS)
2195                     return res;
2196 
2197           /* commit-element */
2198           res = sae_parse_commit_element(sae, &pos, end);
2199           if (res != WLAN_STATUS_SUCCESS)
2200                     return res;
2201 
2202           if (ie_offset)
2203                     *ie_offset = pos - data;
2204 
2205           /* Optional Password Identifier element */
2206           res = sae_parse_password_identifier(sae, &pos, end);
2207           if (res != WLAN_STATUS_SUCCESS)
2208                     return res;
2209 
2210           /* Conditional Rejected Groups element */
2211           if (h2e) {
2212                     res = sae_parse_rejected_groups(sae, &pos, end);
2213                     if (res != WLAN_STATUS_SUCCESS)
2214                               return res;
2215           } else {
2216                     wpabuf_free(sae->tmp->peer_rejected_groups);
2217                     sae->tmp->peer_rejected_groups = NULL;
2218           }
2219 
2220           /* Optional Anti-Clogging Token Container element */
2221           if (h2e)
2222                     sae_parse_token_container(sae, pos, end, token, token_len);
2223 
2224           /* Conditional AKM Suite Selector element */
2225           if (h2e) {
2226                     res = sae_parse_akm_suite_selector(sae, &pos, end);
2227                     if (res != WLAN_STATUS_SUCCESS)
2228                               return res;
2229           }
2230 
2231           if (sae->own_akm_suite_selector &&
2232               sae->own_akm_suite_selector != sae->peer_akm_suite_selector) {
2233                     wpa_printf(MSG_DEBUG,
2234                                  "SAE: AKM suite selector mismatch: own=%08x peer=%08x",
2235                                  sae->own_akm_suite_selector,
2236                                  sae->peer_akm_suite_selector);
2237                     return WLAN_STATUS_UNSPECIFIED_FAILURE;
2238           }
2239 
2240           if (!sae->akmp) {
2241                     if (sae->peer_akm_suite_selector ==
2242                         RSN_AUTH_KEY_MGMT_SAE_EXT_KEY)
2243                               sae->akmp = WPA_KEY_MGMT_SAE_EXT_KEY;
2244                     else if (sae->peer_akm_suite_selector ==
2245                         RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY)
2246                               sae->akmp = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
2247           }
2248 
2249           /*
2250            * Check whether peer-commit-scalar and PEER-COMMIT-ELEMENT are same as
2251            * the values we sent which would be evidence of a reflection attack.
2252            */
2253           if (!sae->tmp->own_commit_scalar ||
2254               crypto_bignum_cmp(sae->tmp->own_commit_scalar,
2255                                     sae->peer_commit_scalar) != 0 ||
2256               (sae->tmp->dh &&
2257                (!sae->tmp->own_commit_element_ffc ||
2258                 crypto_bignum_cmp(sae->tmp->own_commit_element_ffc,
2259                                         sae->tmp->peer_commit_element_ffc) != 0)) ||
2260               (sae->tmp->ec &&
2261                (!sae->tmp->own_commit_element_ecc ||
2262                 crypto_ec_point_cmp(sae->tmp->ec,
2263                                           sae->tmp->own_commit_element_ecc,
2264                                           sae->tmp->peer_commit_element_ecc) != 0)))
2265                     return WLAN_STATUS_SUCCESS; /* scalars/elements are different */
2266 
2267           /*
2268            * This is a reflection attack - return special value to trigger caller
2269            * to silently discard the frame instead of replying with a specific
2270            * status code.
2271            */
2272           return SAE_SILENTLY_DISCARD;
2273 }
2274 
2275 
sae_cn_confirm(struct sae_data * sae,const u8 * sc,const struct crypto_bignum * scalar1,const u8 * element1,size_t element1_len,const struct crypto_bignum * scalar2,const u8 * element2,size_t element2_len,u8 * confirm)2276 static int sae_cn_confirm(struct sae_data *sae, const u8 *sc,
2277                                 const struct crypto_bignum *scalar1,
2278                                 const u8 *element1, size_t element1_len,
2279                                 const struct crypto_bignum *scalar2,
2280                                 const u8 *element2, size_t element2_len,
2281                                 u8 *confirm)
2282 {
2283           const u8 *addr[5];
2284           size_t len[5];
2285           u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN];
2286 
2287           /* Confirm
2288            * CN(key, X, Y, Z, ...) =
2289            *    HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...)
2290            * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT,
2291            *              peer-commit-scalar, PEER-COMMIT-ELEMENT)
2292            * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar,
2293            *               PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT)
2294            */
2295           if (crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1),
2296                                          sae->tmp->prime_len) < 0 ||
2297               crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2),
2298                                          sae->tmp->prime_len) < 0)
2299                     return -1;
2300           addr[0] = sc;
2301           len[0] = 2;
2302           addr[1] = scalar_b1;
2303           len[1] = sae->tmp->prime_len;
2304           addr[2] = element1;
2305           len[2] = element1_len;
2306           addr[3] = scalar_b2;
2307           len[3] = sae->tmp->prime_len;
2308           addr[4] = element2;
2309           len[4] = element2_len;
2310           return hkdf_extract(sae->tmp->kck_len, sae->tmp->kck, sae->tmp->kck_len,
2311                                   5, addr, len, confirm);
2312 }
2313 
2314 
sae_cn_confirm_ecc(struct sae_data * sae,const u8 * sc,const struct crypto_bignum * scalar1,const struct crypto_ec_point * element1,const struct crypto_bignum * scalar2,const struct crypto_ec_point * element2,u8 * confirm)2315 static int sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
2316                                     const struct crypto_bignum *scalar1,
2317                                     const struct crypto_ec_point *element1,
2318                                     const struct crypto_bignum *scalar2,
2319                                     const struct crypto_ec_point *element2,
2320                                     u8 *confirm)
2321 {
2322           u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN];
2323           u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN];
2324 
2325           if (crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1,
2326                                            element_b1 + sae->tmp->prime_len) < 0 ||
2327               crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2,
2328                                            element_b2 + sae->tmp->prime_len) < 0 ||
2329               sae_cn_confirm(sae, sc, scalar1, element_b1,
2330                                  2 * sae->tmp->prime_len,
2331                                  scalar2, element_b2, 2 * sae->tmp->prime_len,
2332                                  confirm) < 0)
2333                     return -1;
2334           return 0;
2335 }
2336 
2337 
sae_cn_confirm_ffc(struct sae_data * sae,const u8 * sc,const struct crypto_bignum * scalar1,const struct crypto_bignum * element1,const struct crypto_bignum * scalar2,const struct crypto_bignum * element2,u8 * confirm)2338 static int sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
2339                                     const struct crypto_bignum *scalar1,
2340                                     const struct crypto_bignum *element1,
2341                                     const struct crypto_bignum *scalar2,
2342                                     const struct crypto_bignum *element2,
2343                                     u8 *confirm)
2344 {
2345           u8 element_b1[SAE_MAX_PRIME_LEN];
2346           u8 element_b2[SAE_MAX_PRIME_LEN];
2347 
2348           if (crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1),
2349                                          sae->tmp->prime_len) < 0 ||
2350               crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2),
2351                                          sae->tmp->prime_len) < 0 ||
2352               sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len,
2353                                  scalar2, element_b2, sae->tmp->prime_len,
2354                                  confirm) < 0)
2355                     return -1;
2356           return 0;
2357 }
2358 
2359 
sae_write_confirm(struct sae_data * sae,struct wpabuf * buf)2360 int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
2361 {
2362           const u8 *sc;
2363           size_t hash_len;
2364           int res;
2365 
2366           if (sae->tmp == NULL)
2367                     return -1;
2368 
2369           hash_len = sae->tmp->kck_len;
2370 
2371           /* Send-Confirm */
2372           if (sae->send_confirm < 0xffff)
2373                     sae->send_confirm++;
2374           sc = wpabuf_put(buf, 0);
2375           wpabuf_put_le16(buf, sae->send_confirm);
2376 
2377           if (sae->tmp->ec)
2378                     res = sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
2379                                                    sae->tmp->own_commit_element_ecc,
2380                                                    sae->peer_commit_scalar,
2381                                                    sae->tmp->peer_commit_element_ecc,
2382                                                    wpabuf_put(buf, hash_len));
2383           else
2384                     res = sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar,
2385                                                    sae->tmp->own_commit_element_ffc,
2386                                                    sae->peer_commit_scalar,
2387                                                    sae->tmp->peer_commit_element_ffc,
2388                                                    wpabuf_put(buf, hash_len));
2389           if (res)
2390                     return res;
2391 
2392 #ifdef CONFIG_SAE_PK
2393           if (sae_write_confirm_pk(sae, buf) < 0)
2394                     return -1;
2395 #endif /* CONFIG_SAE_PK */
2396 
2397           return 0;
2398 }
2399 
2400 
sae_check_confirm(struct sae_data * sae,const u8 * data,size_t len,int * ie_offset)2401 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len,
2402                           int *ie_offset)
2403 {
2404           u8 verifier[SAE_MAX_HASH_LEN];
2405           size_t hash_len;
2406 
2407           if (!sae->tmp)
2408                     return -1;
2409 
2410           hash_len = sae->tmp->kck_len;
2411           if (len < 2 + hash_len) {
2412                     wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
2413                     return -1;
2414           }
2415 
2416           wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data));
2417 
2418           if (!sae->peer_commit_scalar || !sae->tmp->own_commit_scalar) {
2419                     wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available");
2420                     return -1;
2421           }
2422 
2423           if (sae->tmp->ec) {
2424                     if (!sae->tmp->peer_commit_element_ecc ||
2425                         !sae->tmp->own_commit_element_ecc ||
2426                         sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar,
2427                                                sae->tmp->peer_commit_element_ecc,
2428                                                sae->tmp->own_commit_scalar,
2429                                                sae->tmp->own_commit_element_ecc,
2430                                                verifier) < 0)
2431                               return -1;
2432           } else {
2433                     if (!sae->tmp->peer_commit_element_ffc ||
2434                         !sae->tmp->own_commit_element_ffc ||
2435                         sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar,
2436                                                sae->tmp->peer_commit_element_ffc,
2437                                                sae->tmp->own_commit_scalar,
2438                                                sae->tmp->own_commit_element_ffc,
2439                                                verifier) < 0)
2440                               return -1;
2441           }
2442 
2443           if (os_memcmp_const(verifier, data + 2, hash_len) != 0) {
2444                     wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
2445                     wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
2446                                   data + 2, hash_len);
2447                     wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
2448                                   verifier, hash_len);
2449                     return -1;
2450           }
2451 
2452 #ifdef CONFIG_SAE_PK
2453           if (sae_check_confirm_pk(sae, data + 2 + hash_len,
2454                                          len - 2 - hash_len) < 0)
2455                     return -1;
2456 #endif /* CONFIG_SAE_PK */
2457 
2458           /* 2 bytes are for send-confirm, then the hash, followed by IEs */
2459           if (ie_offset)
2460                     *ie_offset = 2 + hash_len;
2461 
2462           return 0;
2463 }
2464 
2465 
sae_state_txt(enum sae_state state)2466 const char * sae_state_txt(enum sae_state state)
2467 {
2468           switch (state) {
2469           case SAE_NOTHING:
2470                     return "Nothing";
2471           case SAE_COMMITTED:
2472                     return "Committed";
2473           case SAE_CONFIRMED:
2474                     return "Confirmed";
2475           case SAE_ACCEPTED:
2476                     return "Accepted";
2477           }
2478           return "?";
2479 }
2480