summaryrefslogtreecommitdiffstats
path: root/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0009-SAE-Use-constant-time-operations-in-sae_test_pwd_see.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0009-SAE-Use-constant-time-operations-in-sae_test_pwd_see.patch')
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0009-SAE-Use-constant-time-operations-in-sae_test_pwd_see.patch139
1 files changed, 139 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0009-SAE-Use-constant-time-operations-in-sae_test_pwd_see.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0009-SAE-Use-constant-time-operations-in-sae_test_pwd_see.patch
new file mode 100644
index 0000000000..d2ae8188e1
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0009-SAE-Use-constant-time-operations-in-sae_test_pwd_see.patch
@@ -0,0 +1,139 @@
1From cff138b0747fa39765cbc641b66cfa5d7f1735d1 Mon Sep 17 00:00:00 2001
2From: Jouni Malinen <jouni@codeaurora.org>
3Date: Sat, 2 Mar 2019 16:05:56 +0200
4Subject: [PATCH 09/14] SAE: Use constant time operations in
5 sae_test_pwd_seed_ffc()
6
7Try to avoid showing externally visible timing or memory access
8differences regardless of whether the derived pwd-value is smaller than
9the group prime.
10
11This is related to CVE-2019-9494.
12
13Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
14Signed-off-by: Adrian Bunk <bunk@stusta.de>
15Upstream-Status: Backport
16CVE: CVE-2019-9494
17---
18 src/common/sae.c | 75 ++++++++++++++++++++++++++++++++++----------------------
19 1 file changed, 46 insertions(+), 29 deletions(-)
20
21diff --git a/src/common/sae.c b/src/common/sae.c
22index fa9a145..eaf825d 100644
23--- a/src/common/sae.c
24+++ b/src/common/sae.c
25@@ -334,14 +334,17 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
26 }
27
28
29+/* Returns -1 on fatal failure, 0 if PWE cannot be derived from the provided
30+ * pwd-seed, or 1 if a valid PWE was derived from pwd-seed. */
31 static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
32 struct crypto_bignum *pwe)
33 {
34 u8 pwd_value[SAE_MAX_PRIME_LEN];
35 size_t bits = sae->tmp->prime_len * 8;
36 u8 exp[1];
37- struct crypto_bignum *a, *b;
38- int res;
39+ struct crypto_bignum *a, *b = NULL;
40+ int res, is_val;
41+ u8 pwd_value_valid;
42
43 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
44
45@@ -353,16 +356,29 @@ static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
46 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value,
47 sae->tmp->prime_len);
48
49- if (os_memcmp(pwd_value, sae->tmp->dh->prime, sae->tmp->prime_len) >= 0)
50- {
51- wpa_printf(MSG_DEBUG, "SAE: pwd-value >= p");
52- return 0;
53- }
54+ /* Check whether pwd-value < p */
55+ res = const_time_memcmp(pwd_value, sae->tmp->dh->prime,
56+ sae->tmp->prime_len);
57+ /* pwd-value >= p is invalid, so res is < 0 for the valid cases and
58+ * the negative sign can be used to fill the mask for constant time
59+ * selection */
60+ pwd_value_valid = const_time_fill_msb(res);
61+
62+ /* If pwd-value >= p, force pwd-value to be < p and perform the
63+ * calculations anyway to hide timing difference. The derived PWE will
64+ * be ignored in that case. */
65+ pwd_value[0] = const_time_select_u8(pwd_value_valid, pwd_value[0], 0);
66
67 /* PWE = pwd-value^((p-1)/r) modulo p */
68
69+ res = -1;
70 a = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
71+ if (!a)
72+ goto fail;
73
74+ /* This is an optimization based on the used group that does not depend
75+ * on the password in any way, so it is fine to use separate branches
76+ * for this step without constant time operations. */
77 if (sae->tmp->dh->safe_prime) {
78 /*
79 * r = (p-1)/2 for the group used here, so this becomes:
80@@ -376,33 +392,34 @@ static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
81 b = crypto_bignum_init_set(exp, sizeof(exp));
82 if (b == NULL ||
83 crypto_bignum_sub(sae->tmp->prime, b, b) < 0 ||
84- crypto_bignum_div(b, sae->tmp->order, b) < 0) {
85- crypto_bignum_deinit(b, 0);
86- b = NULL;
87- }
88+ crypto_bignum_div(b, sae->tmp->order, b) < 0)
89+ goto fail;
90 }
91
92- if (a == NULL || b == NULL)
93- res = -1;
94- else
95- res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe);
96-
97- crypto_bignum_deinit(a, 0);
98- crypto_bignum_deinit(b, 0);
99+ if (!b)
100+ goto fail;
101
102- if (res < 0) {
103- wpa_printf(MSG_DEBUG, "SAE: Failed to calculate PWE");
104- return -1;
105- }
106+ res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe);
107+ if (res < 0)
108+ goto fail;
109
110- /* if (PWE > 1) --> found */
111- if (crypto_bignum_is_zero(pwe) || crypto_bignum_is_one(pwe)) {
112- wpa_printf(MSG_DEBUG, "SAE: PWE <= 1");
113- return 0;
114- }
115+ /* There were no fatal errors in calculations, so determine the return
116+ * value using constant time operations. We get here for number of
117+ * invalid cases which are cleared here after having performed all the
118+ * computation. PWE is valid if pwd-value was less than prime and
119+ * PWE > 1. Start with pwd-value check first and then use constant time
120+ * operations to clear res to 0 if PWE is 0 or 1.
121+ */
122+ res = const_time_select_u8(pwd_value_valid, 1, 0);
123+ is_val = crypto_bignum_is_zero(pwe);
124+ res = const_time_select_u8(const_time_is_zero(is_val), res, 0);
125+ is_val = crypto_bignum_is_one(pwe);
126+ res = const_time_select_u8(const_time_is_zero(is_val), res, 0);
127
128- wpa_printf(MSG_DEBUG, "SAE: PWE found");
129- return 1;
130+fail:
131+ crypto_bignum_deinit(a, 1);
132+ crypto_bignum_deinit(b, 1);
133+ return res;
134 }
135
136
137--
1382.7.4
139