summaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
authorAdrian Bunk <bunk@stusta.de>2019-06-19 21:04:22 +0300
committerRichard Purdie <richard.purdie@linuxfoundation.org>2019-06-30 22:34:23 +0100
commitee0e9eaafed96587b6f1c6b995cd7d5927170c21 (patch)
treec3e3b3602923c23aa0614a44b3b4049e6f340dea /meta
parent76c220e5fe43aef1014e6eec7f0136c2b34be308 (diff)
downloadpoky-ee0e9eaafed96587b6f1c6b995cd7d5927170c21.tar.gz
wpa-supplicant: Fix CVE-2019-9494 CVE-2019-9495 CVE-2019-9496 CVE-2019-9497 CVE-2019-9498 CVE-2019-9499 CVE-2019-11555
(From OE-Core rev: ae8e0440fc1177bf44e46804e1f5927cb86f8324) Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Armin Kuster <akuster808@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta')
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0001-EAP-pwd-server-Fix-reassembly-buffer-handling.patch48
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0001-OpenSSL-Use-constant-time-operations-for-private-big.patch97
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0002-Add-helper-functions-for-constant-time-operations.patch222
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0003-EAP-pwd-peer-Fix-reassembly-buffer-handling.patch48
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0003-OpenSSL-Use-constant-time-selection-for-crypto_bignu.patch64
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0004-EAP-pwd-Use-constant-time-and-memory-access-for-find.patch327
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0005-SAE-Minimize-timing-differences-in-PWE-derivation.patch244
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0006-SAE-Avoid-branches-in-is_quadratic_residue_blind.patch147
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0007-SAE-Mask-timing-of-MODP-groups-22-23-24.patch121
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0008-SAE-Use-const_time-selection-for-PWE-in-FFC.patch108
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0009-SAE-Use-constant-time-operations-in-sae_test_pwd_see.patch139
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0010-SAE-Fix-confirm-message-validation-in-error-cases.patch60
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0011-EAP-pwd-server-Verify-received-scalar-and-element.patch61
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0012-EAP-pwd-server-Detect-reflection-attacks.patch48
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0013-EAP-pwd-client-Verify-received-scalar-and-element.patch61
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0014-EAP-pwd-Check-element-x-y-coordinates-explicitly.patch335
-rw-r--r--meta/recipes-connectivity/wpa-supplicant/wpa-supplicant_2.7.bb16
17 files changed, 2146 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0001-EAP-pwd-server-Fix-reassembly-buffer-handling.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0001-EAP-pwd-server-Fix-reassembly-buffer-handling.patch
new file mode 100644
index 0000000000..45e6e87dfe
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0001-EAP-pwd-server-Fix-reassembly-buffer-handling.patch
@@ -0,0 +1,48 @@
1From fe76f487e28bdc61940f304f153a954cf36935ea Mon Sep 17 00:00:00 2001
2From: Jouni Malinen <jouni@codeaurora.org>
3Date: Wed, 17 Apr 2019 01:55:32 +0300
4Subject: [PATCH 1/3] EAP-pwd server: Fix reassembly buffer handling
5
6data->inbuf allocation might fail and if that were to happen, the next
7fragment in the exchange could have resulted in NULL pointer
8dereference. Unexpected fragment with more bit might also be able to
9trigger this. Fix that by explicitly checking for data->inbuf to be
10available before using it.
11
12Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
13Signed-off-by: Adrian Bunk <bunk@stusta.de>
14Upstream-Status: Backport
15CVE: CVE-2019-11555
16---
17 src/eap_server/eap_server_pwd.c | 8 +++++++-
18 1 file changed, 7 insertions(+), 1 deletion(-)
19
20diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c
21index 11bef55..38e2af8 100644
22--- a/src/eap_server/eap_server_pwd.c
23+++ b/src/eap_server/eap_server_pwd.c
24@@ -912,6 +912,12 @@ static void eap_pwd_process(struct eap_sm *sm, void *priv,
25 * the first and all intermediate fragments have the M bit set
26 */
27 if (EAP_PWD_GET_MORE_BIT(lm_exch) || data->in_frag_pos) {
28+ if (!data->inbuf) {
29+ wpa_printf(MSG_DEBUG,
30+ "EAP-pwd: No buffer for reassembly");
31+ eap_pwd_state(data, FAILURE);
32+ return;
33+ }
34 if ((data->in_frag_pos + len) > wpabuf_size(data->inbuf)) {
35 wpa_printf(MSG_DEBUG, "EAP-pwd: Buffer overflow "
36 "attack detected! (%d+%d > %d)",
37@@ -932,7 +938,7 @@ static void eap_pwd_process(struct eap_sm *sm, void *priv,
38 * last fragment won't have the M bit set (but we're obviously
39 * buffering fragments so that's how we know it's the last)
40 */
41- if (data->in_frag_pos) {
42+ if (data->in_frag_pos && data->inbuf) {
43 pos = wpabuf_head_u8(data->inbuf);
44 len = data->in_frag_pos;
45 wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",
46--
472.7.4
48
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0001-OpenSSL-Use-constant-time-operations-for-private-big.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0001-OpenSSL-Use-constant-time-operations-for-private-big.patch
new file mode 100644
index 0000000000..e64d140c7b
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0001-OpenSSL-Use-constant-time-operations-for-private-big.patch
@@ -0,0 +1,97 @@
1From d42c477cc794163a3757956bbffca5cea000923c Mon Sep 17 00:00:00 2001
2From: Jouni Malinen <jouni@codeaurora.org>
3Date: Tue, 26 Feb 2019 11:43:03 +0200
4Subject: [PATCH 01/14] OpenSSL: Use constant time operations for private
5 bignums
6
7This helps in reducing measurable timing differences in operations
8involving private information. BoringSSL has removed BN_FLG_CONSTTIME
9and expects specific constant time functions to be called instead, so a
10bit different approach is needed depending on which library is used.
11
12The main operation that needs protection against side channel attacks is
13BN_mod_exp() that depends on private keys (the public key validation
14step in crypto_dh_derive_secret() is an exception that can use the
15faster version since it does not depend on private keys).
16
17crypto_bignum_div() is currently used only in SAE FFC case with not
18safe-prime groups and only with values that do not depend on private
19keys, so it is not critical to protect it.
20
21crypto_bignum_inverse() is currently used only in SAE FFC PWE
22derivation. The additional protection here is targeting only OpenSSL.
23BoringSSL may need conversion to using BN_mod_inverse_blinded().
24
25This is related to CVE-2019-9494 and CVE-2019-9495.
26
27Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
28Signed-off-by: Adrian Bunk <bunk@stusta.de>
29Upstream-Status: Backport
30CVE: CVE-2019-9494
31CVE: CVE-2019-9495
32---
33 src/crypto/crypto_openssl.c | 20 +++++++++++++++-----
34 1 file changed, 15 insertions(+), 5 deletions(-)
35
36diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
37index 9c2ba58..ac53cc8 100644
38--- a/src/crypto/crypto_openssl.c
39+++ b/src/crypto/crypto_openssl.c
40@@ -607,7 +607,8 @@ int crypto_mod_exp(const u8 *base, size_t base_len,
41 bn_result == NULL)
42 goto error;
43
44- if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1)
45+ if (BN_mod_exp_mont_consttime(bn_result, bn_base, bn_exp, bn_modulus,
46+ ctx, NULL) != 1)
47 goto error;
48
49 *result_len = BN_bn2bin(bn_result, result);
50@@ -1360,8 +1361,9 @@ int crypto_bignum_exptmod(const struct crypto_bignum *a,
51 bnctx = BN_CTX_new();
52 if (bnctx == NULL)
53 return -1;
54- res = BN_mod_exp((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,
55- (const BIGNUM *) c, bnctx);
56+ res = BN_mod_exp_mont_consttime((BIGNUM *) d, (const BIGNUM *) a,
57+ (const BIGNUM *) b, (const BIGNUM *) c,
58+ bnctx, NULL);
59 BN_CTX_free(bnctx);
60
61 return res ? 0 : -1;
62@@ -1380,6 +1382,11 @@ int crypto_bignum_inverse(const struct crypto_bignum *a,
63 bnctx = BN_CTX_new();
64 if (bnctx == NULL)
65 return -1;
66+#ifdef OPENSSL_IS_BORINGSSL
67+ /* TODO: use BN_mod_inverse_blinded() ? */
68+#else /* OPENSSL_IS_BORINGSSL */
69+ BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME);
70+#endif /* OPENSSL_IS_BORINGSSL */
71 res = BN_mod_inverse((BIGNUM *) c, (const BIGNUM *) a,
72 (const BIGNUM *) b, bnctx);
73 BN_CTX_free(bnctx);
74@@ -1413,6 +1420,9 @@ int crypto_bignum_div(const struct crypto_bignum *a,
75 bnctx = BN_CTX_new();
76 if (bnctx == NULL)
77 return -1;
78+#ifndef OPENSSL_IS_BORINGSSL
79+ BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME);
80+#endif /* OPENSSL_IS_BORINGSSL */
81 res = BN_div((BIGNUM *) c, NULL, (const BIGNUM *) a,
82 (const BIGNUM *) b, bnctx);
83 BN_CTX_free(bnctx);
84@@ -1504,8 +1514,8 @@ int crypto_bignum_legendre(const struct crypto_bignum *a,
85 /* exp = (p-1) / 2 */
86 !BN_sub(exp, (const BIGNUM *) p, BN_value_one()) ||
87 !BN_rshift1(exp, exp) ||
88- !BN_mod_exp(tmp, (const BIGNUM *) a, exp, (const BIGNUM *) p,
89- bnctx))
90+ !BN_mod_exp_mont_consttime(tmp, (const BIGNUM *) a, exp,
91+ (const BIGNUM *) p, bnctx, NULL))
92 goto fail;
93
94 if (BN_is_word(tmp, 1))
95--
962.7.4
97
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0002-Add-helper-functions-for-constant-time-operations.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0002-Add-helper-functions-for-constant-time-operations.patch
new file mode 100644
index 0000000000..fd6f2ce158
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0002-Add-helper-functions-for-constant-time-operations.patch
@@ -0,0 +1,222 @@
1From 6e34f618d37ddbb5854c42e2ad4fca83492fa7b7 Mon Sep 17 00:00:00 2001
2From: Jouni Malinen <jouni@codeaurora.org>
3Date: Wed, 27 Feb 2019 18:38:30 +0200
4Subject: [PATCH 02/14] Add helper functions for constant time operations
5
6These functions can be used to help implement constant time operations
7for various cryptographic operations that must minimize externally
8observable differences in processing (both in timing and also in
9internal cache use, etc.).
10
11This is related to CVE-2019-9494 and CVE-2019-9495.
12
13Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
14Signed-off-by: Adrian Bunk <bunk@stusta.de>
15Upstream-Status: Backport
16CVE: CVE-2019-9494
17CVE: CVE-2019-9495
18---
19 src/utils/const_time.h | 191 +++++++++++++++++++++++++++++++++++++++++++++++++
20 1 file changed, 191 insertions(+)
21 create mode 100644 src/utils/const_time.h
22
23diff --git a/src/utils/const_time.h b/src/utils/const_time.h
24new file mode 100644
25index 0000000..ab8f611
26--- /dev/null
27+++ b/src/utils/const_time.h
28@@ -0,0 +1,191 @@
29+/*
30+ * Helper functions for constant time operations
31+ * Copyright (c) 2019, The Linux Foundation
32+ *
33+ * This software may be distributed under the terms of the BSD license.
34+ * See README for more details.
35+ *
36+ * These helper functions can be used to implement logic that needs to minimize
37+ * externally visible differences in execution path by avoiding use of branches,
38+ * avoiding early termination or other time differences, and forcing same memory
39+ * access pattern regardless of values.
40+ */
41+
42+#ifndef CONST_TIME_H
43+#define CONST_TIME_H
44+
45+
46+#if defined(__clang__)
47+#define NO_UBSAN_UINT_OVERFLOW \
48+ __attribute__((no_sanitize("unsigned-integer-overflow")))
49+#else
50+#define NO_UBSAN_UINT_OVERFLOW
51+#endif
52+
53+
54+/**
55+ * const_time_fill_msb - Fill all bits with MSB value
56+ * @val: Input value
57+ * Returns: Value with all the bits set to the MSB of the input val
58+ */
59+static inline unsigned int const_time_fill_msb(unsigned int val)
60+{
61+ /* Move the MSB to LSB and multiple by -1 to fill in all bits. */
62+ return (val >> (sizeof(val) * 8 - 1)) * ~0U;
63+}
64+
65+
66+/* Returns: -1 if val is zero; 0 if val is not zero */
67+static inline unsigned int const_time_is_zero(unsigned int val)
68+ NO_UBSAN_UINT_OVERFLOW
69+{
70+ /* Set MSB to 1 for 0 and fill rest of bits with the MSB value */
71+ return const_time_fill_msb(~val & (val - 1));
72+}
73+
74+
75+/* Returns: -1 if a == b; 0 if a != b */
76+static inline unsigned int const_time_eq(unsigned int a, unsigned int b)
77+{
78+ return const_time_is_zero(a ^ b);
79+}
80+
81+
82+/* Returns: -1 if a == b; 0 if a != b */
83+static inline u8 const_time_eq_u8(unsigned int a, unsigned int b)
84+{
85+ return (u8) const_time_eq(a, b);
86+}
87+
88+
89+/**
90+ * const_time_eq_bin - Constant time memory comparison
91+ * @a: First buffer to compare
92+ * @b: Second buffer to compare
93+ * @len: Number of octets to compare
94+ * Returns: -1 if buffers are equal, 0 if not
95+ *
96+ * This function is meant for comparing passwords or hash values where
97+ * difference in execution time or memory access pattern could provide external
98+ * observer information about the location of the difference in the memory
99+ * buffers. The return value does not behave like memcmp(), i.e.,
100+ * const_time_eq_bin() cannot be used to sort items into a defined order. Unlike
101+ * memcmp(), the execution time of const_time_eq_bin() does not depend on the
102+ * contents of the compared memory buffers, but only on the total compared
103+ * length.
104+ */
105+static inline unsigned int const_time_eq_bin(const void *a, const void *b,
106+ size_t len)
107+{
108+ const u8 *aa = a;
109+ const u8 *bb = b;
110+ size_t i;
111+ u8 res = 0;
112+
113+ for (i = 0; i < len; i++)
114+ res |= aa[i] ^ bb[i];
115+
116+ return const_time_is_zero(res);
117+}
118+
119+
120+/**
121+ * const_time_select - Constant time unsigned int selection
122+ * @mask: 0 (false) or -1 (true) to identify which value to select
123+ * @true_val: Value to select for the true case
124+ * @false_val: Value to select for the false case
125+ * Returns: true_val if mask == -1, false_val if mask == 0
126+ */
127+static inline unsigned int const_time_select(unsigned int mask,
128+ unsigned int true_val,
129+ unsigned int false_val)
130+{
131+ return (mask & true_val) | (~mask & false_val);
132+}
133+
134+
135+/**
136+ * const_time_select_int - Constant time int selection
137+ * @mask: 0 (false) or -1 (true) to identify which value to select
138+ * @true_val: Value to select for the true case
139+ * @false_val: Value to select for the false case
140+ * Returns: true_val if mask == -1, false_val if mask == 0
141+ */
142+static inline int const_time_select_int(unsigned int mask, int true_val,
143+ int false_val)
144+{
145+ return (int) const_time_select(mask, (unsigned int) true_val,
146+ (unsigned int) false_val);
147+}
148+
149+
150+/**
151+ * const_time_select_u8 - Constant time u8 selection
152+ * @mask: 0 (false) or -1 (true) to identify which value to select
153+ * @true_val: Value to select for the true case
154+ * @false_val: Value to select for the false case
155+ * Returns: true_val if mask == -1, false_val if mask == 0
156+ */
157+static inline u8 const_time_select_u8(u8 mask, u8 true_val, u8 false_val)
158+{
159+ return (u8) const_time_select(mask, true_val, false_val);
160+}
161+
162+
163+/**
164+ * const_time_select_s8 - Constant time s8 selection
165+ * @mask: 0 (false) or -1 (true) to identify which value to select
166+ * @true_val: Value to select for the true case
167+ * @false_val: Value to select for the false case
168+ * Returns: true_val if mask == -1, false_val if mask == 0
169+ */
170+static inline s8 const_time_select_s8(u8 mask, s8 true_val, s8 false_val)
171+{
172+ return (s8) const_time_select(mask, (unsigned int) true_val,
173+ (unsigned int) false_val);
174+}
175+
176+
177+/**
178+ * const_time_select_bin - Constant time binary buffer selection copy
179+ * @mask: 0 (false) or -1 (true) to identify which value to copy
180+ * @true_val: Buffer to copy for the true case
181+ * @false_val: Buffer to copy for the false case
182+ * @len: Number of octets to copy
183+ * @dst: Destination buffer for the copy
184+ *
185+ * This function copies the specified buffer into the destination buffer using
186+ * operations with identical memory access pattern regardless of which buffer
187+ * is being copied.
188+ */
189+static inline void const_time_select_bin(u8 mask, const u8 *true_val,
190+ const u8 *false_val, size_t len,
191+ u8 *dst)
192+{
193+ size_t i;
194+
195+ for (i = 0; i < len; i++)
196+ dst[i] = const_time_select_u8(mask, true_val[i], false_val[i]);
197+}
198+
199+
200+static inline int const_time_memcmp(const void *a, const void *b, size_t len)
201+{
202+ const u8 *aa = a;
203+ const u8 *bb = b;
204+ int diff, res = 0;
205+ unsigned int mask;
206+
207+ if (len == 0)
208+ return 0;
209+ do {
210+ len--;
211+ diff = (int) aa[len] - (int) bb[len];
212+ mask = const_time_is_zero((unsigned int) diff);
213+ res = const_time_select_int(mask, res, diff);
214+ } while (len);
215+
216+ return res;
217+}
218+
219+#endif /* CONST_TIME_H */
220--
2212.7.4
222
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0003-EAP-pwd-peer-Fix-reassembly-buffer-handling.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0003-EAP-pwd-peer-Fix-reassembly-buffer-handling.patch
new file mode 100644
index 0000000000..95ea809ef2
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0003-EAP-pwd-peer-Fix-reassembly-buffer-handling.patch
@@ -0,0 +1,48 @@
1From d2d1a324ce937628e4d9d9999fe113819b7d4478 Mon Sep 17 00:00:00 2001
2From: Jouni Malinen <jouni@codeaurora.org>
3Date: Wed, 17 Apr 2019 02:21:20 +0300
4Subject: [PATCH 3/3] EAP-pwd peer: Fix reassembly buffer handling
5
6Unexpected fragment might result in data->inbuf not being allocated
7before processing and that could have resulted in NULL pointer
8dereference. Fix that by explicitly checking for data->inbuf to be
9available before using it.
10
11Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
12Signed-off-by: Adrian Bunk <bunk@stusta.de>
13Upstream-Status: Backport
14CVE: CVE-2019-11555
15---
16 src/eap_peer/eap_pwd.c | 9 ++++++++-
17 1 file changed, 8 insertions(+), 1 deletion(-)
18
19diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
20index 46894a5..76fcad4 100644
21--- a/src/eap_peer/eap_pwd.c
22+++ b/src/eap_peer/eap_pwd.c
23@@ -932,6 +932,13 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret,
24 * buffer and ACK the fragment
25 */
26 if (EAP_PWD_GET_MORE_BIT(lm_exch) || data->in_frag_pos) {
27+ if (!data->inbuf) {
28+ wpa_printf(MSG_DEBUG,
29+ "EAP-pwd: No buffer for reassembly");
30+ ret->methodState = METHOD_DONE;
31+ ret->decision = DECISION_FAIL;
32+ return NULL;
33+ }
34 data->in_frag_pos += len;
35 if (data->in_frag_pos > wpabuf_size(data->inbuf)) {
36 wpa_printf(MSG_INFO, "EAP-pwd: Buffer overflow attack "
37@@ -958,7 +965,7 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret,
38 /*
39 * we're buffering and this is the last fragment
40 */
41- if (data->in_frag_pos) {
42+ if (data->in_frag_pos && data->inbuf) {
43 wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",
44 (int) len);
45 pos = wpabuf_head_u8(data->inbuf);
46--
472.7.4
48
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0003-OpenSSL-Use-constant-time-selection-for-crypto_bignu.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0003-OpenSSL-Use-constant-time-selection-for-crypto_bignu.patch
new file mode 100644
index 0000000000..790041f259
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0003-OpenSSL-Use-constant-time-selection-for-crypto_bignu.patch
@@ -0,0 +1,64 @@
1From c93461c1d98f52681717a088776ab32fd97872b0 Mon Sep 17 00:00:00 2001
2From: Jouni Malinen <jouni@codeaurora.org>
3Date: Fri, 8 Mar 2019 00:24:12 +0200
4Subject: [PATCH 03/14] OpenSSL: Use constant time selection for
5 crypto_bignum_legendre()
6
7Get rid of the branches that depend on the result of the Legendre
8operation. This is needed to avoid leaking information about different
9temporary results in blinding mechanisms.
10
11This is related to CVE-2019-9494 and CVE-2019-9495.
12
13Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
14Signed-off-by: Adrian Bunk <bunk@stusta.de>
15Upstream-Status: Backport
16CVE: CVE-2019-9494
17CVE: CVE-2019-9495
18---
19 src/crypto/crypto_openssl.c | 15 +++++++++------
20 1 file changed, 9 insertions(+), 6 deletions(-)
21
22diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
23index ac53cc8..0f52101 100644
24--- a/src/crypto/crypto_openssl.c
25+++ b/src/crypto/crypto_openssl.c
26@@ -24,6 +24,7 @@
27 #endif /* CONFIG_ECC */
28
29 #include "common.h"
30+#include "utils/const_time.h"
31 #include "wpabuf.h"
32 #include "dh_group5.h"
33 #include "sha1.h"
34@@ -1500,6 +1501,7 @@ int crypto_bignum_legendre(const struct crypto_bignum *a,
35 BN_CTX *bnctx;
36 BIGNUM *exp = NULL, *tmp = NULL;
37 int res = -2;
38+ unsigned int mask;
39
40 if (TEST_FAIL())
41 return -2;
42@@ -1518,12 +1520,13 @@ int crypto_bignum_legendre(const struct crypto_bignum *a,
43 (const BIGNUM *) p, bnctx, NULL))
44 goto fail;
45
46- if (BN_is_word(tmp, 1))
47- res = 1;
48- else if (BN_is_zero(tmp))
49- res = 0;
50- else
51- res = -1;
52+ /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need to use
53+ * constant time selection to avoid branches here. */
54+ res = -1;
55+ mask = const_time_eq(BN_is_word(tmp, 1), 1);
56+ res = const_time_select_int(mask, 1, res);
57+ mask = const_time_eq(BN_is_zero(tmp), 1);
58+ res = const_time_select_int(mask, 0, res);
59
60 fail:
61 BN_clear_free(tmp);
62--
632.7.4
64
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0004-EAP-pwd-Use-constant-time-and-memory-access-for-find.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0004-EAP-pwd-Use-constant-time-and-memory-access-for-find.patch
new file mode 100644
index 0000000000..471380c443
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0004-EAP-pwd-Use-constant-time-and-memory-access-for-find.patch
@@ -0,0 +1,327 @@
1From aaf65feac67c3993935634eefe5bc76b9fce03aa Mon Sep 17 00:00:00 2001
2From: Jouni Malinen <jouni@codeaurora.org>
3Date: Tue, 26 Feb 2019 11:59:45 +0200
4Subject: [PATCH 04/14] EAP-pwd: Use constant time and memory access for
5 finding the PWE
6
7This algorithm could leak information to external observers in form of
8timing differences or memory access patterns (cache use). While the
9previous implementation had protection against the most visible timing
10differences (looping 40 rounds and masking the legendre operation), it
11did not protect against memory access patterns between the two possible
12code paths in the masking operations. That might be sufficient to allow
13an unprivileged process running on the same device to be able to
14determine which path is being executed through a cache attack and based
15on that, determine information about the used password.
16
17Convert the PWE finding loop to use constant time functions and
18identical memory access path without different branches for the QR/QNR
19cases to minimize possible side-channel information similarly to the
20changes done for SAE authentication. (CVE-2019-9495)
21
22Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
23Signed-off-by: Adrian Bunk <bunk@stusta.de>
24Upstream-Status: Backport
25CVE: CVE-2019-9495
26---
27 src/eap_common/eap_pwd_common.c | 187 +++++++++++++++++++++-------------------
28 1 file changed, 99 insertions(+), 88 deletions(-)
29
30diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
31index 02fe01e..e49aaf8 100644
32--- a/src/eap_common/eap_pwd_common.c
33+++ b/src/eap_common/eap_pwd_common.c
34@@ -8,11 +8,15 @@
35
36 #include "includes.h"
37 #include "common.h"
38+#include "utils/const_time.h"
39 #include "crypto/sha256.h"
40 #include "crypto/crypto.h"
41 #include "eap_defs.h"
42 #include "eap_pwd_common.h"
43
44+#define MAX_ECC_PRIME_LEN 66
45+
46+
47 /* The random function H(x) = HMAC-SHA256(0^32, x) */
48 struct crypto_hash * eap_pwd_h_init(void)
49 {
50@@ -102,6 +106,15 @@ EAP_PWD_group * get_eap_pwd_group(u16 num)
51 }
52
53
54+static void buf_shift_right(u8 *buf, size_t len, size_t bits)
55+{
56+ size_t i;
57+ for (i = len - 1; i > 0; i--)
58+ buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits);
59+ buf[0] >>= bits;
60+}
61+
62+
63 /*
64 * compute a "random" secret point on an elliptic curve based
65 * on the password and identities.
66@@ -113,17 +126,27 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
67 const u8 *token)
68 {
69 struct crypto_bignum *qr = NULL, *qnr = NULL, *one = NULL;
70+ struct crypto_bignum *qr_or_qnr = NULL;
71+ u8 qr_bin[MAX_ECC_PRIME_LEN];
72+ u8 qnr_bin[MAX_ECC_PRIME_LEN];
73+ u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN];
74+ u8 x_bin[MAX_ECC_PRIME_LEN];
75 struct crypto_bignum *tmp1 = NULL, *tmp2 = NULL, *pm1 = NULL;
76 struct crypto_hash *hash;
77 unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr;
78- int is_odd, ret = 0, check, found = 0;
79- size_t primebytelen, primebitlen;
80- struct crypto_bignum *x_candidate = NULL, *rnd = NULL, *cofactor = NULL;
81+ int ret = 0, check, res;
82+ u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
83+ * mask */
84+ size_t primebytelen = 0, primebitlen;
85+ struct crypto_bignum *x_candidate = NULL, *cofactor = NULL;
86 const struct crypto_bignum *prime;
87+ u8 mask, found_ctr = 0, is_odd = 0;
88
89 if (grp->pwe)
90 return -1;
91
92+ os_memset(x_bin, 0, sizeof(x_bin));
93+
94 prime = crypto_ec_get_prime(grp->group);
95 cofactor = crypto_bignum_init();
96 grp->pwe = crypto_ec_point_init(grp->group);
97@@ -152,8 +175,6 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
98
99 /* get a random quadratic residue and nonresidue */
100 while (!qr || !qnr) {
101- int res;
102-
103 if (crypto_bignum_rand(tmp1, prime) < 0)
104 goto fail;
105 res = crypto_bignum_legendre(tmp1, prime);
106@@ -167,6 +188,11 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
107 if (!tmp1)
108 goto fail;
109 }
110+ if (crypto_bignum_to_bin(qr, qr_bin, sizeof(qr_bin),
111+ primebytelen) < 0 ||
112+ crypto_bignum_to_bin(qnr, qnr_bin, sizeof(qnr_bin),
113+ primebytelen) < 0)
114+ goto fail;
115
116 os_memset(prfbuf, 0, primebytelen);
117 ctr = 0;
118@@ -194,17 +220,16 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
119 eap_pwd_h_update(hash, &ctr, sizeof(ctr));
120 eap_pwd_h_final(hash, pwe_digest);
121
122- crypto_bignum_deinit(rnd, 1);
123- rnd = crypto_bignum_init_set(pwe_digest, SHA256_MAC_LEN);
124- if (!rnd) {
125- wpa_printf(MSG_INFO, "EAP-pwd: unable to create rnd");
126- goto fail;
127- }
128+ is_odd = const_time_select_u8(
129+ found, is_odd, pwe_digest[SHA256_MAC_LEN - 1] & 0x01);
130 if (eap_pwd_kdf(pwe_digest, SHA256_MAC_LEN,
131 (u8 *) "EAP-pwd Hunting And Pecking",
132 os_strlen("EAP-pwd Hunting And Pecking"),
133 prfbuf, primebitlen) < 0)
134 goto fail;
135+ if (primebitlen % 8)
136+ buf_shift_right(prfbuf, primebytelen,
137+ 8 - primebitlen % 8);
138
139 crypto_bignum_deinit(x_candidate, 1);
140 x_candidate = crypto_bignum_init_set(prfbuf, primebytelen);
141@@ -214,24 +239,13 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
142 goto fail;
143 }
144
145- /*
146- * eap_pwd_kdf() returns a string of bits 0..primebitlen but
147- * BN_bin2bn will treat that string of bits as a big endian
148- * number. If the primebitlen is not an even multiple of 8
149- * then excessive bits-- those _after_ primebitlen-- so now
150- * we have to shift right the amount we masked off.
151- */
152- if ((primebitlen % 8) &&
153- crypto_bignum_rshift(x_candidate,
154- (8 - (primebitlen % 8)),
155- x_candidate) < 0)
156- goto fail;
157-
158 if (crypto_bignum_cmp(x_candidate, prime) >= 0)
159 continue;
160
161- wpa_hexdump(MSG_DEBUG, "EAP-pwd: x_candidate",
162- prfbuf, primebytelen);
163+ wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: x_candidate",
164+ prfbuf, primebytelen);
165+ const_time_select_bin(found, x_bin, prfbuf, primebytelen,
166+ x_bin);
167
168 /*
169 * compute y^2 using the equation of the curve
170@@ -261,13 +275,15 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
171 * Flip a coin, multiply by the random quadratic residue or the
172 * random quadratic nonresidue and record heads or tails.
173 */
174- if (crypto_bignum_is_odd(tmp1)) {
175- crypto_bignum_mulmod(tmp2, qr, prime, tmp2);
176- check = 1;
177- } else {
178- crypto_bignum_mulmod(tmp2, qnr, prime, tmp2);
179- check = -1;
180- }
181+ mask = const_time_eq_u8(crypto_bignum_is_odd(tmp1), 1);
182+ check = const_time_select_s8(mask, 1, -1);
183+ const_time_select_bin(mask, qr_bin, qnr_bin, primebytelen,
184+ qr_or_qnr_bin);
185+ crypto_bignum_deinit(qr_or_qnr, 1);
186+ qr_or_qnr = crypto_bignum_init_set(qr_or_qnr_bin, primebytelen);
187+ if (!qr_or_qnr ||
188+ crypto_bignum_mulmod(tmp2, qr_or_qnr, prime, tmp2) < 0)
189+ goto fail;
190
191 /*
192 * Now it's safe to do legendre, if check is 1 then it's
193@@ -275,59 +291,12 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
194 * change result), if check is -1 then it's the opposite test
195 * (multiplying a qr by qnr would make a qnr).
196 */
197- if (crypto_bignum_legendre(tmp2, prime) == check) {
198- if (found == 1)
199- continue;
200-
201- /* need to unambiguously identify the solution */
202- is_odd = crypto_bignum_is_odd(rnd);
203-
204- /*
205- * We know x_candidate is a quadratic residue so set
206- * it here.
207- */
208- if (crypto_ec_point_solve_y_coord(grp->group, grp->pwe,
209- x_candidate,
210- is_odd) != 0) {
211- wpa_printf(MSG_INFO,
212- "EAP-pwd: Could not solve for y");
213- continue;
214- }
215-
216- /*
217- * If there's a solution to the equation then the point
218- * must be on the curve so why check again explicitly?
219- * OpenSSL code says this is required by X9.62. We're
220- * not X9.62 but it can't hurt just to be sure.
221- */
222- if (!crypto_ec_point_is_on_curve(grp->group,
223- grp->pwe)) {
224- wpa_printf(MSG_INFO,
225- "EAP-pwd: point is not on curve");
226- continue;
227- }
228-
229- if (!crypto_bignum_is_one(cofactor)) {
230- /* make sure the point is not in a small
231- * sub-group */
232- if (crypto_ec_point_mul(grp->group, grp->pwe,
233- cofactor,
234- grp->pwe) != 0) {
235- wpa_printf(MSG_INFO,
236- "EAP-pwd: cannot multiply generator by order");
237- continue;
238- }
239- if (crypto_ec_point_is_at_infinity(grp->group,
240- grp->pwe)) {
241- wpa_printf(MSG_INFO,
242- "EAP-pwd: point is at infinity");
243- continue;
244- }
245- }
246- wpa_printf(MSG_DEBUG,
247- "EAP-pwd: found a PWE in %d tries", ctr);
248- found = 1;
249- }
250+ res = crypto_bignum_legendre(tmp2, prime);
251+ if (res == -2)
252+ goto fail;
253+ mask = const_time_eq(res, check);
254+ found_ctr = const_time_select_u8(found, found_ctr, ctr);
255+ found |= mask;
256 }
257 if (found == 0) {
258 wpa_printf(MSG_INFO,
259@@ -335,6 +304,44 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
260 num);
261 goto fail;
262 }
263+
264+ /*
265+ * We know x_candidate is a quadratic residue so set it here.
266+ */
267+ crypto_bignum_deinit(x_candidate, 1);
268+ x_candidate = crypto_bignum_init_set(x_bin, primebytelen);
269+ if (!x_candidate ||
270+ crypto_ec_point_solve_y_coord(grp->group, grp->pwe, x_candidate,
271+ is_odd) != 0) {
272+ wpa_printf(MSG_INFO, "EAP-pwd: Could not solve for y");
273+ goto fail;
274+ }
275+
276+ /*
277+ * If there's a solution to the equation then the point must be on the
278+ * curve so why check again explicitly? OpenSSL code says this is
279+ * required by X9.62. We're not X9.62 but it can't hurt just to be sure.
280+ */
281+ if (!crypto_ec_point_is_on_curve(grp->group, grp->pwe)) {
282+ wpa_printf(MSG_INFO, "EAP-pwd: point is not on curve");
283+ goto fail;
284+ }
285+
286+ if (!crypto_bignum_is_one(cofactor)) {
287+ /* make sure the point is not in a small sub-group */
288+ if (crypto_ec_point_mul(grp->group, grp->pwe, cofactor,
289+ grp->pwe) != 0) {
290+ wpa_printf(MSG_INFO,
291+ "EAP-pwd: cannot multiply generator by order");
292+ goto fail;
293+ }
294+ if (crypto_ec_point_is_at_infinity(grp->group, grp->pwe)) {
295+ wpa_printf(MSG_INFO, "EAP-pwd: point is at infinity");
296+ goto fail;
297+ }
298+ }
299+ wpa_printf(MSG_DEBUG, "EAP-pwd: found a PWE in %02d tries", found_ctr);
300+
301 if (0) {
302 fail:
303 crypto_ec_point_deinit(grp->pwe, 1);
304@@ -344,14 +351,18 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
305 /* cleanliness and order.... */
306 crypto_bignum_deinit(cofactor, 1);
307 crypto_bignum_deinit(x_candidate, 1);
308- crypto_bignum_deinit(rnd, 1);
309 crypto_bignum_deinit(pm1, 0);
310 crypto_bignum_deinit(tmp1, 1);
311 crypto_bignum_deinit(tmp2, 1);
312 crypto_bignum_deinit(qr, 1);
313 crypto_bignum_deinit(qnr, 1);
314+ crypto_bignum_deinit(qr_or_qnr, 1);
315 crypto_bignum_deinit(one, 0);
316- os_free(prfbuf);
317+ bin_clear_free(prfbuf, primebytelen);
318+ os_memset(qr_bin, 0, sizeof(qr_bin));
319+ os_memset(qnr_bin, 0, sizeof(qnr_bin));
320+ os_memset(qr_or_qnr_bin, 0, sizeof(qr_or_qnr_bin));
321+ os_memset(pwe_digest, 0, sizeof(pwe_digest));
322
323 return ret;
324 }
325--
3262.7.4
327
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
new file mode 100644
index 0000000000..6a567c5fb6
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0005-SAE-Minimize-timing-differences-in-PWE-derivation.patch
@@ -0,0 +1,244 @@
1From 6513db3e96c43c2e36805cf5ead349765d18eaf7 Mon Sep 17 00:00:00 2001
2From: Jouni Malinen <jouni@codeaurora.org>
3Date: Tue, 26 Feb 2019 13:05:09 +0200
4Subject: [PATCH 05/14] SAE: Minimize timing differences in PWE derivation
5
6The QR test result can provide information about the password to an
7attacker, so try to minimize differences in how the
8sae_test_pwd_seed_ecc() result is used. (CVE-2019-9494)
9
10Use heap memory for the dummy password to allow the same password length
11to be used even with long passwords.
12
13Use constant time selection functions to track the real vs. dummy
14variables so that the exact same operations can be performed for both QR
15test results.
16
17Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
18Signed-off-by: Adrian Bunk <bunk@stusta.de>
19Upstream-Status: Backport
20CVE: CVE-2019-9494
21---
22 src/common/sae.c | 106 ++++++++++++++++++++++++++++++-------------------------
23 1 file changed, 57 insertions(+), 49 deletions(-)
24
25diff --git a/src/common/sae.c b/src/common/sae.c
26index 8129a7c..d55323b 100644
27--- a/src/common/sae.c
28+++ b/src/common/sae.c
29@@ -9,6 +9,7 @@
30 #include "includes.h"
31
32 #include "common.h"
33+#include "utils/const_time.h"
34 #include "crypto/crypto.h"
35 #include "crypto/sha256.h"
36 #include "crypto/random.h"
37@@ -292,15 +293,12 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
38 const u8 *prime,
39 const struct crypto_bignum *qr,
40 const struct crypto_bignum *qnr,
41- struct crypto_bignum **ret_x_cand)
42+ u8 *pwd_value)
43 {
44- u8 pwd_value[SAE_MAX_ECC_PRIME_LEN];
45 struct crypto_bignum *y_sqr, *x_cand;
46 int res;
47 size_t bits;
48
49- *ret_x_cand = NULL;
50-
51 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
52
53 /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
54@@ -309,7 +307,7 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
55 prime, sae->tmp->prime_len, pwd_value, bits) < 0)
56 return -1;
57 if (bits % 8)
58- buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
59+ buf_shift_right(pwd_value, sae->tmp->prime_len, 8 - bits % 8);
60 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
61 pwd_value, sae->tmp->prime_len);
62
63@@ -320,20 +318,13 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
64 if (!x_cand)
65 return -1;
66 y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand);
67- if (!y_sqr) {
68- crypto_bignum_deinit(x_cand, 1);
69+ crypto_bignum_deinit(x_cand, 1);
70+ if (!y_sqr)
71 return -1;
72- }
73
74 res = is_quadratic_residue_blind(sae, prime, bits, qr, qnr, y_sqr);
75 crypto_bignum_deinit(y_sqr, 1);
76- if (res <= 0) {
77- crypto_bignum_deinit(x_cand, 1);
78- return res;
79- }
80-
81- *ret_x_cand = x_cand;
82- return 1;
83+ return res;
84 }
85
86
87@@ -454,25 +445,30 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
88 const u8 *addr[3];
89 size_t len[3];
90 size_t num_elem;
91- u8 dummy_password[32];
92- size_t dummy_password_len;
93+ u8 *dummy_password, *tmp_password;
94 int pwd_seed_odd = 0;
95 u8 prime[SAE_MAX_ECC_PRIME_LEN];
96 size_t prime_len;
97- struct crypto_bignum *x = NULL, *qr, *qnr;
98+ struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL;
99+ u8 x_bin[SAE_MAX_ECC_PRIME_LEN];
100+ u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN];
101 size_t bits;
102- int res;
103+ int res = -1;
104+ u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
105+ * mask */
106
107- dummy_password_len = password_len;
108- if (dummy_password_len > sizeof(dummy_password))
109- dummy_password_len = sizeof(dummy_password);
110- if (random_get_bytes(dummy_password, dummy_password_len) < 0)
111- return -1;
112+ os_memset(x_bin, 0, sizeof(x_bin));
113+
114+ dummy_password = os_malloc(password_len);
115+ tmp_password = os_malloc(password_len);
116+ if (!dummy_password || !tmp_password ||
117+ random_get_bytes(dummy_password, password_len) < 0)
118+ goto fail;
119
120 prime_len = sae->tmp->prime_len;
121 if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
122 prime_len) < 0)
123- return -1;
124+ goto fail;
125 bits = crypto_ec_prime_len_bits(sae->tmp->ec);
126
127 /*
128@@ -481,7 +477,7 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
129 */
130 if (get_random_qr_qnr(prime, prime_len, sae->tmp->prime, bits,
131 &qr, &qnr) < 0)
132- return -1;
133+ goto fail;
134
135 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
136 password, password_len);
137@@ -497,7 +493,7 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
138 */
139 sae_pwd_seed_key(addr1, addr2, addrs);
140
141- addr[0] = password;
142+ addr[0] = tmp_password;
143 len[0] = password_len;
144 num_elem = 1;
145 if (identifier) {
146@@ -514,9 +510,8 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
147 * attacks that attempt to determine the number of iterations required
148 * in the loop.
149 */
150- for (counter = 1; counter <= k || !x; counter++) {
151+ for (counter = 1; counter <= k || !found; counter++) {
152 u8 pwd_seed[SHA256_MAC_LEN];
153- struct crypto_bignum *x_cand;
154
155 if (counter > 200) {
156 /* This should not happen in practice */
157@@ -524,36 +519,45 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
158 break;
159 }
160
161- wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
162+ wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter);
163+ const_time_select_bin(found, dummy_password, password,
164+ password_len, tmp_password);
165 if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
166 addr, len, pwd_seed) < 0)
167 break;
168
169 res = sae_test_pwd_seed_ecc(sae, pwd_seed,
170- prime, qr, qnr, &x_cand);
171+ prime, qr, qnr, x_cand_bin);
172+ const_time_select_bin(found, x_bin, x_cand_bin, prime_len,
173+ x_bin);
174+ pwd_seed_odd = const_time_select_u8(
175+ found, pwd_seed_odd,
176+ pwd_seed[SHA256_MAC_LEN - 1] & 0x01);
177+ os_memset(pwd_seed, 0, sizeof(pwd_seed));
178 if (res < 0)
179 goto fail;
180- if (res > 0 && !x) {
181- wpa_printf(MSG_DEBUG,
182- "SAE: Selected pwd-seed with counter %u",
183- counter);
184- x = x_cand;
185- pwd_seed_odd = pwd_seed[SHA256_MAC_LEN - 1] & 0x01;
186- os_memset(pwd_seed, 0, sizeof(pwd_seed));
187+ /* Need to minimize differences in handling res == 0 and 1 here
188+ * to avoid differences in timing and instruction cache access,
189+ * so use const_time_select_*() to make local copies of the
190+ * values based on whether this loop iteration was the one that
191+ * found the pwd-seed/x. */
192+
193+ /* found is 0 or 0xff here and res is 0 or 1. Bitwise OR of them
194+ * (with res converted to 0/0xff) handles this in constant time.
195+ */
196+ found |= res * 0xff;
197+ wpa_printf(MSG_DEBUG, "SAE: pwd-seed result %d found=0x%02x",
198+ res, found);
199+ }
200
201- /*
202- * Use a dummy password for the following rounds, if
203- * any.
204- */
205- addr[0] = dummy_password;
206- len[0] = dummy_password_len;
207- } else if (res > 0) {
208- crypto_bignum_deinit(x_cand, 1);
209- }
210+ if (!found) {
211+ wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
212+ res = -1;
213+ goto fail;
214 }
215
216+ x = crypto_bignum_init_set(x_bin, prime_len);
217 if (!x) {
218- wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
219 res = -1;
220 goto fail;
221 }
222@@ -566,7 +570,6 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
223 res = crypto_ec_point_solve_y_coord(sae->tmp->ec,
224 sae->tmp->pwe_ecc, x,
225 pwd_seed_odd);
226- crypto_bignum_deinit(x, 1);
227 if (res < 0) {
228 /*
229 * This should not happen since we already checked that there
230@@ -578,6 +581,11 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
231 fail:
232 crypto_bignum_deinit(qr, 0);
233 crypto_bignum_deinit(qnr, 0);
234+ os_free(dummy_password);
235+ bin_clear_free(tmp_password, password_len);
236+ crypto_bignum_deinit(x, 1);
237+ os_memset(x_bin, 0, sizeof(x_bin));
238+ os_memset(x_cand_bin, 0, sizeof(x_cand_bin));
239
240 return res;
241 }
242--
2432.7.4
244
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0006-SAE-Avoid-branches-in-is_quadratic_residue_blind.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0006-SAE-Avoid-branches-in-is_quadratic_residue_blind.patch
new file mode 100644
index 0000000000..5209559659
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0006-SAE-Avoid-branches-in-is_quadratic_residue_blind.patch
@@ -0,0 +1,147 @@
1From 362704dda04507e7ebb8035122e83d9f0ae7c320 Mon Sep 17 00:00:00 2001
2From: Jouni Malinen <jouni@codeaurora.org>
3Date: Tue, 26 Feb 2019 19:34:38 +0200
4Subject: [PATCH 06/14] SAE: Avoid branches in is_quadratic_residue_blind()
5
6Make the non-failure path in the function proceed without branches based
7on r_odd and in constant time to minimize risk of observable differences
8in timing or cache use. (CVE-2019-9494)
9
10Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
11Signed-off-by: Adrian Bunk <bunk@stusta.de>
12Upstream-Status: Backport
13CVE: CVE-2019-9494
14---
15 src/common/sae.c | 64 ++++++++++++++++++++++++++++++++------------------------
16 1 file changed, 37 insertions(+), 27 deletions(-)
17
18diff --git a/src/common/sae.c b/src/common/sae.c
19index d55323b..5df9b95 100644
20--- a/src/common/sae.c
21+++ b/src/common/sae.c
22@@ -232,12 +232,14 @@ get_rand_1_to_p_1(const u8 *prime, size_t prime_len, size_t prime_bits,
23
24 static int is_quadratic_residue_blind(struct sae_data *sae,
25 const u8 *prime, size_t bits,
26- const struct crypto_bignum *qr,
27- const struct crypto_bignum *qnr,
28+ const u8 *qr, const u8 *qnr,
29 const struct crypto_bignum *y_sqr)
30 {
31- struct crypto_bignum *r, *num;
32+ struct crypto_bignum *r, *num, *qr_or_qnr = NULL;
33 int r_odd, check, res = -1;
34+ u8 qr_or_qnr_bin[SAE_MAX_ECC_PRIME_LEN];
35+ size_t prime_len = sae->tmp->prime_len;
36+ unsigned int mask;
37
38 /*
39 * Use the blinding technique to mask y_sqr while determining
40@@ -248,7 +250,7 @@ static int is_quadratic_residue_blind(struct sae_data *sae,
41 * r = a random number between 1 and p-1, inclusive
42 * num = (v * r * r) modulo p
43 */
44- r = get_rand_1_to_p_1(prime, sae->tmp->prime_len, bits, &r_odd);
45+ r = get_rand_1_to_p_1(prime, prime_len, bits, &r_odd);
46 if (!r)
47 return -1;
48
49@@ -258,41 +260,45 @@ static int is_quadratic_residue_blind(struct sae_data *sae,
50 crypto_bignum_mulmod(num, r, sae->tmp->prime, num) < 0)
51 goto fail;
52
53- if (r_odd) {
54- /*
55- * num = (num * qr) module p
56- * LGR(num, p) = 1 ==> quadratic residue
57- */
58- if (crypto_bignum_mulmod(num, qr, sae->tmp->prime, num) < 0)
59- goto fail;
60- check = 1;
61- } else {
62- /*
63- * num = (num * qnr) module p
64- * LGR(num, p) = -1 ==> quadratic residue
65- */
66- if (crypto_bignum_mulmod(num, qnr, sae->tmp->prime, num) < 0)
67- goto fail;
68- check = -1;
69- }
70+ /*
71+ * Need to minimize differences in handling different cases, so try to
72+ * avoid branches and timing differences.
73+ *
74+ * If r_odd:
75+ * num = (num * qr) module p
76+ * LGR(num, p) = 1 ==> quadratic residue
77+ * else:
78+ * num = (num * qnr) module p
79+ * LGR(num, p) = -1 ==> quadratic residue
80+ */
81+ mask = const_time_is_zero(r_odd);
82+ const_time_select_bin(mask, qnr, qr, prime_len, qr_or_qnr_bin);
83+ qr_or_qnr = crypto_bignum_init_set(qr_or_qnr_bin, prime_len);
84+ if (!qr_or_qnr ||
85+ crypto_bignum_mulmod(num, qr_or_qnr, sae->tmp->prime, num) < 0)
86+ goto fail;
87+ /* r_odd is 0 or 1; branchless version of check = r_odd ? 1 : -1, */
88+ check = const_time_select_int(mask, -1, 1);
89
90 res = crypto_bignum_legendre(num, sae->tmp->prime);
91 if (res == -2) {
92 res = -1;
93 goto fail;
94 }
95- res = res == check;
96+ /* branchless version of res = res == check
97+ * (res is -1, 0, or 1; check is -1 or 1) */
98+ mask = const_time_eq(res, check);
99+ res = const_time_select_int(mask, 1, 0);
100 fail:
101 crypto_bignum_deinit(num, 1);
102 crypto_bignum_deinit(r, 1);
103+ crypto_bignum_deinit(qr_or_qnr, 1);
104 return res;
105 }
106
107
108 static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
109- const u8 *prime,
110- const struct crypto_bignum *qr,
111- const struct crypto_bignum *qnr,
112+ const u8 *prime, const u8 *qr, const u8 *qnr,
113 u8 *pwd_value)
114 {
115 struct crypto_bignum *y_sqr, *x_cand;
116@@ -452,6 +458,8 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
117 struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL;
118 u8 x_bin[SAE_MAX_ECC_PRIME_LEN];
119 u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN];
120+ u8 qr_bin[SAE_MAX_ECC_PRIME_LEN];
121+ u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN];
122 size_t bits;
123 int res = -1;
124 u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
125@@ -476,7 +484,9 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
126 * (qnr) modulo p for blinding purposes during the loop.
127 */
128 if (get_random_qr_qnr(prime, prime_len, sae->tmp->prime, bits,
129- &qr, &qnr) < 0)
130+ &qr, &qnr) < 0 ||
131+ crypto_bignum_to_bin(qr, qr_bin, sizeof(qr_bin), prime_len) < 0 ||
132+ crypto_bignum_to_bin(qnr, qnr_bin, sizeof(qnr_bin), prime_len) < 0)
133 goto fail;
134
135 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
136@@ -527,7 +537,7 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
137 break;
138
139 res = sae_test_pwd_seed_ecc(sae, pwd_seed,
140- prime, qr, qnr, x_cand_bin);
141+ prime, qr_bin, qnr_bin, x_cand_bin);
142 const_time_select_bin(found, x_bin, x_cand_bin, prime_len,
143 x_bin);
144 pwd_seed_odd = const_time_select_u8(
145--
1462.7.4
147
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0007-SAE-Mask-timing-of-MODP-groups-22-23-24.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0007-SAE-Mask-timing-of-MODP-groups-22-23-24.patch
new file mode 100644
index 0000000000..6cfa7220e1
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0007-SAE-Mask-timing-of-MODP-groups-22-23-24.patch
@@ -0,0 +1,121 @@
1From 90839597cc4016b33f00055b12d59174c62770a3 Mon Sep 17 00:00:00 2001
2From: Jouni Malinen <jouni@codeaurora.org>
3Date: Sat, 2 Mar 2019 12:24:09 +0200
4Subject: [PATCH 07/14] SAE: Mask timing of MODP groups 22, 23, 24
5
6These groups have significant probability of coming up with pwd-value
7that is equal or greater than the prime and as such, need for going
8through the PWE derivation loop multiple times. This can result in
9sufficient timing different to allow an external observer to determine
10how many rounds are needed and that can leak information about the used
11password.
12
13Force at least 40 loop rounds for these MODP groups similarly to the ECC
14group design to mask timing. This behavior is not described in IEEE Std
15802.11-2016 for SAE, but it does not result in different values (i.e.,
16only different timing), so such implementation specific countermeasures
17can be done without breaking interoperability with other implementation.
18
19Note: These MODP groups 22, 23, and 24 are not considered sufficiently
20strong to be used with SAE (or more or less anything else). As such,
21they should never be enabled in runtime configuration for any production
22use cases. These changes to introduce additional protection to mask
23timing is only for completeness of implementation and not an indication
24that these groups should be used.
25
26This is related to CVE-2019-9494.
27
28Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
29Signed-off-by: Adrian Bunk <bunk@stusta.de>
30Upstream-Status: Backport
31CVE: CVE-2019-9494
32---
33 src/common/sae.c | 38 ++++++++++++++++++++++++++++----------
34 1 file changed, 28 insertions(+), 10 deletions(-)
35
36diff --git a/src/common/sae.c b/src/common/sae.c
37index 5df9b95..75b1b4a 100644
38--- a/src/common/sae.c
39+++ b/src/common/sae.c
40@@ -601,22 +601,27 @@ fail:
41 }
42
43
44+static int sae_modp_group_require_masking(int group)
45+{
46+ /* Groups for which pwd-value is likely to be >= p frequently */
47+ return group == 22 || group == 23 || group == 24;
48+}
49+
50+
51 static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
52 const u8 *addr2, const u8 *password,
53 size_t password_len, const char *identifier)
54 {
55- u8 counter;
56+ u8 counter, k;
57 u8 addrs[2 * ETH_ALEN];
58 const u8 *addr[3];
59 size_t len[3];
60 size_t num_elem;
61 int found = 0;
62+ struct crypto_bignum *pwe = NULL;
63
64- if (sae->tmp->pwe_ffc == NULL) {
65- sae->tmp->pwe_ffc = crypto_bignum_init();
66- if (sae->tmp->pwe_ffc == NULL)
67- return -1;
68- }
69+ crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
70+ sae->tmp->pwe_ffc = NULL;
71
72 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
73 password, password_len);
74@@ -640,7 +645,9 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
75 len[num_elem] = sizeof(counter);
76 num_elem++;
77
78- for (counter = 1; !found; counter++) {
79+ k = sae_modp_group_require_masking(sae->group) ? 40 : 1;
80+
81+ for (counter = 1; counter <= k || !found; counter++) {
82 u8 pwd_seed[SHA256_MAC_LEN];
83 int res;
84
85@@ -650,19 +657,30 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
86 break;
87 }
88
89- wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
90+ wpa_printf(MSG_DEBUG, "SAE: counter = %02u", counter);
91 if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
92 addr, len, pwd_seed) < 0)
93 break;
94- res = sae_test_pwd_seed_ffc(sae, pwd_seed, sae->tmp->pwe_ffc);
95+ if (!pwe) {
96+ pwe = crypto_bignum_init();
97+ if (!pwe)
98+ break;
99+ }
100+ res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
101 if (res < 0)
102 break;
103 if (res > 0) {
104- wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
105 found = 1;
106+ if (!sae->tmp->pwe_ffc) {
107+ wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
108+ sae->tmp->pwe_ffc = pwe;
109+ pwe = NULL;
110+ }
111 }
112 }
113
114+ crypto_bignum_deinit(pwe, 1);
115+
116 return found ? 0 : -1;
117 }
118
119--
1202.7.4
121
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0008-SAE-Use-const_time-selection-for-PWE-in-FFC.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0008-SAE-Use-const_time-selection-for-PWE-in-FFC.patch
new file mode 100644
index 0000000000..7b8616a66d
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0008-SAE-Use-const_time-selection-for-PWE-in-FFC.patch
@@ -0,0 +1,108 @@
1From f8f20717f87eff1f025f48ed585c7684debacf72 Mon Sep 17 00:00:00 2001
2From: Jouni Malinen <jouni@codeaurora.org>
3Date: Sat, 2 Mar 2019 12:45:33 +0200
4Subject: [PATCH 08/14] SAE: Use const_time selection for PWE in FFC
5
6This is an initial step towards making the FFC case use strictly
7constant time operations similarly to the ECC case.
8sae_test_pwd_seed_ffc() does not yet have constant time behavior,
9though.
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 | 53 +++++++++++++++++++++++++++++++++++------------------
19 1 file changed, 35 insertions(+), 18 deletions(-)
20
21diff --git a/src/common/sae.c b/src/common/sae.c
22index 75b1b4a..fa9a145 100644
23--- a/src/common/sae.c
24+++ b/src/common/sae.c
25@@ -612,17 +612,28 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
26 const u8 *addr2, const u8 *password,
27 size_t password_len, const char *identifier)
28 {
29- u8 counter, k;
30+ u8 counter, k, sel_counter = 0;
31 u8 addrs[2 * ETH_ALEN];
32 const u8 *addr[3];
33 size_t len[3];
34 size_t num_elem;
35- int found = 0;
36- struct crypto_bignum *pwe = NULL;
37+ u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
38+ * mask */
39+ u8 mask;
40+ struct crypto_bignum *pwe;
41+ size_t prime_len = sae->tmp->prime_len * 8;
42+ u8 *pwe_buf;
43
44 crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
45 sae->tmp->pwe_ffc = NULL;
46
47+ /* Allocate a buffer to maintain selected and candidate PWE for constant
48+ * time selection. */
49+ pwe_buf = os_zalloc(prime_len * 2);
50+ pwe = crypto_bignum_init();
51+ if (!pwe_buf || !pwe)
52+ goto fail;
53+
54 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
55 password, password_len);
56
57@@ -661,27 +672,33 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
58 if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
59 addr, len, pwd_seed) < 0)
60 break;
61- if (!pwe) {
62- pwe = crypto_bignum_init();
63- if (!pwe)
64- break;
65- }
66 res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
67+ /* res is -1 for fatal failure, 0 if a valid PWE was not found,
68+ * or 1 if a valid PWE was found. */
69 if (res < 0)
70 break;
71- if (res > 0) {
72- found = 1;
73- if (!sae->tmp->pwe_ffc) {
74- wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
75- sae->tmp->pwe_ffc = pwe;
76- pwe = NULL;
77- }
78- }
79+ /* Store the candidate PWE into the second half of pwe_buf and
80+ * the selected PWE in the beginning of pwe_buf using constant
81+ * time selection. */
82+ if (crypto_bignum_to_bin(pwe, pwe_buf + prime_len, prime_len,
83+ prime_len) < 0)
84+ break;
85+ const_time_select_bin(found, pwe_buf, pwe_buf + prime_len,
86+ prime_len, pwe_buf);
87+ sel_counter = const_time_select_u8(found, sel_counter, counter);
88+ mask = const_time_eq_u8(res, 1);
89+ found = const_time_select_u8(found, found, mask);
90 }
91
92- crypto_bignum_deinit(pwe, 1);
93+ if (!found)
94+ goto fail;
95
96- return found ? 0 : -1;
97+ wpa_printf(MSG_DEBUG, "SAE: Use PWE from counter = %02u", sel_counter);
98+ sae->tmp->pwe_ffc = crypto_bignum_init_set(pwe_buf, prime_len);
99+fail:
100+ crypto_bignum_deinit(pwe, 1);
101+ bin_clear_free(pwe_buf, prime_len * 2);
102+ return sae->tmp->pwe_ffc ? 0 : -1;
103 }
104
105
106--
1072.7.4
108
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
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0010-SAE-Fix-confirm-message-validation-in-error-cases.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0010-SAE-Fix-confirm-message-validation-in-error-cases.patch
new file mode 100644
index 0000000000..9d2c6983d4
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0010-SAE-Fix-confirm-message-validation-in-error-cases.patch
@@ -0,0 +1,60 @@
1From ac8fa9ef198640086cf2ce7c94673be2b6a018a0 Mon Sep 17 00:00:00 2001
2From: Jouni Malinen <jouni@codeaurora.org>
3Date: Tue, 5 Mar 2019 23:43:25 +0200
4Subject: [PATCH 10/14] SAE: Fix confirm message validation in error cases
5
6Explicitly verify that own and peer commit scalar/element are available
7when trying to check SAE confirm message. It could have been possible to
8hit a NULL pointer dereference if the peer element could not have been
9parsed. (CVE-2019-9496)
10
11Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
12Signed-off-by: Adrian Bunk <bunk@stusta.de>
13Upstream-Status: Backport
14CVE: CVE-2019-9496
15---
16 src/common/sae.c | 14 +++++++++++---
17 1 file changed, 11 insertions(+), 3 deletions(-)
18
19diff --git a/src/common/sae.c b/src/common/sae.c
20index eaf825d..5a50294 100644
21--- a/src/common/sae.c
22+++ b/src/common/sae.c
23@@ -1487,23 +1487,31 @@ int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
24
25 wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data));
26
27- if (sae->tmp == NULL) {
28+ if (!sae->tmp || !sae->peer_commit_scalar ||
29+ !sae->tmp->own_commit_scalar) {
30 wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available");
31 return -1;
32 }
33
34- if (sae->tmp->ec)
35+ if (sae->tmp->ec) {
36+ if (!sae->tmp->peer_commit_element_ecc ||
37+ !sae->tmp->own_commit_element_ecc)
38+ return -1;
39 sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar,
40 sae->tmp->peer_commit_element_ecc,
41 sae->tmp->own_commit_scalar,
42 sae->tmp->own_commit_element_ecc,
43 verifier);
44- else
45+ } else {
46+ if (!sae->tmp->peer_commit_element_ffc ||
47+ !sae->tmp->own_commit_element_ffc)
48+ return -1;
49 sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar,
50 sae->tmp->peer_commit_element_ffc,
51 sae->tmp->own_commit_scalar,
52 sae->tmp->own_commit_element_ffc,
53 verifier);
54+ }
55
56 if (os_memcmp_const(verifier, data + 2, SHA256_MAC_LEN) != 0) {
57 wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
58--
592.7.4
60
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0011-EAP-pwd-server-Verify-received-scalar-and-element.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0011-EAP-pwd-server-Verify-received-scalar-and-element.patch
new file mode 100644
index 0000000000..87095bf7f4
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0011-EAP-pwd-server-Verify-received-scalar-and-element.patch
@@ -0,0 +1,61 @@
1From 70ff850e89fbc8bc7da515321b4d15b5eef70581 Mon Sep 17 00:00:00 2001
2From: Mathy Vanhoef <mathy.vanhoef@nyu.edu>
3Date: Sun, 31 Mar 2019 17:13:06 +0200
4Subject: [PATCH 11/14] EAP-pwd server: Verify received scalar and element
5
6When processing an EAP-pwd Commit frame, the peer's scalar and element
7(elliptic curve point) were not validated. This allowed an adversary to
8bypass authentication, and impersonate any user if the crypto
9implementation did not verify the validity of the EC point.
10
11Fix this vulnerability by assuring the received scalar lies within the
12valid range, and by checking that the received element is not the point
13at infinity and lies on the elliptic curve being used. (CVE-2019-9498)
14
15The vulnerability is only exploitable if OpenSSL version 1.0.2 or lower
16is used, or if LibreSSL or wolfssl is used. Newer versions of OpenSSL
17(and also BoringSSL) implicitly validate the elliptic curve point in
18EC_POINT_set_affine_coordinates_GFp(), preventing the attack.
19
20Signed-off-by: Mathy Vanhoef <mathy.vanhoef@nyu.edu>
21Signed-off-by: Adrian Bunk <bunk@stusta.de>
22Upstream-Status: Backport
23CVE: CVE-2019-9498
24---
25 src/eap_server/eap_server_pwd.c | 20 ++++++++++++++++++++
26 1 file changed, 20 insertions(+)
27
28diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c
29index d0fa54a..74979da 100644
30--- a/src/eap_server/eap_server_pwd.c
31+++ b/src/eap_server/eap_server_pwd.c
32@@ -718,6 +718,26 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
33 goto fin;
34 }
35
36+ /* verify received scalar */
37+ if (crypto_bignum_is_zero(data->peer_scalar) ||
38+ crypto_bignum_is_one(data->peer_scalar) ||
39+ crypto_bignum_cmp(data->peer_scalar,
40+ crypto_ec_get_order(data->grp->group)) >= 0) {
41+ wpa_printf(MSG_INFO,
42+ "EAP-PWD (server): received scalar is invalid");
43+ goto fin;
44+ }
45+
46+ /* verify received element */
47+ if (!crypto_ec_point_is_on_curve(data->grp->group,
48+ data->peer_element) ||
49+ crypto_ec_point_is_at_infinity(data->grp->group,
50+ data->peer_element)) {
51+ wpa_printf(MSG_INFO,
52+ "EAP-PWD (server): received element is invalid");
53+ goto fin;
54+ }
55+
56 /* check to ensure peer's element is not in a small sub-group */
57 if (!crypto_bignum_is_one(cofactor)) {
58 if (crypto_ec_point_mul(data->grp->group, data->peer_element,
59--
602.7.4
61
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0012-EAP-pwd-server-Detect-reflection-attacks.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0012-EAP-pwd-server-Detect-reflection-attacks.patch
new file mode 100644
index 0000000000..32d134db41
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0012-EAP-pwd-server-Detect-reflection-attacks.patch
@@ -0,0 +1,48 @@
1From d63edfa90243e9a7de6ae5c275032f2cc79fef95 Mon Sep 17 00:00:00 2001
2From: Mathy Vanhoef <mathy.vanhoef@nyu.edu>
3Date: Sun, 31 Mar 2019 17:26:01 +0200
4Subject: [PATCH 12/14] EAP-pwd server: Detect reflection attacks
5
6When processing an EAP-pwd Commit frame, verify that the peer's scalar
7and elliptic curve element differ from the one sent by the server. This
8prevents reflection attacks where the adversary reflects the scalar and
9element sent by the server. (CVE-2019-9497)
10
11The vulnerability allows an adversary to complete the EAP-pwd handshake
12as any user. However, the adversary does not learn the negotiated
13session key, meaning the subsequent 4-way handshake would fail. As a
14result, this cannot be abused to bypass authentication unless EAP-pwd is
15used in non-WLAN cases without any following key exchange that would
16require the attacker to learn the MSK.
17
18Signed-off-by: Mathy Vanhoef <mathy.vanhoef@nyu.edu>
19Signed-off-by: Adrian Bunk <bunk@stusta.de>
20Upstream-Status: Backport
21CVE: CVE-2019-9497
22---
23 src/eap_server/eap_server_pwd.c | 9 +++++++++
24 1 file changed, 9 insertions(+)
25
26diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c
27index 74979da..16057e9 100644
28--- a/src/eap_server/eap_server_pwd.c
29+++ b/src/eap_server/eap_server_pwd.c
30@@ -753,6 +753,15 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
31 }
32 }
33
34+ /* detect reflection attacks */
35+ if (crypto_bignum_cmp(data->my_scalar, data->peer_scalar) == 0 ||
36+ crypto_ec_point_cmp(data->grp->group, data->my_element,
37+ data->peer_element) == 0) {
38+ wpa_printf(MSG_INFO,
39+ "EAP-PWD (server): detected reflection attack!");
40+ goto fin;
41+ }
42+
43 /* compute the shared key, k */
44 if ((crypto_ec_point_mul(data->grp->group, data->grp->pwe,
45 data->peer_scalar, K) < 0) ||
46--
472.7.4
48
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0013-EAP-pwd-client-Verify-received-scalar-and-element.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0013-EAP-pwd-client-Verify-received-scalar-and-element.patch
new file mode 100644
index 0000000000..c6e61cb803
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0013-EAP-pwd-client-Verify-received-scalar-and-element.patch
@@ -0,0 +1,61 @@
1From 8ad8585f91823ddcc3728155e288e0f9f872e31a Mon Sep 17 00:00:00 2001
2From: Mathy Vanhoef <mathy.vanhoef@nyu.edu>
3Date: Sun, 31 Mar 2019 17:43:44 +0200
4Subject: [PATCH 13/14] EAP-pwd client: Verify received scalar and element
5
6When processing an EAP-pwd Commit frame, the server's scalar and element
7(elliptic curve point) were not validated. This allowed an adversary to
8bypass authentication, and act as a rogue Access Point (AP) if the
9crypto implementation did not verify the validity of the EC point.
10
11Fix this vulnerability by assuring the received scalar lies within the
12valid range, and by checking that the received element is not the point
13at infinity and lies on the elliptic curve being used. (CVE-2019-9499)
14
15The vulnerability is only exploitable if OpenSSL version 1.0.2 or lower
16is used, or if LibreSSL or wolfssl is used. Newer versions of OpenSSL
17(and also BoringSSL) implicitly validate the elliptic curve point in
18EC_POINT_set_affine_coordinates_GFp(), preventing the attack.
19
20Signed-off-by: Mathy Vanhoef <mathy.vanhoef@nyu.edu>
21Signed-off-by: Adrian Bunk <bunk@stusta.de>
22Upstream-Status: Backport
23CVE: CVE-2019-9499
24---
25 src/eap_peer/eap_pwd.c | 20 ++++++++++++++++++++
26 1 file changed, 20 insertions(+)
27
28diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
29index 761c16a..5a05e54 100644
30--- a/src/eap_peer/eap_pwd.c
31+++ b/src/eap_peer/eap_pwd.c
32@@ -594,6 +594,26 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
33 goto fin;
34 }
35
36+ /* verify received scalar */
37+ if (crypto_bignum_is_zero(data->server_scalar) ||
38+ crypto_bignum_is_one(data->server_scalar) ||
39+ crypto_bignum_cmp(data->server_scalar,
40+ crypto_ec_get_order(data->grp->group)) >= 0) {
41+ wpa_printf(MSG_INFO,
42+ "EAP-PWD (peer): received scalar is invalid");
43+ goto fin;
44+ }
45+
46+ /* verify received element */
47+ if (!crypto_ec_point_is_on_curve(data->grp->group,
48+ data->server_element) ||
49+ crypto_ec_point_is_at_infinity(data->grp->group,
50+ data->server_element)) {
51+ wpa_printf(MSG_INFO,
52+ "EAP-PWD (peer): received element is invalid");
53+ goto fin;
54+ }
55+
56 /* check to ensure server's element is not in a small sub-group */
57 if (!crypto_bignum_is_one(cofactor)) {
58 if (crypto_ec_point_mul(data->grp->group, data->server_element,
59--
602.7.4
61
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0014-EAP-pwd-Check-element-x-y-coordinates-explicitly.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0014-EAP-pwd-Check-element-x-y-coordinates-explicitly.patch
new file mode 100644
index 0000000000..e944ef110f
--- /dev/null
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0014-EAP-pwd-Check-element-x-y-coordinates-explicitly.patch
@@ -0,0 +1,335 @@
1From 16d4f1069118aa19bfce013493e1ac5783f92f1d Mon Sep 17 00:00:00 2001
2From: Jouni Malinen <jouni@codeaurora.org>
3Date: Fri, 5 Apr 2019 02:12:50 +0300
4Subject: [PATCH 14/14] EAP-pwd: Check element x,y coordinates explicitly
5
6This adds an explicit check for 0 < x,y < prime based on RFC 5931,
72.8.5.2.2 requirement. The earlier checks might have covered this
8implicitly, but it is safer to avoid any dependency on implicit checks
9and specific crypto library behavior. (CVE-2019-9498 and CVE-2019-9499)
10
11Furthermore, this moves the EAP-pwd element and scalar parsing and
12validation steps into shared helper functions so that there is no need
13to maintain two separate copies of this common functionality between the
14server and peer implementations.
15
16Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
17Signed-off-by: Adrian Bunk <bunk@stusta.de>
18Upstream-Status: Backport
19CVE: CVE-2019-9498
20CVE: CVE-2019-9499
21---
22 src/eap_common/eap_pwd_common.c | 106 ++++++++++++++++++++++++++++++++++++++++
23 src/eap_common/eap_pwd_common.h | 3 ++
24 src/eap_peer/eap_pwd.c | 45 ++---------------
25 src/eap_server/eap_server_pwd.c | 45 ++---------------
26 4 files changed, 117 insertions(+), 82 deletions(-)
27
28diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
29index e49aaf8..c28b56d 100644
30--- a/src/eap_common/eap_pwd_common.c
31+++ b/src/eap_common/eap_pwd_common.c
32@@ -428,3 +428,109 @@ int compute_keys(EAP_PWD_group *grp, const struct crypto_bignum *k,
33
34 return 1;
35 }
36+
37+
38+static int eap_pwd_element_coord_ok(const struct crypto_bignum *prime,
39+ const u8 *buf, size_t len)
40+{
41+ struct crypto_bignum *val;
42+ int ok = 1;
43+
44+ val = crypto_bignum_init_set(buf, len);
45+ if (!val || crypto_bignum_is_zero(val) ||
46+ crypto_bignum_cmp(val, prime) >= 0)
47+ ok = 0;
48+ crypto_bignum_deinit(val, 0);
49+ return ok;
50+}
51+
52+
53+struct crypto_ec_point * eap_pwd_get_element(EAP_PWD_group *group,
54+ const u8 *buf)
55+{
56+ struct crypto_ec_point *element;
57+ const struct crypto_bignum *prime;
58+ size_t prime_len;
59+ struct crypto_bignum *cofactor = NULL;
60+
61+ prime = crypto_ec_get_prime(group->group);
62+ prime_len = crypto_ec_prime_len(group->group);
63+
64+ /* RFC 5931, 2.8.5.2.2: 0 < x,y < p */
65+ if (!eap_pwd_element_coord_ok(prime, buf, prime_len) ||
66+ !eap_pwd_element_coord_ok(prime, buf + prime_len, prime_len)) {
67+ wpa_printf(MSG_INFO, "EAP-pwd: Invalid coordinate in element");
68+ return NULL;
69+ }
70+
71+ element = crypto_ec_point_from_bin(group->group, buf);
72+ if (!element) {
73+ wpa_printf(MSG_INFO, "EAP-pwd: EC point from element failed");
74+ return NULL;
75+ }
76+
77+ /* RFC 5931, 2.8.5.2.2: on curve and not the point at infinity */
78+ if (!crypto_ec_point_is_on_curve(group->group, element) ||
79+ crypto_ec_point_is_at_infinity(group->group, element)) {
80+ wpa_printf(MSG_INFO, "EAP-pwd: Invalid element");
81+ goto fail;
82+ }
83+
84+ cofactor = crypto_bignum_init();
85+ if (!cofactor || crypto_ec_cofactor(group->group, cofactor) < 0) {
86+ wpa_printf(MSG_INFO,
87+ "EAP-pwd: Unable to get cofactor for curve");
88+ goto fail;
89+ }
90+
91+ if (!crypto_bignum_is_one(cofactor)) {
92+ struct crypto_ec_point *point;
93+ int ok = 1;
94+
95+ /* check to ensure peer's element is not in a small sub-group */
96+ point = crypto_ec_point_init(group->group);
97+ if (!point ||
98+ crypto_ec_point_mul(group->group, element,
99+ cofactor, point) != 0 ||
100+ crypto_ec_point_is_at_infinity(group->group, point))
101+ ok = 0;
102+ crypto_ec_point_deinit(point, 0);
103+
104+ if (!ok) {
105+ wpa_printf(MSG_INFO,
106+ "EAP-pwd: Small sub-group check on peer element failed");
107+ goto fail;
108+ }
109+ }
110+
111+out:
112+ crypto_bignum_deinit(cofactor, 0);
113+ return element;
114+fail:
115+ crypto_ec_point_deinit(element, 0);
116+ element = NULL;
117+ goto out;
118+}
119+
120+
121+struct crypto_bignum * eap_pwd_get_scalar(EAP_PWD_group *group, const u8 *buf)
122+{
123+ struct crypto_bignum *scalar;
124+ const struct crypto_bignum *order;
125+ size_t order_len;
126+
127+ order = crypto_ec_get_order(group->group);
128+ order_len = crypto_ec_order_len(group->group);
129+
130+ /* RFC 5931, 2.8.5.2: 1 < scalar < r */
131+ scalar = crypto_bignum_init_set(buf, order_len);
132+ if (!scalar || crypto_bignum_is_zero(scalar) ||
133+ crypto_bignum_is_one(scalar) ||
134+ crypto_bignum_cmp(scalar, order) >= 0) {
135+ wpa_printf(MSG_INFO, "EAP-pwd: received scalar is invalid");
136+ crypto_bignum_deinit(scalar, 0);
137+ scalar = NULL;
138+ }
139+
140+ return scalar;
141+}
142diff --git a/src/eap_common/eap_pwd_common.h b/src/eap_common/eap_pwd_common.h
143index 6b07cf8..2387e59 100644
144--- a/src/eap_common/eap_pwd_common.h
145+++ b/src/eap_common/eap_pwd_common.h
146@@ -67,5 +67,8 @@ int compute_keys(EAP_PWD_group *grp, const struct crypto_bignum *k,
147 struct crypto_hash * eap_pwd_h_init(void);
148 void eap_pwd_h_update(struct crypto_hash *hash, const u8 *data, size_t len);
149 void eap_pwd_h_final(struct crypto_hash *hash, u8 *digest);
150+struct crypto_ec_point * eap_pwd_get_element(EAP_PWD_group *group,
151+ const u8 *buf);
152+struct crypto_bignum * eap_pwd_get_scalar(EAP_PWD_group *group, const u8 *buf);
153
154 #endif /* EAP_PWD_COMMON_H */
155diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
156index 5a05e54..f37b974 100644
157--- a/src/eap_peer/eap_pwd.c
158+++ b/src/eap_peer/eap_pwd.c
159@@ -308,7 +308,7 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
160 const struct wpabuf *reqData,
161 const u8 *payload, size_t payload_len)
162 {
163- struct crypto_ec_point *K = NULL, *point = NULL;
164+ struct crypto_ec_point *K = NULL;
165 struct crypto_bignum *mask = NULL, *cofactor = NULL;
166 const u8 *ptr = payload;
167 u8 *scalar = NULL, *element = NULL;
168@@ -572,63 +572,27 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
169 /* process the request */
170 data->k = crypto_bignum_init();
171 K = crypto_ec_point_init(data->grp->group);
172- point = crypto_ec_point_init(data->grp->group);
173- if (!data->k || !K || !point) {
174+ if (!data->k || !K) {
175 wpa_printf(MSG_INFO, "EAP-PWD (peer): peer data allocation "
176 "fail");
177 goto fin;
178 }
179
180 /* element, x then y, followed by scalar */
181- data->server_element = crypto_ec_point_from_bin(data->grp->group, ptr);
182+ data->server_element = eap_pwd_get_element(data->grp, ptr);
183 if (!data->server_element) {
184 wpa_printf(MSG_INFO, "EAP-PWD (peer): setting peer element "
185 "fail");
186 goto fin;
187 }
188 ptr += prime_len * 2;
189- data->server_scalar = crypto_bignum_init_set(ptr, order_len);
190+ data->server_scalar = eap_pwd_get_scalar(data->grp, ptr);
191 if (!data->server_scalar) {
192 wpa_printf(MSG_INFO,
193 "EAP-PWD (peer): setting peer scalar fail");
194 goto fin;
195 }
196
197- /* verify received scalar */
198- if (crypto_bignum_is_zero(data->server_scalar) ||
199- crypto_bignum_is_one(data->server_scalar) ||
200- crypto_bignum_cmp(data->server_scalar,
201- crypto_ec_get_order(data->grp->group)) >= 0) {
202- wpa_printf(MSG_INFO,
203- "EAP-PWD (peer): received scalar is invalid");
204- goto fin;
205- }
206-
207- /* verify received element */
208- if (!crypto_ec_point_is_on_curve(data->grp->group,
209- data->server_element) ||
210- crypto_ec_point_is_at_infinity(data->grp->group,
211- data->server_element)) {
212- wpa_printf(MSG_INFO,
213- "EAP-PWD (peer): received element is invalid");
214- goto fin;
215- }
216-
217- /* check to ensure server's element is not in a small sub-group */
218- if (!crypto_bignum_is_one(cofactor)) {
219- if (crypto_ec_point_mul(data->grp->group, data->server_element,
220- cofactor, point) < 0) {
221- wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply "
222- "server element by order!\n");
223- goto fin;
224- }
225- if (crypto_ec_point_is_at_infinity(data->grp->group, point)) {
226- wpa_printf(MSG_INFO, "EAP-PWD (peer): server element "
227- "is at infinity!\n");
228- goto fin;
229- }
230- }
231-
232 /* compute the shared key, k */
233 if (crypto_ec_point_mul(data->grp->group, data->grp->pwe,
234 data->server_scalar, K) < 0 ||
235@@ -702,7 +666,6 @@ fin:
236 crypto_bignum_deinit(mask, 1);
237 crypto_bignum_deinit(cofactor, 1);
238 crypto_ec_point_deinit(K, 1);
239- crypto_ec_point_deinit(point, 1);
240 if (data->outbuf == NULL)
241 eap_pwd_state(data, FAILURE);
242 else
243diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c
244index 16057e9..f6c75cf 100644
245--- a/src/eap_server/eap_server_pwd.c
246+++ b/src/eap_server/eap_server_pwd.c
247@@ -669,7 +669,7 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
248 {
249 const u8 *ptr;
250 struct crypto_bignum *cofactor = NULL;
251- struct crypto_ec_point *K = NULL, *point = NULL;
252+ struct crypto_ec_point *K = NULL;
253 int res = 0;
254 size_t prime_len, order_len;
255
256@@ -688,9 +688,8 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
257
258 data->k = crypto_bignum_init();
259 cofactor = crypto_bignum_init();
260- point = crypto_ec_point_init(data->grp->group);
261 K = crypto_ec_point_init(data->grp->group);
262- if (!data->k || !cofactor || !point || !K) {
263+ if (!data->k || !cofactor || !K) {
264 wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation "
265 "fail");
266 goto fin;
267@@ -704,55 +703,20 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
268
269 /* element, x then y, followed by scalar */
270 ptr = payload;
271- data->peer_element = crypto_ec_point_from_bin(data->grp->group, ptr);
272+ data->peer_element = eap_pwd_get_element(data->grp, ptr);
273 if (!data->peer_element) {
274 wpa_printf(MSG_INFO, "EAP-PWD (server): setting peer element "
275 "fail");
276 goto fin;
277 }
278 ptr += prime_len * 2;
279- data->peer_scalar = crypto_bignum_init_set(ptr, order_len);
280+ data->peer_scalar = eap_pwd_get_scalar(data->grp, ptr);
281 if (!data->peer_scalar) {
282 wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation "
283 "fail");
284 goto fin;
285 }
286
287- /* verify received scalar */
288- if (crypto_bignum_is_zero(data->peer_scalar) ||
289- crypto_bignum_is_one(data->peer_scalar) ||
290- crypto_bignum_cmp(data->peer_scalar,
291- crypto_ec_get_order(data->grp->group)) >= 0) {
292- wpa_printf(MSG_INFO,
293- "EAP-PWD (server): received scalar is invalid");
294- goto fin;
295- }
296-
297- /* verify received element */
298- if (!crypto_ec_point_is_on_curve(data->grp->group,
299- data->peer_element) ||
300- crypto_ec_point_is_at_infinity(data->grp->group,
301- data->peer_element)) {
302- wpa_printf(MSG_INFO,
303- "EAP-PWD (server): received element is invalid");
304- goto fin;
305- }
306-
307- /* check to ensure peer's element is not in a small sub-group */
308- if (!crypto_bignum_is_one(cofactor)) {
309- if (crypto_ec_point_mul(data->grp->group, data->peer_element,
310- cofactor, point) != 0) {
311- wpa_printf(MSG_INFO, "EAP-PWD (server): cannot "
312- "multiply peer element by order");
313- goto fin;
314- }
315- if (crypto_ec_point_is_at_infinity(data->grp->group, point)) {
316- wpa_printf(MSG_INFO, "EAP-PWD (server): peer element "
317- "is at infinity!\n");
318- goto fin;
319- }
320- }
321-
322 /* detect reflection attacks */
323 if (crypto_bignum_cmp(data->my_scalar, data->peer_scalar) == 0 ||
324 crypto_ec_point_cmp(data->grp->group, data->my_element,
325@@ -804,7 +768,6 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
326
327 fin:
328 crypto_ec_point_deinit(K, 1);
329- crypto_ec_point_deinit(point, 1);
330 crypto_bignum_deinit(cofactor, 1);
331
332 if (res)
333--
3342.7.4
335
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant_2.7.bb b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant_2.7.bb
index fe5fa2b82e..277bbaec63 100644
--- a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant_2.7.bb
+++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant_2.7.bb
@@ -25,6 +25,22 @@ SRC_URI = "http://w1.fi/releases/wpa_supplicant-${PV}.tar.gz \
25 file://wpa_supplicant.conf-sane \ 25 file://wpa_supplicant.conf-sane \
26 file://99_wpa_supplicant \ 26 file://99_wpa_supplicant \
27 file://0001-replace-systemd-install-Alias-with-WantedBy.patch \ 27 file://0001-replace-systemd-install-Alias-with-WantedBy.patch \
28 file://0001-OpenSSL-Use-constant-time-operations-for-private-big.patch \
29 file://0002-Add-helper-functions-for-constant-time-operations.patch \
30 file://0003-OpenSSL-Use-constant-time-selection-for-crypto_bignu.patch \
31 file://0004-EAP-pwd-Use-constant-time-and-memory-access-for-find.patch \
32 file://0005-SAE-Minimize-timing-differences-in-PWE-derivation.patch \
33 file://0006-SAE-Avoid-branches-in-is_quadratic_residue_blind.patch \
34 file://0007-SAE-Mask-timing-of-MODP-groups-22-23-24.patch \
35 file://0008-SAE-Use-const_time-selection-for-PWE-in-FFC.patch \
36 file://0009-SAE-Use-constant-time-operations-in-sae_test_pwd_see.patch \
37 file://0010-SAE-Fix-confirm-message-validation-in-error-cases.patch \
38 file://0011-EAP-pwd-server-Verify-received-scalar-and-element.patch \
39 file://0012-EAP-pwd-server-Detect-reflection-attacks.patch \
40 file://0013-EAP-pwd-client-Verify-received-scalar-and-element.patch \
41 file://0014-EAP-pwd-Check-element-x-y-coordinates-explicitly.patch \
42 file://0001-EAP-pwd-server-Fix-reassembly-buffer-handling.patch \
43 file://0003-EAP-pwd-peer-Fix-reassembly-buffer-handling.patch \
28 " 44 "
29SRC_URI[md5sum] = "a68538fb62766f40f890125026c42c10" 45SRC_URI[md5sum] = "a68538fb62766f40f890125026c42c10"
30SRC_URI[sha256sum] = "76ea6b06b7a2ea8e6d9eb1a9166166f1656e6d48c7508914f592100c95c73074" 46SRC_URI[sha256sum] = "76ea6b06b7a2ea8e6d9eb1a9166166f1656e6d48c7508914f592100c95c73074"