[OE-core] [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

akuster808 akuster808 at gmail.com
Wed Jun 19 18:30:59 UTC 2019



On 6/19/19 11:04 AM, Adrian Bunk wrote:
> Signed-off-by: Adrian Bunk <bunk at 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

A simple "affects: < {version}" help RP and myself from asking if master
is affected.

So is this fixed in master?

- armin
>
> 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 at 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 at codeaurora.org>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at codeaurora.org>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at codeaurora.org>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at codeaurora.org>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at codeaurora.org>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at codeaurora.org>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at codeaurora.org>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at codeaurora.org>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at codeaurora.org>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at codeaurora.org>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at codeaurora.org>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at codeaurora.org>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at nyu.edu>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at nyu.edu>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at nyu.edu>
> +Signed-off-by: Adrian Bunk <bunk at 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 at 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 at codeaurora.org>
> +Signed-off-by: Adrian Bunk <bunk at 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"



More information about the Openembedded-core mailing list