diff options
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.patch | 139 |
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 @@ | |||
1 | From cff138b0747fa39765cbc641b66cfa5d7f1735d1 Mon Sep 17 00:00:00 2001 | ||
2 | From: Jouni Malinen <jouni@codeaurora.org> | ||
3 | Date: Sat, 2 Mar 2019 16:05:56 +0200 | ||
4 | Subject: [PATCH 09/14] SAE: Use constant time operations in | ||
5 | sae_test_pwd_seed_ffc() | ||
6 | |||
7 | Try to avoid showing externally visible timing or memory access | ||
8 | differences regardless of whether the derived pwd-value is smaller than | ||
9 | the group prime. | ||
10 | |||
11 | This is related to CVE-2019-9494. | ||
12 | |||
13 | Signed-off-by: Jouni Malinen <jouni@codeaurora.org> | ||
14 | Signed-off-by: Adrian Bunk <bunk@stusta.de> | ||
15 | Upstream-Status: Backport | ||
16 | CVE: CVE-2019-9494 | ||
17 | --- | ||
18 | src/common/sae.c | 75 ++++++++++++++++++++++++++++++++++---------------------- | ||
19 | 1 file changed, 46 insertions(+), 29 deletions(-) | ||
20 | |||
21 | diff --git a/src/common/sae.c b/src/common/sae.c | ||
22 | index 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 | -- | ||
138 | 2.7.4 | ||
139 | |||