hostapd: Update to version 2.8 (2019-04-21)
[openwrt/staging/chunkeey.git] / package / network / services / hostapd / patches / 061-0005-SAE-Minimize-timing-differences-in-PWE-derivation.patch
diff --git a/package/network/services/hostapd/patches/061-0005-SAE-Minimize-timing-differences-in-PWE-derivation.patch b/package/network/services/hostapd/patches/061-0005-SAE-Minimize-timing-differences-in-PWE-derivation.patch
deleted file mode 100644 (file)
index e72a9cb..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-From 6513db3e96c43c2e36805cf5ead349765d18eaf7 Mon Sep 17 00:00:00 2001
-From: Jouni Malinen <jouni@codeaurora.org>
-Date: Tue, 26 Feb 2019 13:05:09 +0200
-Subject: [PATCH 05/14] SAE: Minimize timing differences in PWE derivation
-
-The QR test result can provide information about the password to an
-attacker, so try to minimize differences in how the
-sae_test_pwd_seed_ecc() result is used. (CVE-2019-9494)
-
-Use heap memory for the dummy password to allow the same password length
-to be used even with long passwords.
-
-Use constant time selection functions to track the real vs. dummy
-variables so that the exact same operations can be performed for both QR
-test results.
-
-Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
----
- src/common/sae.c | 106 ++++++++++++++++++++++++++++++-------------------------
- 1 file changed, 57 insertions(+), 49 deletions(-)
-
---- a/src/common/sae.c
-+++ b/src/common/sae.c
-@@ -9,6 +9,7 @@
- #include "includes.h"
- #include "common.h"
-+#include "utils/const_time.h"
- #include "crypto/crypto.h"
- #include "crypto/sha256.h"
- #include "crypto/random.h"
-@@ -269,15 +270,12 @@ static int sae_test_pwd_seed_ecc(struct
-                                const u8 *prime,
-                                const struct crypto_bignum *qr,
-                                const struct crypto_bignum *qnr,
--                               struct crypto_bignum **ret_x_cand)
-+                               u8 *pwd_value)
- {
--      u8 pwd_value[SAE_MAX_ECC_PRIME_LEN];
-       struct crypto_bignum *y_sqr, *x_cand;
-       int res;
-       size_t bits;
--      *ret_x_cand = NULL;
--
-       wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
-       /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
-@@ -286,7 +284,7 @@ static int sae_test_pwd_seed_ecc(struct
-                           prime, sae->tmp->prime_len, pwd_value, bits) < 0)
-               return -1;
-       if (bits % 8)
--              buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
-+              buf_shift_right(pwd_value, sae->tmp->prime_len, 8 - bits % 8);
-       wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
-                       pwd_value, sae->tmp->prime_len);
-@@ -297,20 +295,13 @@ static int sae_test_pwd_seed_ecc(struct
-       if (!x_cand)
-               return -1;
-       y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand);
--      if (!y_sqr) {
--              crypto_bignum_deinit(x_cand, 1);
-+      crypto_bignum_deinit(x_cand, 1);
-+      if (!y_sqr)
-               return -1;
--      }
-       res = is_quadratic_residue_blind(sae, prime, bits, qr, qnr, y_sqr);
-       crypto_bignum_deinit(y_sqr, 1);
--      if (res <= 0) {
--              crypto_bignum_deinit(x_cand, 1);
--              return res;
--      }
--
--      *ret_x_cand = x_cand;
--      return 1;
-+      return res;
- }
-@@ -431,25 +422,30 @@ static int sae_derive_pwe_ecc(struct sae
-       const u8 *addr[3];
-       size_t len[3];
-       size_t num_elem;
--      u8 dummy_password[32];
--      size_t dummy_password_len;
-+      u8 *dummy_password, *tmp_password;
-       int pwd_seed_odd = 0;
-       u8 prime[SAE_MAX_ECC_PRIME_LEN];
-       size_t prime_len;
--      struct crypto_bignum *x = NULL, *qr, *qnr;
-+      struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL;
-+      u8 x_bin[SAE_MAX_ECC_PRIME_LEN];
-+      u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN];
-       size_t bits;
--      int res;
--
--      dummy_password_len = password_len;
--      if (dummy_password_len > sizeof(dummy_password))
--              dummy_password_len = sizeof(dummy_password);
--      if (random_get_bytes(dummy_password, dummy_password_len) < 0)
--              return -1;
-+      int res = -1;
-+      u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
-+                     * mask */
-+
-+      os_memset(x_bin, 0, sizeof(x_bin));
-+
-+      dummy_password = os_malloc(password_len);
-+      tmp_password = os_malloc(password_len);
-+      if (!dummy_password || !tmp_password ||
-+          random_get_bytes(dummy_password, password_len) < 0)
-+              goto fail;
-       prime_len = sae->tmp->prime_len;
-       if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
-                                prime_len) < 0)
--              return -1;
-+              goto fail;
-       bits = crypto_ec_prime_len_bits(sae->tmp->ec);
-       /*
-@@ -458,7 +454,7 @@ static int sae_derive_pwe_ecc(struct sae
-        */
-       if (get_random_qr_qnr(prime, prime_len, sae->tmp->prime, bits,
-                             &qr, &qnr) < 0)
--              return -1;
-+              goto fail;
-       wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
-                             password, password_len);
-@@ -474,7 +470,7 @@ static int sae_derive_pwe_ecc(struct sae
-        */
-       sae_pwd_seed_key(addr1, addr2, addrs);
--      addr[0] = password;
-+      addr[0] = tmp_password;
-       len[0] = password_len;
-       num_elem = 1;
-       if (identifier) {
-@@ -491,9 +487,8 @@ static int sae_derive_pwe_ecc(struct sae
-        * attacks that attempt to determine the number of iterations required
-        * in the loop.
-        */
--      for (counter = 1; counter <= k || !x; counter++) {
-+      for (counter = 1; counter <= k || !found; counter++) {
-               u8 pwd_seed[SHA256_MAC_LEN];
--              struct crypto_bignum *x_cand;
-               if (counter > 200) {
-                       /* This should not happen in practice */
-@@ -501,40 +496,49 @@ static int sae_derive_pwe_ecc(struct sae
-                       break;
-               }
--              wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
-+              wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter);
-+              const_time_select_bin(found, dummy_password, password,
-+                                    password_len, tmp_password);
-               if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
-                                      addr, len, pwd_seed) < 0)
-                       break;
-               res = sae_test_pwd_seed_ecc(sae, pwd_seed,
--                                          prime, qr, qnr, &x_cand);
-+                                          prime, qr, qnr, x_cand_bin);
-+              const_time_select_bin(found, x_bin, x_cand_bin, prime_len,
-+                                    x_bin);
-+              pwd_seed_odd = const_time_select_u8(
-+                      found, pwd_seed_odd,
-+                      pwd_seed[SHA256_MAC_LEN - 1] & 0x01);
-+              os_memset(pwd_seed, 0, sizeof(pwd_seed));
-               if (res < 0)
-                       goto fail;
--              if (res > 0 && !x) {
--                      wpa_printf(MSG_DEBUG,
--                                 "SAE: Selected pwd-seed with counter %u",
--                                 counter);
--                      x = x_cand;
--                      pwd_seed_odd = pwd_seed[SHA256_MAC_LEN - 1] & 0x01;
--                      os_memset(pwd_seed, 0, sizeof(pwd_seed));
--
--                      /*
--                       * Use a dummy password for the following rounds, if
--                       * any.
--                       */
--                      addr[0] = dummy_password;
--                      len[0] = dummy_password_len;
--              } else if (res > 0) {
--                      crypto_bignum_deinit(x_cand, 1);
--              }
-+              /* Need to minimize differences in handling res == 0 and 1 here
-+               * to avoid differences in timing and instruction cache access,
-+               * so use const_time_select_*() to make local copies of the
-+               * values based on whether this loop iteration was the one that
-+               * found the pwd-seed/x. */
-+
-+              /* found is 0 or 0xff here and res is 0 or 1. Bitwise OR of them
-+               * (with res converted to 0/0xff) handles this in constant time.
-+               */
-+              found |= res * 0xff;
-+              wpa_printf(MSG_DEBUG, "SAE: pwd-seed result %d found=0x%02x",
-+                         res, found);
-       }
--      if (!x) {
-+      if (!found) {
-               wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
-               res = -1;
-               goto fail;
-       }
-+      x = crypto_bignum_init_set(x_bin, prime_len);
-+      if (!x) {
-+              res = -1;
-+              goto fail;
-+      }
-+
-       if (!sae->tmp->pwe_ecc)
-               sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec);
-       if (!sae->tmp->pwe_ecc)
-@@ -543,7 +547,6 @@ static int sae_derive_pwe_ecc(struct sae
-               res = crypto_ec_point_solve_y_coord(sae->tmp->ec,
-                                                   sae->tmp->pwe_ecc, x,
-                                                   pwd_seed_odd);
--      crypto_bignum_deinit(x, 1);
-       if (res < 0) {
-               /*
-                * This should not happen since we already checked that there
-@@ -555,6 +558,11 @@ static int sae_derive_pwe_ecc(struct sae
- fail:
-       crypto_bignum_deinit(qr, 0);
-       crypto_bignum_deinit(qnr, 0);
-+      os_free(dummy_password);
-+      bin_clear_free(tmp_password, password_len);
-+      crypto_bignum_deinit(x, 1);
-+      os_memset(x_bin, 0, sizeof(x_bin));
-+      os_memset(x_cand_bin, 0, sizeof(x_cand_bin));
-       return res;
- }