From: Adrian Bunk <bunk@stusta.de>
To: openembedded-core@lists.openembedded.org
Subject: [warrior][PATCH] wpa-supplicant: Fix CVE-2019-9494 CVE-2019-9495 CVE-2019-9496 CVE-2019-9497 CVE-2019-9498 CVE-2019-9499 CVE-2019-11555
Date: Wed, 19 Jun 2019 21:04:22 +0300 [thread overview]
Message-ID: <20190619180422.31204-1-bunk@stusta.de> (raw)
Signed-off-by: Adrian Bunk <bunk@stusta.de>
---
...erver-Fix-reassembly-buffer-handling.patch | 48 +++
...tant-time-operations-for-private-big.patch | 97 +++++
...nctions-for-constant-time-operations.patch | 222 ++++++++++++
...-peer-Fix-reassembly-buffer-handling.patch | 48 +++
...tant-time-selection-for-crypto_bignu.patch | 64 ++++
...tant-time-and-memory-access-for-find.patch | 327 +++++++++++++++++
...timing-differences-in-PWE-derivation.patch | 244 +++++++++++++
...anches-in-is_quadratic_residue_blind.patch | 147 ++++++++
...-Mask-timing-of-MODP-groups-22-23-24.patch | 121 +++++++
...-const_time-selection-for-PWE-in-FFC.patch | 108 ++++++
...-time-operations-in-sae_test_pwd_see.patch | 139 ++++++++
...rm-message-validation-in-error-cases.patch | 60 ++++
...r-Verify-received-scalar-and-element.patch | 61 ++++
...pwd-server-Detect-reflection-attacks.patch | 48 +++
...t-Verify-received-scalar-and-element.patch | 61 ++++
...k-element-x-y-coordinates-explicitly.patch | 335 ++++++++++++++++++
.../wpa-supplicant/wpa-supplicant_2.7.bb | 16 +
17 files changed, 2146 insertions(+)
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0001-EAP-pwd-server-Fix-reassembly-buffer-handling.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0001-OpenSSL-Use-constant-time-operations-for-private-big.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0002-Add-helper-functions-for-constant-time-operations.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0003-EAP-pwd-peer-Fix-reassembly-buffer-handling.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0003-OpenSSL-Use-constant-time-selection-for-crypto_bignu.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0004-EAP-pwd-Use-constant-time-and-memory-access-for-find.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0005-SAE-Minimize-timing-differences-in-PWE-derivation.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0006-SAE-Avoid-branches-in-is_quadratic_residue_blind.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0007-SAE-Mask-timing-of-MODP-groups-22-23-24.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0008-SAE-Use-const_time-selection-for-PWE-in-FFC.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0009-SAE-Use-constant-time-operations-in-sae_test_pwd_see.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0010-SAE-Fix-confirm-message-validation-in-error-cases.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0011-EAP-pwd-server-Verify-received-scalar-and-element.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0012-EAP-pwd-server-Detect-reflection-attacks.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0013-EAP-pwd-client-Verify-received-scalar-and-element.patch
create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0014-EAP-pwd-Check-element-x-y-coordinates-explicitly.patch
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 @@
+From fe76f487e28bdc61940f304f153a954cf36935ea Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <jouni@codeaurora.org>
+Date: Wed, 17 Apr 2019 01:55:32 +0300
+Subject: [PATCH 1/3] EAP-pwd server: Fix reassembly buffer handling
+
+data->inbuf allocation might fail and if that were to happen, the next
+fragment in the exchange could have resulted in NULL pointer
+dereference. Unexpected fragment with more bit might also be able to
+trigger this. Fix that by explicitly checking for data->inbuf to be
+available before using it.
+
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-11555
+---
+ src/eap_server/eap_server_pwd.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c
+index 11bef55..38e2af8 100644
+--- a/src/eap_server/eap_server_pwd.c
++++ b/src/eap_server/eap_server_pwd.c
+@@ -912,6 +912,12 @@ static void eap_pwd_process(struct eap_sm *sm, void *priv,
+ * the first and all intermediate fragments have the M bit set
+ */
+ if (EAP_PWD_GET_MORE_BIT(lm_exch) || data->in_frag_pos) {
++ if (!data->inbuf) {
++ wpa_printf(MSG_DEBUG,
++ "EAP-pwd: No buffer for reassembly");
++ eap_pwd_state(data, FAILURE);
++ return;
++ }
+ if ((data->in_frag_pos + len) > wpabuf_size(data->inbuf)) {
+ wpa_printf(MSG_DEBUG, "EAP-pwd: Buffer overflow "
+ "attack detected! (%d+%d > %d)",
+@@ -932,7 +938,7 @@ static void eap_pwd_process(struct eap_sm *sm, void *priv,
+ * last fragment won't have the M bit set (but we're obviously
+ * buffering fragments so that's how we know it's the last)
+ */
+- if (data->in_frag_pos) {
++ if (data->in_frag_pos && data->inbuf) {
+ pos = wpabuf_head_u8(data->inbuf);
+ len = data->in_frag_pos;
+ wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",
+--
+2.7.4
+
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 @@
+From d42c477cc794163a3757956bbffca5cea000923c Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <jouni@codeaurora.org>
+Date: Tue, 26 Feb 2019 11:43:03 +0200
+Subject: [PATCH 01/14] OpenSSL: Use constant time operations for private
+ bignums
+
+This helps in reducing measurable timing differences in operations
+involving private information. BoringSSL has removed BN_FLG_CONSTTIME
+and expects specific constant time functions to be called instead, so a
+bit different approach is needed depending on which library is used.
+
+The main operation that needs protection against side channel attacks is
+BN_mod_exp() that depends on private keys (the public key validation
+step in crypto_dh_derive_secret() is an exception that can use the
+faster version since it does not depend on private keys).
+
+crypto_bignum_div() is currently used only in SAE FFC case with not
+safe-prime groups and only with values that do not depend on private
+keys, so it is not critical to protect it.
+
+crypto_bignum_inverse() is currently used only in SAE FFC PWE
+derivation. The additional protection here is targeting only OpenSSL.
+BoringSSL may need conversion to using BN_mod_inverse_blinded().
+
+This is related to CVE-2019-9494 and CVE-2019-9495.
+
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-9494
+CVE: CVE-2019-9495
+---
+ src/crypto/crypto_openssl.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
+index 9c2ba58..ac53cc8 100644
+--- a/src/crypto/crypto_openssl.c
++++ b/src/crypto/crypto_openssl.c
+@@ -607,7 +607,8 @@ int crypto_mod_exp(const u8 *base, size_t base_len,
+ bn_result == NULL)
+ goto error;
+
+- if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1)
++ if (BN_mod_exp_mont_consttime(bn_result, bn_base, bn_exp, bn_modulus,
++ ctx, NULL) != 1)
+ goto error;
+
+ *result_len = BN_bn2bin(bn_result, result);
+@@ -1360,8 +1361,9 @@ int crypto_bignum_exptmod(const struct crypto_bignum *a,
+ bnctx = BN_CTX_new();
+ if (bnctx == NULL)
+ return -1;
+- res = BN_mod_exp((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,
+- (const BIGNUM *) c, bnctx);
++ res = BN_mod_exp_mont_consttime((BIGNUM *) d, (const BIGNUM *) a,
++ (const BIGNUM *) b, (const BIGNUM *) c,
++ bnctx, NULL);
+ BN_CTX_free(bnctx);
+
+ return res ? 0 : -1;
+@@ -1380,6 +1382,11 @@ int crypto_bignum_inverse(const struct crypto_bignum *a,
+ bnctx = BN_CTX_new();
+ if (bnctx == NULL)
+ return -1;
++#ifdef OPENSSL_IS_BORINGSSL
++ /* TODO: use BN_mod_inverse_blinded() ? */
++#else /* OPENSSL_IS_BORINGSSL */
++ BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME);
++#endif /* OPENSSL_IS_BORINGSSL */
+ res = BN_mod_inverse((BIGNUM *) c, (const BIGNUM *) a,
+ (const BIGNUM *) b, bnctx);
+ BN_CTX_free(bnctx);
+@@ -1413,6 +1420,9 @@ int crypto_bignum_div(const struct crypto_bignum *a,
+ bnctx = BN_CTX_new();
+ if (bnctx == NULL)
+ return -1;
++#ifndef OPENSSL_IS_BORINGSSL
++ BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME);
++#endif /* OPENSSL_IS_BORINGSSL */
+ res = BN_div((BIGNUM *) c, NULL, (const BIGNUM *) a,
+ (const BIGNUM *) b, bnctx);
+ BN_CTX_free(bnctx);
+@@ -1504,8 +1514,8 @@ int crypto_bignum_legendre(const struct crypto_bignum *a,
+ /* exp = (p-1) / 2 */
+ !BN_sub(exp, (const BIGNUM *) p, BN_value_one()) ||
+ !BN_rshift1(exp, exp) ||
+- !BN_mod_exp(tmp, (const BIGNUM *) a, exp, (const BIGNUM *) p,
+- bnctx))
++ !BN_mod_exp_mont_consttime(tmp, (const BIGNUM *) a, exp,
++ (const BIGNUM *) p, bnctx, NULL))
+ goto fail;
+
+ if (BN_is_word(tmp, 1))
+--
+2.7.4
+
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 @@
+From 6e34f618d37ddbb5854c42e2ad4fca83492fa7b7 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <jouni@codeaurora.org>
+Date: Wed, 27 Feb 2019 18:38:30 +0200
+Subject: [PATCH 02/14] Add helper functions for constant time operations
+
+These functions can be used to help implement constant time operations
+for various cryptographic operations that must minimize externally
+observable differences in processing (both in timing and also in
+internal cache use, etc.).
+
+This is related to CVE-2019-9494 and CVE-2019-9495.
+
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-9494
+CVE: CVE-2019-9495
+---
+ src/utils/const_time.h | 191 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 191 insertions(+)
+ create mode 100644 src/utils/const_time.h
+
+diff --git a/src/utils/const_time.h b/src/utils/const_time.h
+new file mode 100644
+index 0000000..ab8f611
+--- /dev/null
++++ b/src/utils/const_time.h
+@@ -0,0 +1,191 @@
++/*
++ * Helper functions for constant time operations
++ * Copyright (c) 2019, The Linux Foundation
++ *
++ * This software may be distributed under the terms of the BSD license.
++ * See README for more details.
++ *
++ * These helper functions can be used to implement logic that needs to minimize
++ * externally visible differences in execution path by avoiding use of branches,
++ * avoiding early termination or other time differences, and forcing same memory
++ * access pattern regardless of values.
++ */
++
++#ifndef CONST_TIME_H
++#define CONST_TIME_H
++
++
++#if defined(__clang__)
++#define NO_UBSAN_UINT_OVERFLOW \
++ __attribute__((no_sanitize("unsigned-integer-overflow")))
++#else
++#define NO_UBSAN_UINT_OVERFLOW
++#endif
++
++
++/**
++ * const_time_fill_msb - Fill all bits with MSB value
++ * @val: Input value
++ * Returns: Value with all the bits set to the MSB of the input val
++ */
++static inline unsigned int const_time_fill_msb(unsigned int val)
++{
++ /* Move the MSB to LSB and multiple by -1 to fill in all bits. */
++ return (val >> (sizeof(val) * 8 - 1)) * ~0U;
++}
++
++
++/* Returns: -1 if val is zero; 0 if val is not zero */
++static inline unsigned int const_time_is_zero(unsigned int val)
++ NO_UBSAN_UINT_OVERFLOW
++{
++ /* Set MSB to 1 for 0 and fill rest of bits with the MSB value */
++ return const_time_fill_msb(~val & (val - 1));
++}
++
++
++/* Returns: -1 if a == b; 0 if a != b */
++static inline unsigned int const_time_eq(unsigned int a, unsigned int b)
++{
++ return const_time_is_zero(a ^ b);
++}
++
++
++/* Returns: -1 if a == b; 0 if a != b */
++static inline u8 const_time_eq_u8(unsigned int a, unsigned int b)
++{
++ return (u8) const_time_eq(a, b);
++}
++
++
++/**
++ * const_time_eq_bin - Constant time memory comparison
++ * @a: First buffer to compare
++ * @b: Second buffer to compare
++ * @len: Number of octets to compare
++ * Returns: -1 if buffers are equal, 0 if not
++ *
++ * This function is meant for comparing passwords or hash values where
++ * difference in execution time or memory access pattern could provide external
++ * observer information about the location of the difference in the memory
++ * buffers. The return value does not behave like memcmp(), i.e.,
++ * const_time_eq_bin() cannot be used to sort items into a defined order. Unlike
++ * memcmp(), the execution time of const_time_eq_bin() does not depend on the
++ * contents of the compared memory buffers, but only on the total compared
++ * length.
++ */
++static inline unsigned int const_time_eq_bin(const void *a, const void *b,
++ size_t len)
++{
++ const u8 *aa = a;
++ const u8 *bb = b;
++ size_t i;
++ u8 res = 0;
++
++ for (i = 0; i < len; i++)
++ res |= aa[i] ^ bb[i];
++
++ return const_time_is_zero(res);
++}
++
++
++/**
++ * const_time_select - Constant time unsigned int selection
++ * @mask: 0 (false) or -1 (true) to identify which value to select
++ * @true_val: Value to select for the true case
++ * @false_val: Value to select for the false case
++ * Returns: true_val if mask == -1, false_val if mask == 0
++ */
++static inline unsigned int const_time_select(unsigned int mask,
++ unsigned int true_val,
++ unsigned int false_val)
++{
++ return (mask & true_val) | (~mask & false_val);
++}
++
++
++/**
++ * const_time_select_int - Constant time int selection
++ * @mask: 0 (false) or -1 (true) to identify which value to select
++ * @true_val: Value to select for the true case
++ * @false_val: Value to select for the false case
++ * Returns: true_val if mask == -1, false_val if mask == 0
++ */
++static inline int const_time_select_int(unsigned int mask, int true_val,
++ int false_val)
++{
++ return (int) const_time_select(mask, (unsigned int) true_val,
++ (unsigned int) false_val);
++}
++
++
++/**
++ * const_time_select_u8 - Constant time u8 selection
++ * @mask: 0 (false) or -1 (true) to identify which value to select
++ * @true_val: Value to select for the true case
++ * @false_val: Value to select for the false case
++ * Returns: true_val if mask == -1, false_val if mask == 0
++ */
++static inline u8 const_time_select_u8(u8 mask, u8 true_val, u8 false_val)
++{
++ return (u8) const_time_select(mask, true_val, false_val);
++}
++
++
++/**
++ * const_time_select_s8 - Constant time s8 selection
++ * @mask: 0 (false) or -1 (true) to identify which value to select
++ * @true_val: Value to select for the true case
++ * @false_val: Value to select for the false case
++ * Returns: true_val if mask == -1, false_val if mask == 0
++ */
++static inline s8 const_time_select_s8(u8 mask, s8 true_val, s8 false_val)
++{
++ return (s8) const_time_select(mask, (unsigned int) true_val,
++ (unsigned int) false_val);
++}
++
++
++/**
++ * const_time_select_bin - Constant time binary buffer selection copy
++ * @mask: 0 (false) or -1 (true) to identify which value to copy
++ * @true_val: Buffer to copy for the true case
++ * @false_val: Buffer to copy for the false case
++ * @len: Number of octets to copy
++ * @dst: Destination buffer for the copy
++ *
++ * This function copies the specified buffer into the destination buffer using
++ * operations with identical memory access pattern regardless of which buffer
++ * is being copied.
++ */
++static inline void const_time_select_bin(u8 mask, const u8 *true_val,
++ const u8 *false_val, size_t len,
++ u8 *dst)
++{
++ size_t i;
++
++ for (i = 0; i < len; i++)
++ dst[i] = const_time_select_u8(mask, true_val[i], false_val[i]);
++}
++
++
++static inline int const_time_memcmp(const void *a, const void *b, size_t len)
++{
++ const u8 *aa = a;
++ const u8 *bb = b;
++ int diff, res = 0;
++ unsigned int mask;
++
++ if (len == 0)
++ return 0;
++ do {
++ len--;
++ diff = (int) aa[len] - (int) bb[len];
++ mask = const_time_is_zero((unsigned int) diff);
++ res = const_time_select_int(mask, res, diff);
++ } while (len);
++
++ return res;
++}
++
++#endif /* CONST_TIME_H */
+--
+2.7.4
+
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 @@
+From d2d1a324ce937628e4d9d9999fe113819b7d4478 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <jouni@codeaurora.org>
+Date: Wed, 17 Apr 2019 02:21:20 +0300
+Subject: [PATCH 3/3] EAP-pwd peer: Fix reassembly buffer handling
+
+Unexpected fragment might result in data->inbuf not being allocated
+before processing and that could have resulted in NULL pointer
+dereference. Fix that by explicitly checking for data->inbuf to be
+available before using it.
+
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-11555
+---
+ src/eap_peer/eap_pwd.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
+index 46894a5..76fcad4 100644
+--- a/src/eap_peer/eap_pwd.c
++++ b/src/eap_peer/eap_pwd.c
+@@ -932,6 +932,13 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret,
+ * buffer and ACK the fragment
+ */
+ if (EAP_PWD_GET_MORE_BIT(lm_exch) || data->in_frag_pos) {
++ if (!data->inbuf) {
++ wpa_printf(MSG_DEBUG,
++ "EAP-pwd: No buffer for reassembly");
++ ret->methodState = METHOD_DONE;
++ ret->decision = DECISION_FAIL;
++ return NULL;
++ }
+ data->in_frag_pos += len;
+ if (data->in_frag_pos > wpabuf_size(data->inbuf)) {
+ wpa_printf(MSG_INFO, "EAP-pwd: Buffer overflow attack "
+@@ -958,7 +965,7 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret,
+ /*
+ * we're buffering and this is the last fragment
+ */
+- if (data->in_frag_pos) {
++ if (data->in_frag_pos && data->inbuf) {
+ wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",
+ (int) len);
+ pos = wpabuf_head_u8(data->inbuf);
+--
+2.7.4
+
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 @@
+From c93461c1d98f52681717a088776ab32fd97872b0 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <jouni@codeaurora.org>
+Date: Fri, 8 Mar 2019 00:24:12 +0200
+Subject: [PATCH 03/14] OpenSSL: Use constant time selection for
+ crypto_bignum_legendre()
+
+Get rid of the branches that depend on the result of the Legendre
+operation. This is needed to avoid leaking information about different
+temporary results in blinding mechanisms.
+
+This is related to CVE-2019-9494 and CVE-2019-9495.
+
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-9494
+CVE: CVE-2019-9495
+---
+ src/crypto/crypto_openssl.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
+index ac53cc8..0f52101 100644
+--- a/src/crypto/crypto_openssl.c
++++ b/src/crypto/crypto_openssl.c
+@@ -24,6 +24,7 @@
+ #endif /* CONFIG_ECC */
+
+ #include "common.h"
++#include "utils/const_time.h"
+ #include "wpabuf.h"
+ #include "dh_group5.h"
+ #include "sha1.h"
+@@ -1500,6 +1501,7 @@ int crypto_bignum_legendre(const struct crypto_bignum *a,
+ BN_CTX *bnctx;
+ BIGNUM *exp = NULL, *tmp = NULL;
+ int res = -2;
++ unsigned int mask;
+
+ if (TEST_FAIL())
+ return -2;
+@@ -1518,12 +1520,13 @@ int crypto_bignum_legendre(const struct crypto_bignum *a,
+ (const BIGNUM *) p, bnctx, NULL))
+ goto fail;
+
+- if (BN_is_word(tmp, 1))
+- res = 1;
+- else if (BN_is_zero(tmp))
+- res = 0;
+- else
+- res = -1;
++ /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need to use
++ * constant time selection to avoid branches here. */
++ res = -1;
++ mask = const_time_eq(BN_is_word(tmp, 1), 1);
++ res = const_time_select_int(mask, 1, res);
++ mask = const_time_eq(BN_is_zero(tmp), 1);
++ res = const_time_select_int(mask, 0, res);
+
+ fail:
+ BN_clear_free(tmp);
+--
+2.7.4
+
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 @@
+From aaf65feac67c3993935634eefe5bc76b9fce03aa Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <jouni@codeaurora.org>
+Date: Tue, 26 Feb 2019 11:59:45 +0200
+Subject: [PATCH 04/14] EAP-pwd: Use constant time and memory access for
+ finding the PWE
+
+This algorithm could leak information to external observers in form of
+timing differences or memory access patterns (cache use). While the
+previous implementation had protection against the most visible timing
+differences (looping 40 rounds and masking the legendre operation), it
+did not protect against memory access patterns between the two possible
+code paths in the masking operations. That might be sufficient to allow
+an unprivileged process running on the same device to be able to
+determine which path is being executed through a cache attack and based
+on that, determine information about the used password.
+
+Convert the PWE finding loop to use constant time functions and
+identical memory access path without different branches for the QR/QNR
+cases to minimize possible side-channel information similarly to the
+changes done for SAE authentication. (CVE-2019-9495)
+
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-9495
+---
+ src/eap_common/eap_pwd_common.c | 187 +++++++++++++++++++++-------------------
+ 1 file changed, 99 insertions(+), 88 deletions(-)
+
+diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
+index 02fe01e..e49aaf8 100644
+--- a/src/eap_common/eap_pwd_common.c
++++ b/src/eap_common/eap_pwd_common.c
+@@ -8,11 +8,15 @@
+
+ #include "includes.h"
+ #include "common.h"
++#include "utils/const_time.h"
+ #include "crypto/sha256.h"
+ #include "crypto/crypto.h"
+ #include "eap_defs.h"
+ #include "eap_pwd_common.h"
+
++#define MAX_ECC_PRIME_LEN 66
++
++
+ /* The random function H(x) = HMAC-SHA256(0^32, x) */
+ struct crypto_hash * eap_pwd_h_init(void)
+ {
+@@ -102,6 +106,15 @@ EAP_PWD_group * get_eap_pwd_group(u16 num)
+ }
+
+
++static void buf_shift_right(u8 *buf, size_t len, size_t bits)
++{
++ size_t i;
++ for (i = len - 1; i > 0; i--)
++ buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits);
++ buf[0] >>= bits;
++}
++
++
+ /*
+ * compute a "random" secret point on an elliptic curve based
+ * on the password and identities.
+@@ -113,17 +126,27 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
+ const u8 *token)
+ {
+ struct crypto_bignum *qr = NULL, *qnr = NULL, *one = NULL;
++ struct crypto_bignum *qr_or_qnr = NULL;
++ u8 qr_bin[MAX_ECC_PRIME_LEN];
++ u8 qnr_bin[MAX_ECC_PRIME_LEN];
++ u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN];
++ u8 x_bin[MAX_ECC_PRIME_LEN];
+ struct crypto_bignum *tmp1 = NULL, *tmp2 = NULL, *pm1 = NULL;
+ struct crypto_hash *hash;
+ unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr;
+- int is_odd, ret = 0, check, found = 0;
+- size_t primebytelen, primebitlen;
+- struct crypto_bignum *x_candidate = NULL, *rnd = NULL, *cofactor = NULL;
++ int ret = 0, check, res;
++ u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
++ * mask */
++ size_t primebytelen = 0, primebitlen;
++ struct crypto_bignum *x_candidate = NULL, *cofactor = NULL;
+ const struct crypto_bignum *prime;
++ u8 mask, found_ctr = 0, is_odd = 0;
+
+ if (grp->pwe)
+ return -1;
+
++ os_memset(x_bin, 0, sizeof(x_bin));
++
+ prime = crypto_ec_get_prime(grp->group);
+ cofactor = crypto_bignum_init();
+ grp->pwe = crypto_ec_point_init(grp->group);
+@@ -152,8 +175,6 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
+
+ /* get a random quadratic residue and nonresidue */
+ while (!qr || !qnr) {
+- int res;
+-
+ if (crypto_bignum_rand(tmp1, prime) < 0)
+ goto fail;
+ res = crypto_bignum_legendre(tmp1, prime);
+@@ -167,6 +188,11 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
+ if (!tmp1)
+ goto fail;
+ }
++ if (crypto_bignum_to_bin(qr, qr_bin, sizeof(qr_bin),
++ primebytelen) < 0 ||
++ crypto_bignum_to_bin(qnr, qnr_bin, sizeof(qnr_bin),
++ primebytelen) < 0)
++ goto fail;
+
+ os_memset(prfbuf, 0, primebytelen);
+ ctr = 0;
+@@ -194,17 +220,16 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
+ eap_pwd_h_update(hash, &ctr, sizeof(ctr));
+ eap_pwd_h_final(hash, pwe_digest);
+
+- crypto_bignum_deinit(rnd, 1);
+- rnd = crypto_bignum_init_set(pwe_digest, SHA256_MAC_LEN);
+- if (!rnd) {
+- wpa_printf(MSG_INFO, "EAP-pwd: unable to create rnd");
+- goto fail;
+- }
++ is_odd = const_time_select_u8(
++ found, is_odd, pwe_digest[SHA256_MAC_LEN - 1] & 0x01);
+ if (eap_pwd_kdf(pwe_digest, SHA256_MAC_LEN,
+ (u8 *) "EAP-pwd Hunting And Pecking",
+ os_strlen("EAP-pwd Hunting And Pecking"),
+ prfbuf, primebitlen) < 0)
+ goto fail;
++ if (primebitlen % 8)
++ buf_shift_right(prfbuf, primebytelen,
++ 8 - primebitlen % 8);
+
+ crypto_bignum_deinit(x_candidate, 1);
+ x_candidate = crypto_bignum_init_set(prfbuf, primebytelen);
+@@ -214,24 +239,13 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
+ goto fail;
+ }
+
+- /*
+- * eap_pwd_kdf() returns a string of bits 0..primebitlen but
+- * BN_bin2bn will treat that string of bits as a big endian
+- * number. If the primebitlen is not an even multiple of 8
+- * then excessive bits-- those _after_ primebitlen-- so now
+- * we have to shift right the amount we masked off.
+- */
+- if ((primebitlen % 8) &&
+- crypto_bignum_rshift(x_candidate,
+- (8 - (primebitlen % 8)),
+- x_candidate) < 0)
+- goto fail;
+-
+ if (crypto_bignum_cmp(x_candidate, prime) >= 0)
+ continue;
+
+- wpa_hexdump(MSG_DEBUG, "EAP-pwd: x_candidate",
+- prfbuf, primebytelen);
++ wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: x_candidate",
++ prfbuf, primebytelen);
++ const_time_select_bin(found, x_bin, prfbuf, primebytelen,
++ x_bin);
+
+ /*
+ * compute y^2 using the equation of the curve
+@@ -261,13 +275,15 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
+ * Flip a coin, multiply by the random quadratic residue or the
+ * random quadratic nonresidue and record heads or tails.
+ */
+- if (crypto_bignum_is_odd(tmp1)) {
+- crypto_bignum_mulmod(tmp2, qr, prime, tmp2);
+- check = 1;
+- } else {
+- crypto_bignum_mulmod(tmp2, qnr, prime, tmp2);
+- check = -1;
+- }
++ mask = const_time_eq_u8(crypto_bignum_is_odd(tmp1), 1);
++ check = const_time_select_s8(mask, 1, -1);
++ const_time_select_bin(mask, qr_bin, qnr_bin, primebytelen,
++ qr_or_qnr_bin);
++ crypto_bignum_deinit(qr_or_qnr, 1);
++ qr_or_qnr = crypto_bignum_init_set(qr_or_qnr_bin, primebytelen);
++ if (!qr_or_qnr ||
++ crypto_bignum_mulmod(tmp2, qr_or_qnr, prime, tmp2) < 0)
++ goto fail;
+
+ /*
+ * Now it's safe to do legendre, if check is 1 then it's
+@@ -275,59 +291,12 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
+ * change result), if check is -1 then it's the opposite test
+ * (multiplying a qr by qnr would make a qnr).
+ */
+- if (crypto_bignum_legendre(tmp2, prime) == check) {
+- if (found == 1)
+- continue;
+-
+- /* need to unambiguously identify the solution */
+- is_odd = crypto_bignum_is_odd(rnd);
+-
+- /*
+- * We know x_candidate is a quadratic residue so set
+- * it here.
+- */
+- if (crypto_ec_point_solve_y_coord(grp->group, grp->pwe,
+- x_candidate,
+- is_odd) != 0) {
+- wpa_printf(MSG_INFO,
+- "EAP-pwd: Could not solve for y");
+- continue;
+- }
+-
+- /*
+- * If there's a solution to the equation then the point
+- * must be on the curve so why check again explicitly?
+- * OpenSSL code says this is required by X9.62. We're
+- * not X9.62 but it can't hurt just to be sure.
+- */
+- if (!crypto_ec_point_is_on_curve(grp->group,
+- grp->pwe)) {
+- wpa_printf(MSG_INFO,
+- "EAP-pwd: point is not on curve");
+- continue;
+- }
+-
+- if (!crypto_bignum_is_one(cofactor)) {
+- /* make sure the point is not in a small
+- * sub-group */
+- if (crypto_ec_point_mul(grp->group, grp->pwe,
+- cofactor,
+- grp->pwe) != 0) {
+- wpa_printf(MSG_INFO,
+- "EAP-pwd: cannot multiply generator by order");
+- continue;
+- }
+- if (crypto_ec_point_is_at_infinity(grp->group,
+- grp->pwe)) {
+- wpa_printf(MSG_INFO,
+- "EAP-pwd: point is at infinity");
+- continue;
+- }
+- }
+- wpa_printf(MSG_DEBUG,
+- "EAP-pwd: found a PWE in %d tries", ctr);
+- found = 1;
+- }
++ res = crypto_bignum_legendre(tmp2, prime);
++ if (res == -2)
++ goto fail;
++ mask = const_time_eq(res, check);
++ found_ctr = const_time_select_u8(found, found_ctr, ctr);
++ found |= mask;
+ }
+ if (found == 0) {
+ wpa_printf(MSG_INFO,
+@@ -335,6 +304,44 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
+ num);
+ goto fail;
+ }
++
++ /*
++ * We know x_candidate is a quadratic residue so set it here.
++ */
++ crypto_bignum_deinit(x_candidate, 1);
++ x_candidate = crypto_bignum_init_set(x_bin, primebytelen);
++ if (!x_candidate ||
++ crypto_ec_point_solve_y_coord(grp->group, grp->pwe, x_candidate,
++ is_odd) != 0) {
++ wpa_printf(MSG_INFO, "EAP-pwd: Could not solve for y");
++ goto fail;
++ }
++
++ /*
++ * If there's a solution to the equation then the point must be on the
++ * curve so why check again explicitly? OpenSSL code says this is
++ * required by X9.62. We're not X9.62 but it can't hurt just to be sure.
++ */
++ if (!crypto_ec_point_is_on_curve(grp->group, grp->pwe)) {
++ wpa_printf(MSG_INFO, "EAP-pwd: point is not on curve");
++ goto fail;
++ }
++
++ if (!crypto_bignum_is_one(cofactor)) {
++ /* make sure the point is not in a small sub-group */
++ if (crypto_ec_point_mul(grp->group, grp->pwe, cofactor,
++ grp->pwe) != 0) {
++ wpa_printf(MSG_INFO,
++ "EAP-pwd: cannot multiply generator by order");
++ goto fail;
++ }
++ if (crypto_ec_point_is_at_infinity(grp->group, grp->pwe)) {
++ wpa_printf(MSG_INFO, "EAP-pwd: point is at infinity");
++ goto fail;
++ }
++ }
++ wpa_printf(MSG_DEBUG, "EAP-pwd: found a PWE in %02d tries", found_ctr);
++
+ if (0) {
+ fail:
+ crypto_ec_point_deinit(grp->pwe, 1);
+@@ -344,14 +351,18 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
+ /* cleanliness and order.... */
+ crypto_bignum_deinit(cofactor, 1);
+ crypto_bignum_deinit(x_candidate, 1);
+- crypto_bignum_deinit(rnd, 1);
+ crypto_bignum_deinit(pm1, 0);
+ crypto_bignum_deinit(tmp1, 1);
+ crypto_bignum_deinit(tmp2, 1);
+ crypto_bignum_deinit(qr, 1);
+ crypto_bignum_deinit(qnr, 1);
++ crypto_bignum_deinit(qr_or_qnr, 1);
+ crypto_bignum_deinit(one, 0);
+- os_free(prfbuf);
++ bin_clear_free(prfbuf, primebytelen);
++ os_memset(qr_bin, 0, sizeof(qr_bin));
++ os_memset(qnr_bin, 0, sizeof(qnr_bin));
++ os_memset(qr_or_qnr_bin, 0, sizeof(qr_or_qnr_bin));
++ os_memset(pwe_digest, 0, sizeof(pwe_digest));
+
+ return ret;
+ }
+--
+2.7.4
+
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 @@
+From 6513db3e96c43c2e36805cf5ead349765d18eaf7 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <jouni@codeaurora.org>
+Date: Tue, 26 Feb 2019 13:05:09 +0200
+Subject: [PATCH 05/14] SAE: Minimize timing differences in PWE derivation
+
+The QR test result can provide information about the password to an
+attacker, so try to minimize differences in how the
+sae_test_pwd_seed_ecc() result is used. (CVE-2019-9494)
+
+Use heap memory for the dummy password to allow the same password length
+to be used even with long passwords.
+
+Use constant time selection functions to track the real vs. dummy
+variables so that the exact same operations can be performed for both QR
+test results.
+
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-9494
+---
+ src/common/sae.c | 106 ++++++++++++++++++++++++++++++-------------------------
+ 1 file changed, 57 insertions(+), 49 deletions(-)
+
+diff --git a/src/common/sae.c b/src/common/sae.c
+index 8129a7c..d55323b 100644
+--- a/src/common/sae.c
++++ b/src/common/sae.c
+@@ -9,6 +9,7 @@
+ #include "includes.h"
+
+ #include "common.h"
++#include "utils/const_time.h"
+ #include "crypto/crypto.h"
+ #include "crypto/sha256.h"
+ #include "crypto/random.h"
+@@ -292,15 +293,12 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
+ const u8 *prime,
+ const struct crypto_bignum *qr,
+ const struct crypto_bignum *qnr,
+- struct crypto_bignum **ret_x_cand)
++ u8 *pwd_value)
+ {
+- u8 pwd_value[SAE_MAX_ECC_PRIME_LEN];
+ struct crypto_bignum *y_sqr, *x_cand;
+ int res;
+ size_t bits;
+
+- *ret_x_cand = NULL;
+-
+ wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
+
+ /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
+@@ -309,7 +307,7 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
+ prime, sae->tmp->prime_len, pwd_value, bits) < 0)
+ return -1;
+ if (bits % 8)
+- buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
++ buf_shift_right(pwd_value, sae->tmp->prime_len, 8 - bits % 8);
+ wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
+ pwd_value, sae->tmp->prime_len);
+
+@@ -320,20 +318,13 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
+ if (!x_cand)
+ return -1;
+ y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand);
+- if (!y_sqr) {
+- crypto_bignum_deinit(x_cand, 1);
++ crypto_bignum_deinit(x_cand, 1);
++ if (!y_sqr)
+ return -1;
+- }
+
+ res = is_quadratic_residue_blind(sae, prime, bits, qr, qnr, y_sqr);
+ crypto_bignum_deinit(y_sqr, 1);
+- if (res <= 0) {
+- crypto_bignum_deinit(x_cand, 1);
+- return res;
+- }
+-
+- *ret_x_cand = x_cand;
+- return 1;
++ return res;
+ }
+
+
+@@ -454,25 +445,30 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
+ const u8 *addr[3];
+ size_t len[3];
+ size_t num_elem;
+- u8 dummy_password[32];
+- size_t dummy_password_len;
++ u8 *dummy_password, *tmp_password;
+ int pwd_seed_odd = 0;
+ u8 prime[SAE_MAX_ECC_PRIME_LEN];
+ size_t prime_len;
+- struct crypto_bignum *x = NULL, *qr, *qnr;
++ struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL;
++ u8 x_bin[SAE_MAX_ECC_PRIME_LEN];
++ u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN];
+ size_t bits;
+- int res;
++ int res = -1;
++ u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
++ * mask */
+
+- dummy_password_len = password_len;
+- if (dummy_password_len > sizeof(dummy_password))
+- dummy_password_len = sizeof(dummy_password);
+- if (random_get_bytes(dummy_password, dummy_password_len) < 0)
+- return -1;
++ os_memset(x_bin, 0, sizeof(x_bin));
++
++ dummy_password = os_malloc(password_len);
++ tmp_password = os_malloc(password_len);
++ if (!dummy_password || !tmp_password ||
++ random_get_bytes(dummy_password, password_len) < 0)
++ goto fail;
+
+ prime_len = sae->tmp->prime_len;
+ if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
+ prime_len) < 0)
+- return -1;
++ goto fail;
+ bits = crypto_ec_prime_len_bits(sae->tmp->ec);
+
+ /*
+@@ -481,7 +477,7 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
+ */
+ if (get_random_qr_qnr(prime, prime_len, sae->tmp->prime, bits,
+ &qr, &qnr) < 0)
+- return -1;
++ goto fail;
+
+ wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
+ password, password_len);
+@@ -497,7 +493,7 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
+ */
+ sae_pwd_seed_key(addr1, addr2, addrs);
+
+- addr[0] = password;
++ addr[0] = tmp_password;
+ len[0] = password_len;
+ num_elem = 1;
+ if (identifier) {
+@@ -514,9 +510,8 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
+ * attacks that attempt to determine the number of iterations required
+ * in the loop.
+ */
+- for (counter = 1; counter <= k || !x; counter++) {
++ for (counter = 1; counter <= k || !found; counter++) {
+ u8 pwd_seed[SHA256_MAC_LEN];
+- struct crypto_bignum *x_cand;
+
+ if (counter > 200) {
+ /* This should not happen in practice */
+@@ -524,36 +519,45 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
+ break;
+ }
+
+- wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
++ wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter);
++ const_time_select_bin(found, dummy_password, password,
++ password_len, tmp_password);
+ if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
+ addr, len, pwd_seed) < 0)
+ break;
+
+ res = sae_test_pwd_seed_ecc(sae, pwd_seed,
+- prime, qr, qnr, &x_cand);
++ prime, qr, qnr, x_cand_bin);
++ const_time_select_bin(found, x_bin, x_cand_bin, prime_len,
++ x_bin);
++ pwd_seed_odd = const_time_select_u8(
++ found, pwd_seed_odd,
++ pwd_seed[SHA256_MAC_LEN - 1] & 0x01);
++ os_memset(pwd_seed, 0, sizeof(pwd_seed));
+ if (res < 0)
+ goto fail;
+- if (res > 0 && !x) {
+- wpa_printf(MSG_DEBUG,
+- "SAE: Selected pwd-seed with counter %u",
+- counter);
+- x = x_cand;
+- pwd_seed_odd = pwd_seed[SHA256_MAC_LEN - 1] & 0x01;
+- os_memset(pwd_seed, 0, sizeof(pwd_seed));
++ /* Need to minimize differences in handling res == 0 and 1 here
++ * to avoid differences in timing and instruction cache access,
++ * so use const_time_select_*() to make local copies of the
++ * values based on whether this loop iteration was the one that
++ * found the pwd-seed/x. */
++
++ /* found is 0 or 0xff here and res is 0 or 1. Bitwise OR of them
++ * (with res converted to 0/0xff) handles this in constant time.
++ */
++ found |= res * 0xff;
++ wpa_printf(MSG_DEBUG, "SAE: pwd-seed result %d found=0x%02x",
++ res, found);
++ }
+
+- /*
+- * Use a dummy password for the following rounds, if
+- * any.
+- */
+- addr[0] = dummy_password;
+- len[0] = dummy_password_len;
+- } else if (res > 0) {
+- crypto_bignum_deinit(x_cand, 1);
+- }
++ if (!found) {
++ wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
++ res = -1;
++ goto fail;
+ }
+
++ x = crypto_bignum_init_set(x_bin, prime_len);
+ if (!x) {
+- wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
+ res = -1;
+ goto fail;
+ }
+@@ -566,7 +570,6 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
+ res = crypto_ec_point_solve_y_coord(sae->tmp->ec,
+ sae->tmp->pwe_ecc, x,
+ pwd_seed_odd);
+- crypto_bignum_deinit(x, 1);
+ if (res < 0) {
+ /*
+ * This should not happen since we already checked that there
+@@ -578,6 +581,11 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
+ fail:
+ crypto_bignum_deinit(qr, 0);
+ crypto_bignum_deinit(qnr, 0);
++ os_free(dummy_password);
++ bin_clear_free(tmp_password, password_len);
++ crypto_bignum_deinit(x, 1);
++ os_memset(x_bin, 0, sizeof(x_bin));
++ os_memset(x_cand_bin, 0, sizeof(x_cand_bin));
+
+ return res;
+ }
+--
+2.7.4
+
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 @@
+From 362704dda04507e7ebb8035122e83d9f0ae7c320 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <jouni@codeaurora.org>
+Date: Tue, 26 Feb 2019 19:34:38 +0200
+Subject: [PATCH 06/14] SAE: Avoid branches in is_quadratic_residue_blind()
+
+Make the non-failure path in the function proceed without branches based
+on r_odd and in constant time to minimize risk of observable differences
+in timing or cache use. (CVE-2019-9494)
+
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-9494
+---
+ src/common/sae.c | 64 ++++++++++++++++++++++++++++++++------------------------
+ 1 file changed, 37 insertions(+), 27 deletions(-)
+
+diff --git a/src/common/sae.c b/src/common/sae.c
+index d55323b..5df9b95 100644
+--- a/src/common/sae.c
++++ b/src/common/sae.c
+@@ -232,12 +232,14 @@ get_rand_1_to_p_1(const u8 *prime, size_t prime_len, size_t prime_bits,
+
+ static int is_quadratic_residue_blind(struct sae_data *sae,
+ const u8 *prime, size_t bits,
+- const struct crypto_bignum *qr,
+- const struct crypto_bignum *qnr,
++ const u8 *qr, const u8 *qnr,
+ const struct crypto_bignum *y_sqr)
+ {
+- struct crypto_bignum *r, *num;
++ struct crypto_bignum *r, *num, *qr_or_qnr = NULL;
+ int r_odd, check, res = -1;
++ u8 qr_or_qnr_bin[SAE_MAX_ECC_PRIME_LEN];
++ size_t prime_len = sae->tmp->prime_len;
++ unsigned int mask;
+
+ /*
+ * Use the blinding technique to mask y_sqr while determining
+@@ -248,7 +250,7 @@ static int is_quadratic_residue_blind(struct sae_data *sae,
+ * r = a random number between 1 and p-1, inclusive
+ * num = (v * r * r) modulo p
+ */
+- r = get_rand_1_to_p_1(prime, sae->tmp->prime_len, bits, &r_odd);
++ r = get_rand_1_to_p_1(prime, prime_len, bits, &r_odd);
+ if (!r)
+ return -1;
+
+@@ -258,41 +260,45 @@ static int is_quadratic_residue_blind(struct sae_data *sae,
+ crypto_bignum_mulmod(num, r, sae->tmp->prime, num) < 0)
+ goto fail;
+
+- if (r_odd) {
+- /*
+- * num = (num * qr) module p
+- * LGR(num, p) = 1 ==> quadratic residue
+- */
+- if (crypto_bignum_mulmod(num, qr, sae->tmp->prime, num) < 0)
+- goto fail;
+- check = 1;
+- } else {
+- /*
+- * num = (num * qnr) module p
+- * LGR(num, p) = -1 ==> quadratic residue
+- */
+- if (crypto_bignum_mulmod(num, qnr, sae->tmp->prime, num) < 0)
+- goto fail;
+- check = -1;
+- }
++ /*
++ * Need to minimize differences in handling different cases, so try to
++ * avoid branches and timing differences.
++ *
++ * If r_odd:
++ * num = (num * qr) module p
++ * LGR(num, p) = 1 ==> quadratic residue
++ * else:
++ * num = (num * qnr) module p
++ * LGR(num, p) = -1 ==> quadratic residue
++ */
++ mask = const_time_is_zero(r_odd);
++ const_time_select_bin(mask, qnr, qr, prime_len, qr_or_qnr_bin);
++ qr_or_qnr = crypto_bignum_init_set(qr_or_qnr_bin, prime_len);
++ if (!qr_or_qnr ||
++ crypto_bignum_mulmod(num, qr_or_qnr, sae->tmp->prime, num) < 0)
++ goto fail;
++ /* r_odd is 0 or 1; branchless version of check = r_odd ? 1 : -1, */
++ check = const_time_select_int(mask, -1, 1);
+
+ res = crypto_bignum_legendre(num, sae->tmp->prime);
+ if (res == -2) {
+ res = -1;
+ goto fail;
+ }
+- res = res == check;
++ /* branchless version of res = res == check
++ * (res is -1, 0, or 1; check is -1 or 1) */
++ mask = const_time_eq(res, check);
++ res = const_time_select_int(mask, 1, 0);
+ fail:
+ crypto_bignum_deinit(num, 1);
+ crypto_bignum_deinit(r, 1);
++ crypto_bignum_deinit(qr_or_qnr, 1);
+ return res;
+ }
+
+
+ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
+- const u8 *prime,
+- const struct crypto_bignum *qr,
+- const struct crypto_bignum *qnr,
++ const u8 *prime, const u8 *qr, const u8 *qnr,
+ u8 *pwd_value)
+ {
+ struct crypto_bignum *y_sqr, *x_cand;
+@@ -452,6 +458,8 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
+ struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL;
+ u8 x_bin[SAE_MAX_ECC_PRIME_LEN];
+ u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN];
++ u8 qr_bin[SAE_MAX_ECC_PRIME_LEN];
++ u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN];
+ size_t bits;
+ int res = -1;
+ u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
+@@ -476,7 +484,9 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
+ * (qnr) modulo p for blinding purposes during the loop.
+ */
+ if (get_random_qr_qnr(prime, prime_len, sae->tmp->prime, bits,
+- &qr, &qnr) < 0)
++ &qr, &qnr) < 0 ||
++ crypto_bignum_to_bin(qr, qr_bin, sizeof(qr_bin), prime_len) < 0 ||
++ crypto_bignum_to_bin(qnr, qnr_bin, sizeof(qnr_bin), prime_len) < 0)
+ goto fail;
+
+ wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
+@@ -527,7 +537,7 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
+ break;
+
+ res = sae_test_pwd_seed_ecc(sae, pwd_seed,
+- prime, qr, qnr, x_cand_bin);
++ prime, qr_bin, qnr_bin, x_cand_bin);
+ const_time_select_bin(found, x_bin, x_cand_bin, prime_len,
+ x_bin);
+ pwd_seed_odd = const_time_select_u8(
+--
+2.7.4
+
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 @@
+From 90839597cc4016b33f00055b12d59174c62770a3 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <jouni@codeaurora.org>
+Date: Sat, 2 Mar 2019 12:24:09 +0200
+Subject: [PATCH 07/14] SAE: Mask timing of MODP groups 22, 23, 24
+
+These groups have significant probability of coming up with pwd-value
+that is equal or greater than the prime and as such, need for going
+through the PWE derivation loop multiple times. This can result in
+sufficient timing different to allow an external observer to determine
+how many rounds are needed and that can leak information about the used
+password.
+
+Force at least 40 loop rounds for these MODP groups similarly to the ECC
+group design to mask timing. This behavior is not described in IEEE Std
+802.11-2016 for SAE, but it does not result in different values (i.e.,
+only different timing), so such implementation specific countermeasures
+can be done without breaking interoperability with other implementation.
+
+Note: These MODP groups 22, 23, and 24 are not considered sufficiently
+strong to be used with SAE (or more or less anything else). As such,
+they should never be enabled in runtime configuration for any production
+use cases. These changes to introduce additional protection to mask
+timing is only for completeness of implementation and not an indication
+that these groups should be used.
+
+This is related to CVE-2019-9494.
+
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-9494
+---
+ src/common/sae.c | 38 ++++++++++++++++++++++++++++----------
+ 1 file changed, 28 insertions(+), 10 deletions(-)
+
+diff --git a/src/common/sae.c b/src/common/sae.c
+index 5df9b95..75b1b4a 100644
+--- a/src/common/sae.c
++++ b/src/common/sae.c
+@@ -601,22 +601,27 @@ fail:
+ }
+
+
++static int sae_modp_group_require_masking(int group)
++{
++ /* Groups for which pwd-value is likely to be >= p frequently */
++ return group == 22 || group == 23 || group == 24;
++}
++
++
+ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
+ const u8 *addr2, const u8 *password,
+ size_t password_len, const char *identifier)
+ {
+- u8 counter;
++ u8 counter, k;
+ u8 addrs[2 * ETH_ALEN];
+ const u8 *addr[3];
+ size_t len[3];
+ size_t num_elem;
+ int found = 0;
++ struct crypto_bignum *pwe = NULL;
+
+- if (sae->tmp->pwe_ffc == NULL) {
+- sae->tmp->pwe_ffc = crypto_bignum_init();
+- if (sae->tmp->pwe_ffc == NULL)
+- return -1;
+- }
++ crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
++ sae->tmp->pwe_ffc = NULL;
+
+ wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
+ password, password_len);
+@@ -640,7 +645,9 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
+ len[num_elem] = sizeof(counter);
+ num_elem++;
+
+- for (counter = 1; !found; counter++) {
++ k = sae_modp_group_require_masking(sae->group) ? 40 : 1;
++
++ for (counter = 1; counter <= k || !found; counter++) {
+ u8 pwd_seed[SHA256_MAC_LEN];
+ int res;
+
+@@ -650,19 +657,30 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
+ break;
+ }
+
+- wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
++ wpa_printf(MSG_DEBUG, "SAE: counter = %02u", counter);
+ if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
+ addr, len, pwd_seed) < 0)
+ break;
+- res = sae_test_pwd_seed_ffc(sae, pwd_seed, sae->tmp->pwe_ffc);
++ if (!pwe) {
++ pwe = crypto_bignum_init();
++ if (!pwe)
++ break;
++ }
++ res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
+ if (res < 0)
+ break;
+ if (res > 0) {
+- wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
+ found = 1;
++ if (!sae->tmp->pwe_ffc) {
++ wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
++ sae->tmp->pwe_ffc = pwe;
++ pwe = NULL;
++ }
+ }
+ }
+
++ crypto_bignum_deinit(pwe, 1);
++
+ return found ? 0 : -1;
+ }
+
+--
+2.7.4
+
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 @@
+From f8f20717f87eff1f025f48ed585c7684debacf72 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <jouni@codeaurora.org>
+Date: Sat, 2 Mar 2019 12:45:33 +0200
+Subject: [PATCH 08/14] SAE: Use const_time selection for PWE in FFC
+
+This is an initial step towards making the FFC case use strictly
+constant time operations similarly to the ECC case.
+sae_test_pwd_seed_ffc() does not yet have constant time behavior,
+though.
+
+This is related to CVE-2019-9494.
+
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-9494
+---
+ src/common/sae.c | 53 +++++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 35 insertions(+), 18 deletions(-)
+
+diff --git a/src/common/sae.c b/src/common/sae.c
+index 75b1b4a..fa9a145 100644
+--- a/src/common/sae.c
++++ b/src/common/sae.c
+@@ -612,17 +612,28 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
+ const u8 *addr2, const u8 *password,
+ size_t password_len, const char *identifier)
+ {
+- u8 counter, k;
++ u8 counter, k, sel_counter = 0;
+ u8 addrs[2 * ETH_ALEN];
+ const u8 *addr[3];
+ size_t len[3];
+ size_t num_elem;
+- int found = 0;
+- struct crypto_bignum *pwe = NULL;
++ u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
++ * mask */
++ u8 mask;
++ struct crypto_bignum *pwe;
++ size_t prime_len = sae->tmp->prime_len * 8;
++ u8 *pwe_buf;
+
+ crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
+ sae->tmp->pwe_ffc = NULL;
+
++ /* Allocate a buffer to maintain selected and candidate PWE for constant
++ * time selection. */
++ pwe_buf = os_zalloc(prime_len * 2);
++ pwe = crypto_bignum_init();
++ if (!pwe_buf || !pwe)
++ goto fail;
++
+ wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
+ password, password_len);
+
+@@ -661,27 +672,33 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
+ if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
+ addr, len, pwd_seed) < 0)
+ break;
+- if (!pwe) {
+- pwe = crypto_bignum_init();
+- if (!pwe)
+- break;
+- }
+ res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
++ /* res is -1 for fatal failure, 0 if a valid PWE was not found,
++ * or 1 if a valid PWE was found. */
+ if (res < 0)
+ break;
+- if (res > 0) {
+- found = 1;
+- if (!sae->tmp->pwe_ffc) {
+- wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
+- sae->tmp->pwe_ffc = pwe;
+- pwe = NULL;
+- }
+- }
++ /* Store the candidate PWE into the second half of pwe_buf and
++ * the selected PWE in the beginning of pwe_buf using constant
++ * time selection. */
++ if (crypto_bignum_to_bin(pwe, pwe_buf + prime_len, prime_len,
++ prime_len) < 0)
++ break;
++ const_time_select_bin(found, pwe_buf, pwe_buf + prime_len,
++ prime_len, pwe_buf);
++ sel_counter = const_time_select_u8(found, sel_counter, counter);
++ mask = const_time_eq_u8(res, 1);
++ found = const_time_select_u8(found, found, mask);
+ }
+
+- crypto_bignum_deinit(pwe, 1);
++ if (!found)
++ goto fail;
+
+- return found ? 0 : -1;
++ wpa_printf(MSG_DEBUG, "SAE: Use PWE from counter = %02u", sel_counter);
++ sae->tmp->pwe_ffc = crypto_bignum_init_set(pwe_buf, prime_len);
++fail:
++ crypto_bignum_deinit(pwe, 1);
++ bin_clear_free(pwe_buf, prime_len * 2);
++ return sae->tmp->pwe_ffc ? 0 : -1;
+ }
+
+
+--
+2.7.4
+
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 @@
+From cff138b0747fa39765cbc641b66cfa5d7f1735d1 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <jouni@codeaurora.org>
+Date: Sat, 2 Mar 2019 16:05:56 +0200
+Subject: [PATCH 09/14] SAE: Use constant time operations in
+ sae_test_pwd_seed_ffc()
+
+Try to avoid showing externally visible timing or memory access
+differences regardless of whether the derived pwd-value is smaller than
+the group prime.
+
+This is related to CVE-2019-9494.
+
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-9494
+---
+ src/common/sae.c | 75 ++++++++++++++++++++++++++++++++++----------------------
+ 1 file changed, 46 insertions(+), 29 deletions(-)
+
+diff --git a/src/common/sae.c b/src/common/sae.c
+index fa9a145..eaf825d 100644
+--- a/src/common/sae.c
++++ b/src/common/sae.c
+@@ -334,14 +334,17 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
+ }
+
+
++/* Returns -1 on fatal failure, 0 if PWE cannot be derived from the provided
++ * pwd-seed, or 1 if a valid PWE was derived from pwd-seed. */
+ static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
+ struct crypto_bignum *pwe)
+ {
+ u8 pwd_value[SAE_MAX_PRIME_LEN];
+ size_t bits = sae->tmp->prime_len * 8;
+ u8 exp[1];
+- struct crypto_bignum *a, *b;
+- int res;
++ struct crypto_bignum *a, *b = NULL;
++ int res, is_val;
++ u8 pwd_value_valid;
+
+ wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
+
+@@ -353,16 +356,29 @@ static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
+ wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value,
+ sae->tmp->prime_len);
+
+- if (os_memcmp(pwd_value, sae->tmp->dh->prime, sae->tmp->prime_len) >= 0)
+- {
+- wpa_printf(MSG_DEBUG, "SAE: pwd-value >= p");
+- return 0;
+- }
++ /* Check whether pwd-value < p */
++ res = const_time_memcmp(pwd_value, sae->tmp->dh->prime,
++ sae->tmp->prime_len);
++ /* pwd-value >= p is invalid, so res is < 0 for the valid cases and
++ * the negative sign can be used to fill the mask for constant time
++ * selection */
++ pwd_value_valid = const_time_fill_msb(res);
++
++ /* If pwd-value >= p, force pwd-value to be < p and perform the
++ * calculations anyway to hide timing difference. The derived PWE will
++ * be ignored in that case. */
++ pwd_value[0] = const_time_select_u8(pwd_value_valid, pwd_value[0], 0);
+
+ /* PWE = pwd-value^((p-1)/r) modulo p */
+
++ res = -1;
+ a = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
++ if (!a)
++ goto fail;
+
++ /* This is an optimization based on the used group that does not depend
++ * on the password in any way, so it is fine to use separate branches
++ * for this step without constant time operations. */
+ if (sae->tmp->dh->safe_prime) {
+ /*
+ * r = (p-1)/2 for the group used here, so this becomes:
+@@ -376,33 +392,34 @@ static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
+ b = crypto_bignum_init_set(exp, sizeof(exp));
+ if (b == NULL ||
+ crypto_bignum_sub(sae->tmp->prime, b, b) < 0 ||
+- crypto_bignum_div(b, sae->tmp->order, b) < 0) {
+- crypto_bignum_deinit(b, 0);
+- b = NULL;
+- }
++ crypto_bignum_div(b, sae->tmp->order, b) < 0)
++ goto fail;
+ }
+
+- if (a == NULL || b == NULL)
+- res = -1;
+- else
+- res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe);
+-
+- crypto_bignum_deinit(a, 0);
+- crypto_bignum_deinit(b, 0);
++ if (!b)
++ goto fail;
+
+- if (res < 0) {
+- wpa_printf(MSG_DEBUG, "SAE: Failed to calculate PWE");
+- return -1;
+- }
++ res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe);
++ if (res < 0)
++ goto fail;
+
+- /* if (PWE > 1) --> found */
+- if (crypto_bignum_is_zero(pwe) || crypto_bignum_is_one(pwe)) {
+- wpa_printf(MSG_DEBUG, "SAE: PWE <= 1");
+- return 0;
+- }
++ /* There were no fatal errors in calculations, so determine the return
++ * value using constant time operations. We get here for number of
++ * invalid cases which are cleared here after having performed all the
++ * computation. PWE is valid if pwd-value was less than prime and
++ * PWE > 1. Start with pwd-value check first and then use constant time
++ * operations to clear res to 0 if PWE is 0 or 1.
++ */
++ res = const_time_select_u8(pwd_value_valid, 1, 0);
++ is_val = crypto_bignum_is_zero(pwe);
++ res = const_time_select_u8(const_time_is_zero(is_val), res, 0);
++ is_val = crypto_bignum_is_one(pwe);
++ res = const_time_select_u8(const_time_is_zero(is_val), res, 0);
+
+- wpa_printf(MSG_DEBUG, "SAE: PWE found");
+- return 1;
++fail:
++ crypto_bignum_deinit(a, 1);
++ crypto_bignum_deinit(b, 1);
++ return res;
+ }
+
+
+--
+2.7.4
+
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 @@
+From ac8fa9ef198640086cf2ce7c94673be2b6a018a0 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <jouni@codeaurora.org>
+Date: Tue, 5 Mar 2019 23:43:25 +0200
+Subject: [PATCH 10/14] SAE: Fix confirm message validation in error cases
+
+Explicitly verify that own and peer commit scalar/element are available
+when trying to check SAE confirm message. It could have been possible to
+hit a NULL pointer dereference if the peer element could not have been
+parsed. (CVE-2019-9496)
+
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-9496
+---
+ src/common/sae.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/src/common/sae.c b/src/common/sae.c
+index eaf825d..5a50294 100644
+--- a/src/common/sae.c
++++ b/src/common/sae.c
+@@ -1487,23 +1487,31 @@ int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
+
+ wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data));
+
+- if (sae->tmp == NULL) {
++ if (!sae->tmp || !sae->peer_commit_scalar ||
++ !sae->tmp->own_commit_scalar) {
+ wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available");
+ return -1;
+ }
+
+- if (sae->tmp->ec)
++ if (sae->tmp->ec) {
++ if (!sae->tmp->peer_commit_element_ecc ||
++ !sae->tmp->own_commit_element_ecc)
++ return -1;
+ sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar,
+ sae->tmp->peer_commit_element_ecc,
+ sae->tmp->own_commit_scalar,
+ sae->tmp->own_commit_element_ecc,
+ verifier);
+- else
++ } else {
++ if (!sae->tmp->peer_commit_element_ffc ||
++ !sae->tmp->own_commit_element_ffc)
++ return -1;
+ sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar,
+ sae->tmp->peer_commit_element_ffc,
+ sae->tmp->own_commit_scalar,
+ sae->tmp->own_commit_element_ffc,
+ verifier);
++ }
+
+ if (os_memcmp_const(verifier, data + 2, SHA256_MAC_LEN) != 0) {
+ wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
+--
+2.7.4
+
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 @@
+From 70ff850e89fbc8bc7da515321b4d15b5eef70581 Mon Sep 17 00:00:00 2001
+From: Mathy Vanhoef <mathy.vanhoef@nyu.edu>
+Date: Sun, 31 Mar 2019 17:13:06 +0200
+Subject: [PATCH 11/14] EAP-pwd server: Verify received scalar and element
+
+When processing an EAP-pwd Commit frame, the peer's scalar and element
+(elliptic curve point) were not validated. This allowed an adversary to
+bypass authentication, and impersonate any user if the crypto
+implementation did not verify the validity of the EC point.
+
+Fix this vulnerability by assuring the received scalar lies within the
+valid range, and by checking that the received element is not the point
+at infinity and lies on the elliptic curve being used. (CVE-2019-9498)
+
+The vulnerability is only exploitable if OpenSSL version 1.0.2 or lower
+is used, or if LibreSSL or wolfssl is used. Newer versions of OpenSSL
+(and also BoringSSL) implicitly validate the elliptic curve point in
+EC_POINT_set_affine_coordinates_GFp(), preventing the attack.
+
+Signed-off-by: Mathy Vanhoef <mathy.vanhoef@nyu.edu>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-9498
+---
+ src/eap_server/eap_server_pwd.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c
+index d0fa54a..74979da 100644
+--- a/src/eap_server/eap_server_pwd.c
++++ b/src/eap_server/eap_server_pwd.c
+@@ -718,6 +718,26 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
+ goto fin;
+ }
+
++ /* verify received scalar */
++ if (crypto_bignum_is_zero(data->peer_scalar) ||
++ crypto_bignum_is_one(data->peer_scalar) ||
++ crypto_bignum_cmp(data->peer_scalar,
++ crypto_ec_get_order(data->grp->group)) >= 0) {
++ wpa_printf(MSG_INFO,
++ "EAP-PWD (server): received scalar is invalid");
++ goto fin;
++ }
++
++ /* verify received element */
++ if (!crypto_ec_point_is_on_curve(data->grp->group,
++ data->peer_element) ||
++ crypto_ec_point_is_at_infinity(data->grp->group,
++ data->peer_element)) {
++ wpa_printf(MSG_INFO,
++ "EAP-PWD (server): received element is invalid");
++ goto fin;
++ }
++
+ /* check to ensure peer's element is not in a small sub-group */
+ if (!crypto_bignum_is_one(cofactor)) {
+ if (crypto_ec_point_mul(data->grp->group, data->peer_element,
+--
+2.7.4
+
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 @@
+From d63edfa90243e9a7de6ae5c275032f2cc79fef95 Mon Sep 17 00:00:00 2001
+From: Mathy Vanhoef <mathy.vanhoef@nyu.edu>
+Date: Sun, 31 Mar 2019 17:26:01 +0200
+Subject: [PATCH 12/14] EAP-pwd server: Detect reflection attacks
+
+When processing an EAP-pwd Commit frame, verify that the peer's scalar
+and elliptic curve element differ from the one sent by the server. This
+prevents reflection attacks where the adversary reflects the scalar and
+element sent by the server. (CVE-2019-9497)
+
+The vulnerability allows an adversary to complete the EAP-pwd handshake
+as any user. However, the adversary does not learn the negotiated
+session key, meaning the subsequent 4-way handshake would fail. As a
+result, this cannot be abused to bypass authentication unless EAP-pwd is
+used in non-WLAN cases without any following key exchange that would
+require the attacker to learn the MSK.
+
+Signed-off-by: Mathy Vanhoef <mathy.vanhoef@nyu.edu>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-9497
+---
+ src/eap_server/eap_server_pwd.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c
+index 74979da..16057e9 100644
+--- a/src/eap_server/eap_server_pwd.c
++++ b/src/eap_server/eap_server_pwd.c
+@@ -753,6 +753,15 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
+ }
+ }
+
++ /* detect reflection attacks */
++ if (crypto_bignum_cmp(data->my_scalar, data->peer_scalar) == 0 ||
++ crypto_ec_point_cmp(data->grp->group, data->my_element,
++ data->peer_element) == 0) {
++ wpa_printf(MSG_INFO,
++ "EAP-PWD (server): detected reflection attack!");
++ goto fin;
++ }
++
+ /* compute the shared key, k */
+ if ((crypto_ec_point_mul(data->grp->group, data->grp->pwe,
+ data->peer_scalar, K) < 0) ||
+--
+2.7.4
+
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 @@
+From 8ad8585f91823ddcc3728155e288e0f9f872e31a Mon Sep 17 00:00:00 2001
+From: Mathy Vanhoef <mathy.vanhoef@nyu.edu>
+Date: Sun, 31 Mar 2019 17:43:44 +0200
+Subject: [PATCH 13/14] EAP-pwd client: Verify received scalar and element
+
+When processing an EAP-pwd Commit frame, the server's scalar and element
+(elliptic curve point) were not validated. This allowed an adversary to
+bypass authentication, and act as a rogue Access Point (AP) if the
+crypto implementation did not verify the validity of the EC point.
+
+Fix this vulnerability by assuring the received scalar lies within the
+valid range, and by checking that the received element is not the point
+at infinity and lies on the elliptic curve being used. (CVE-2019-9499)
+
+The vulnerability is only exploitable if OpenSSL version 1.0.2 or lower
+is used, or if LibreSSL or wolfssl is used. Newer versions of OpenSSL
+(and also BoringSSL) implicitly validate the elliptic curve point in
+EC_POINT_set_affine_coordinates_GFp(), preventing the attack.
+
+Signed-off-by: Mathy Vanhoef <mathy.vanhoef@nyu.edu>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-9499
+---
+ src/eap_peer/eap_pwd.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
+index 761c16a..5a05e54 100644
+--- a/src/eap_peer/eap_pwd.c
++++ b/src/eap_peer/eap_pwd.c
+@@ -594,6 +594,26 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
+ goto fin;
+ }
+
++ /* verify received scalar */
++ if (crypto_bignum_is_zero(data->server_scalar) ||
++ crypto_bignum_is_one(data->server_scalar) ||
++ crypto_bignum_cmp(data->server_scalar,
++ crypto_ec_get_order(data->grp->group)) >= 0) {
++ wpa_printf(MSG_INFO,
++ "EAP-PWD (peer): received scalar is invalid");
++ goto fin;
++ }
++
++ /* verify received element */
++ if (!crypto_ec_point_is_on_curve(data->grp->group,
++ data->server_element) ||
++ crypto_ec_point_is_at_infinity(data->grp->group,
++ data->server_element)) {
++ wpa_printf(MSG_INFO,
++ "EAP-PWD (peer): received element is invalid");
++ goto fin;
++ }
++
+ /* check to ensure server's element is not in a small sub-group */
+ if (!crypto_bignum_is_one(cofactor)) {
+ if (crypto_ec_point_mul(data->grp->group, data->server_element,
+--
+2.7.4
+
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 @@
+From 16d4f1069118aa19bfce013493e1ac5783f92f1d Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <jouni@codeaurora.org>
+Date: Fri, 5 Apr 2019 02:12:50 +0300
+Subject: [PATCH 14/14] EAP-pwd: Check element x,y coordinates explicitly
+
+This adds an explicit check for 0 < x,y < prime based on RFC 5931,
+2.8.5.2.2 requirement. The earlier checks might have covered this
+implicitly, but it is safer to avoid any dependency on implicit checks
+and specific crypto library behavior. (CVE-2019-9498 and CVE-2019-9499)
+
+Furthermore, this moves the EAP-pwd element and scalar parsing and
+validation steps into shared helper functions so that there is no need
+to maintain two separate copies of this common functionality between the
+server and peer implementations.
+
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Upstream-Status: Backport
+CVE: CVE-2019-9498
+CVE: CVE-2019-9499
+---
+ src/eap_common/eap_pwd_common.c | 106 ++++++++++++++++++++++++++++++++++++++++
+ src/eap_common/eap_pwd_common.h | 3 ++
+ src/eap_peer/eap_pwd.c | 45 ++---------------
+ src/eap_server/eap_server_pwd.c | 45 ++---------------
+ 4 files changed, 117 insertions(+), 82 deletions(-)
+
+diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
+index e49aaf8..c28b56d 100644
+--- a/src/eap_common/eap_pwd_common.c
++++ b/src/eap_common/eap_pwd_common.c
+@@ -428,3 +428,109 @@ int compute_keys(EAP_PWD_group *grp, const struct crypto_bignum *k,
+
+ return 1;
+ }
++
++
++static int eap_pwd_element_coord_ok(const struct crypto_bignum *prime,
++ const u8 *buf, size_t len)
++{
++ struct crypto_bignum *val;
++ int ok = 1;
++
++ val = crypto_bignum_init_set(buf, len);
++ if (!val || crypto_bignum_is_zero(val) ||
++ crypto_bignum_cmp(val, prime) >= 0)
++ ok = 0;
++ crypto_bignum_deinit(val, 0);
++ return ok;
++}
++
++
++struct crypto_ec_point * eap_pwd_get_element(EAP_PWD_group *group,
++ const u8 *buf)
++{
++ struct crypto_ec_point *element;
++ const struct crypto_bignum *prime;
++ size_t prime_len;
++ struct crypto_bignum *cofactor = NULL;
++
++ prime = crypto_ec_get_prime(group->group);
++ prime_len = crypto_ec_prime_len(group->group);
++
++ /* RFC 5931, 2.8.5.2.2: 0 < x,y < p */
++ if (!eap_pwd_element_coord_ok(prime, buf, prime_len) ||
++ !eap_pwd_element_coord_ok(prime, buf + prime_len, prime_len)) {
++ wpa_printf(MSG_INFO, "EAP-pwd: Invalid coordinate in element");
++ return NULL;
++ }
++
++ element = crypto_ec_point_from_bin(group->group, buf);
++ if (!element) {
++ wpa_printf(MSG_INFO, "EAP-pwd: EC point from element failed");
++ return NULL;
++ }
++
++ /* RFC 5931, 2.8.5.2.2: on curve and not the point at infinity */
++ if (!crypto_ec_point_is_on_curve(group->group, element) ||
++ crypto_ec_point_is_at_infinity(group->group, element)) {
++ wpa_printf(MSG_INFO, "EAP-pwd: Invalid element");
++ goto fail;
++ }
++
++ cofactor = crypto_bignum_init();
++ if (!cofactor || crypto_ec_cofactor(group->group, cofactor) < 0) {
++ wpa_printf(MSG_INFO,
++ "EAP-pwd: Unable to get cofactor for curve");
++ goto fail;
++ }
++
++ if (!crypto_bignum_is_one(cofactor)) {
++ struct crypto_ec_point *point;
++ int ok = 1;
++
++ /* check to ensure peer's element is not in a small sub-group */
++ point = crypto_ec_point_init(group->group);
++ if (!point ||
++ crypto_ec_point_mul(group->group, element,
++ cofactor, point) != 0 ||
++ crypto_ec_point_is_at_infinity(group->group, point))
++ ok = 0;
++ crypto_ec_point_deinit(point, 0);
++
++ if (!ok) {
++ wpa_printf(MSG_INFO,
++ "EAP-pwd: Small sub-group check on peer element failed");
++ goto fail;
++ }
++ }
++
++out:
++ crypto_bignum_deinit(cofactor, 0);
++ return element;
++fail:
++ crypto_ec_point_deinit(element, 0);
++ element = NULL;
++ goto out;
++}
++
++
++struct crypto_bignum * eap_pwd_get_scalar(EAP_PWD_group *group, const u8 *buf)
++{
++ struct crypto_bignum *scalar;
++ const struct crypto_bignum *order;
++ size_t order_len;
++
++ order = crypto_ec_get_order(group->group);
++ order_len = crypto_ec_order_len(group->group);
++
++ /* RFC 5931, 2.8.5.2: 1 < scalar < r */
++ scalar = crypto_bignum_init_set(buf, order_len);
++ if (!scalar || crypto_bignum_is_zero(scalar) ||
++ crypto_bignum_is_one(scalar) ||
++ crypto_bignum_cmp(scalar, order) >= 0) {
++ wpa_printf(MSG_INFO, "EAP-pwd: received scalar is invalid");
++ crypto_bignum_deinit(scalar, 0);
++ scalar = NULL;
++ }
++
++ return scalar;
++}
+diff --git a/src/eap_common/eap_pwd_common.h b/src/eap_common/eap_pwd_common.h
+index 6b07cf8..2387e59 100644
+--- a/src/eap_common/eap_pwd_common.h
++++ b/src/eap_common/eap_pwd_common.h
+@@ -67,5 +67,8 @@ int compute_keys(EAP_PWD_group *grp, const struct crypto_bignum *k,
+ struct crypto_hash * eap_pwd_h_init(void);
+ void eap_pwd_h_update(struct crypto_hash *hash, const u8 *data, size_t len);
+ void eap_pwd_h_final(struct crypto_hash *hash, u8 *digest);
++struct crypto_ec_point * eap_pwd_get_element(EAP_PWD_group *group,
++ const u8 *buf);
++struct crypto_bignum * eap_pwd_get_scalar(EAP_PWD_group *group, const u8 *buf);
+
+ #endif /* EAP_PWD_COMMON_H */
+diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
+index 5a05e54..f37b974 100644
+--- a/src/eap_peer/eap_pwd.c
++++ b/src/eap_peer/eap_pwd.c
+@@ -308,7 +308,7 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
+ const struct wpabuf *reqData,
+ const u8 *payload, size_t payload_len)
+ {
+- struct crypto_ec_point *K = NULL, *point = NULL;
++ struct crypto_ec_point *K = NULL;
+ struct crypto_bignum *mask = NULL, *cofactor = NULL;
+ const u8 *ptr = payload;
+ u8 *scalar = NULL, *element = NULL;
+@@ -572,63 +572,27 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
+ /* process the request */
+ data->k = crypto_bignum_init();
+ K = crypto_ec_point_init(data->grp->group);
+- point = crypto_ec_point_init(data->grp->group);
+- if (!data->k || !K || !point) {
++ if (!data->k || !K) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): peer data allocation "
+ "fail");
+ goto fin;
+ }
+
+ /* element, x then y, followed by scalar */
+- data->server_element = crypto_ec_point_from_bin(data->grp->group, ptr);
++ data->server_element = eap_pwd_get_element(data->grp, ptr);
+ if (!data->server_element) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): setting peer element "
+ "fail");
+ goto fin;
+ }
+ ptr += prime_len * 2;
+- data->server_scalar = crypto_bignum_init_set(ptr, order_len);
++ data->server_scalar = eap_pwd_get_scalar(data->grp, ptr);
+ if (!data->server_scalar) {
+ wpa_printf(MSG_INFO,
+ "EAP-PWD (peer): setting peer scalar fail");
+ goto fin;
+ }
+
+- /* verify received scalar */
+- if (crypto_bignum_is_zero(data->server_scalar) ||
+- crypto_bignum_is_one(data->server_scalar) ||
+- crypto_bignum_cmp(data->server_scalar,
+- crypto_ec_get_order(data->grp->group)) >= 0) {
+- wpa_printf(MSG_INFO,
+- "EAP-PWD (peer): received scalar is invalid");
+- goto fin;
+- }
+-
+- /* verify received element */
+- if (!crypto_ec_point_is_on_curve(data->grp->group,
+- data->server_element) ||
+- crypto_ec_point_is_at_infinity(data->grp->group,
+- data->server_element)) {
+- wpa_printf(MSG_INFO,
+- "EAP-PWD (peer): received element is invalid");
+- goto fin;
+- }
+-
+- /* check to ensure server's element is not in a small sub-group */
+- if (!crypto_bignum_is_one(cofactor)) {
+- if (crypto_ec_point_mul(data->grp->group, data->server_element,
+- cofactor, point) < 0) {
+- wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply "
+- "server element by order!\n");
+- goto fin;
+- }
+- if (crypto_ec_point_is_at_infinity(data->grp->group, point)) {
+- wpa_printf(MSG_INFO, "EAP-PWD (peer): server element "
+- "is at infinity!\n");
+- goto fin;
+- }
+- }
+-
+ /* compute the shared key, k */
+ if (crypto_ec_point_mul(data->grp->group, data->grp->pwe,
+ data->server_scalar, K) < 0 ||
+@@ -702,7 +666,6 @@ fin:
+ crypto_bignum_deinit(mask, 1);
+ crypto_bignum_deinit(cofactor, 1);
+ crypto_ec_point_deinit(K, 1);
+- crypto_ec_point_deinit(point, 1);
+ if (data->outbuf == NULL)
+ eap_pwd_state(data, FAILURE);
+ else
+diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c
+index 16057e9..f6c75cf 100644
+--- a/src/eap_server/eap_server_pwd.c
++++ b/src/eap_server/eap_server_pwd.c
+@@ -669,7 +669,7 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
+ {
+ const u8 *ptr;
+ struct crypto_bignum *cofactor = NULL;
+- struct crypto_ec_point *K = NULL, *point = NULL;
++ struct crypto_ec_point *K = NULL;
+ int res = 0;
+ size_t prime_len, order_len;
+
+@@ -688,9 +688,8 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
+
+ data->k = crypto_bignum_init();
+ cofactor = crypto_bignum_init();
+- point = crypto_ec_point_init(data->grp->group);
+ K = crypto_ec_point_init(data->grp->group);
+- if (!data->k || !cofactor || !point || !K) {
++ if (!data->k || !cofactor || !K) {
+ wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation "
+ "fail");
+ goto fin;
+@@ -704,55 +703,20 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
+
+ /* element, x then y, followed by scalar */
+ ptr = payload;
+- data->peer_element = crypto_ec_point_from_bin(data->grp->group, ptr);
++ data->peer_element = eap_pwd_get_element(data->grp, ptr);
+ if (!data->peer_element) {
+ wpa_printf(MSG_INFO, "EAP-PWD (server): setting peer element "
+ "fail");
+ goto fin;
+ }
+ ptr += prime_len * 2;
+- data->peer_scalar = crypto_bignum_init_set(ptr, order_len);
++ data->peer_scalar = eap_pwd_get_scalar(data->grp, ptr);
+ if (!data->peer_scalar) {
+ wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation "
+ "fail");
+ goto fin;
+ }
+
+- /* verify received scalar */
+- if (crypto_bignum_is_zero(data->peer_scalar) ||
+- crypto_bignum_is_one(data->peer_scalar) ||
+- crypto_bignum_cmp(data->peer_scalar,
+- crypto_ec_get_order(data->grp->group)) >= 0) {
+- wpa_printf(MSG_INFO,
+- "EAP-PWD (server): received scalar is invalid");
+- goto fin;
+- }
+-
+- /* verify received element */
+- if (!crypto_ec_point_is_on_curve(data->grp->group,
+- data->peer_element) ||
+- crypto_ec_point_is_at_infinity(data->grp->group,
+- data->peer_element)) {
+- wpa_printf(MSG_INFO,
+- "EAP-PWD (server): received element is invalid");
+- goto fin;
+- }
+-
+- /* check to ensure peer's element is not in a small sub-group */
+- if (!crypto_bignum_is_one(cofactor)) {
+- if (crypto_ec_point_mul(data->grp->group, data->peer_element,
+- cofactor, point) != 0) {
+- wpa_printf(MSG_INFO, "EAP-PWD (server): cannot "
+- "multiply peer element by order");
+- goto fin;
+- }
+- if (crypto_ec_point_is_at_infinity(data->grp->group, point)) {
+- wpa_printf(MSG_INFO, "EAP-PWD (server): peer element "
+- "is at infinity!\n");
+- goto fin;
+- }
+- }
+-
+ /* detect reflection attacks */
+ if (crypto_bignum_cmp(data->my_scalar, data->peer_scalar) == 0 ||
+ crypto_ec_point_cmp(data->grp->group, data->my_element,
+@@ -804,7 +768,6 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
+
+ fin:
+ crypto_ec_point_deinit(K, 1);
+- crypto_ec_point_deinit(point, 1);
+ crypto_bignum_deinit(cofactor, 1);
+
+ if (res)
+--
+2.7.4
+
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 \
file://wpa_supplicant.conf-sane \
file://99_wpa_supplicant \
file://0001-replace-systemd-install-Alias-with-WantedBy.patch \
+ file://0001-OpenSSL-Use-constant-time-operations-for-private-big.patch \
+ file://0002-Add-helper-functions-for-constant-time-operations.patch \
+ file://0003-OpenSSL-Use-constant-time-selection-for-crypto_bignu.patch \
+ file://0004-EAP-pwd-Use-constant-time-and-memory-access-for-find.patch \
+ file://0005-SAE-Minimize-timing-differences-in-PWE-derivation.patch \
+ file://0006-SAE-Avoid-branches-in-is_quadratic_residue_blind.patch \
+ file://0007-SAE-Mask-timing-of-MODP-groups-22-23-24.patch \
+ file://0008-SAE-Use-const_time-selection-for-PWE-in-FFC.patch \
+ file://0009-SAE-Use-constant-time-operations-in-sae_test_pwd_see.patch \
+ file://0010-SAE-Fix-confirm-message-validation-in-error-cases.patch \
+ file://0011-EAP-pwd-server-Verify-received-scalar-and-element.patch \
+ file://0012-EAP-pwd-server-Detect-reflection-attacks.patch \
+ file://0013-EAP-pwd-client-Verify-received-scalar-and-element.patch \
+ file://0014-EAP-pwd-Check-element-x-y-coordinates-explicitly.patch \
+ file://0001-EAP-pwd-server-Fix-reassembly-buffer-handling.patch \
+ file://0003-EAP-pwd-peer-Fix-reassembly-buffer-handling.patch \
"
SRC_URI[md5sum] = "a68538fb62766f40f890125026c42c10"
SRC_URI[sha256sum] = "76ea6b06b7a2ea8e6d9eb1a9166166f1656e6d48c7508914f592100c95c73074"
--
2.17.1
next reply other threads:[~2019-06-19 18:04 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-19 18:04 Adrian Bunk [this message]
2019-06-19 18:30 ` ✗ patchtest: failure for wpa-supplicant: Fix CVE-2019-9494 CVE-2019-9495 CVE-2019-9496 CVE-2019-9497 CVE-2019-9498 CVE-2019-9499 CVE-2019-11555 Patchwork
2019-06-19 18:30 ` [warrior][PATCH] " akuster808
2019-06-19 18:56 ` Adrian Bunk
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190619180422.31204-1-bunk@stusta.de \
--to=bunk@stusta.de \
--cc=openembedded-core@lists.openembedded.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.