diff options
Diffstat (limited to 'meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0005-SAE-Minimize-timing-differences-in-PWE-derivation.patch')
-rw-r--r-- | meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0005-SAE-Minimize-timing-differences-in-PWE-derivation.patch | 244 |
1 files changed, 0 insertions, 244 deletions
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0005-SAE-Minimize-timing-differences-in-PWE-derivation.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0005-SAE-Minimize-timing-differences-in-PWE-derivation.patch deleted file mode 100644 index 6a567c5fb6..0000000000 --- a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0005-SAE-Minimize-timing-differences-in-PWE-derivation.patch +++ /dev/null @@ -1,244 +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> -Signed-off-by: Adrian Bunk <bunk@stusta.de> -Upstream-Status: Backport -CVE: CVE-2019-9494 ---- - src/common/sae.c | 106 ++++++++++++++++++++++++++++++------------------------- - 1 file changed, 57 insertions(+), 49 deletions(-) - -diff --git a/src/common/sae.c b/src/common/sae.c -index 8129a7c..d55323b 100644 ---- 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" -@@ -292,15 +293,12 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed, - 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) */ -@@ -309,7 +307,7 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed, - 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); - -@@ -320,20 +318,13 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed, - 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; - } - - -@@ -454,25 +445,30 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, - 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; -+ int res = -1; -+ u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_* -+ * mask */ - -- 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; -+ 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); - - /* -@@ -481,7 +477,7 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, - */ - 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); -@@ -497,7 +493,7 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, - */ - sae_pwd_seed_key(addr1, addr2, addrs); - -- addr[0] = password; -+ addr[0] = tmp_password; - len[0] = password_len; - num_elem = 1; - if (identifier) { -@@ -514,9 +510,8 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, - * 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 */ -@@ -524,36 +519,45 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, - 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)); -+ /* 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); -+ } - -- /* -- * 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); -- } -+ 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) { -- wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE"); - res = -1; - goto fail; - } -@@ -566,7 +570,6 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, - 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 -@@ -578,6 +581,11 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, - 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; - } --- -2.7.4 - |