LCOV - code coverage report
Current view: top level - src/common - sae.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 659 683 96.5 %
Date: 2016-10-02 Functions: 35 35 100.0 %

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

Generated by: LCOV version 1.10