--- wpa_supplicant-2.6-bak/src/common/sae.c	2019-06-30 21:39:30.592000000 -0400
+++ wpa_supplicant-2.6/src/common/sae.c	2019-07-01 04:08:21.023000000 -0400
@@ -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"
@@ -262,15 +263,12 @@ static int sae_test_pwd_seed_ecc(struct
 				 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) */
@@ -279,7 +277,7 @@ static int sae_test_pwd_seed_ecc(struct
 			    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);
 
@@ -290,20 +288,13 @@ static int sae_test_pwd_seed_ecc(struct
 	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;
 }
 
 
@@ -423,25 +414,30 @@ static int sae_derive_pwe_ecc(struct sae
 	u8 addrs[2 * ETH_ALEN];
 	const u8 *addr[2];
 	size_t len[2];
-	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;
-
-	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;
+       int res = -1;
+       u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
+                      * mask */
+
+       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);
 
 	/*
@@ -450,7 +446,7 @@ static int sae_derive_pwe_ecc(struct sae
 	 */
 	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);
@@ -463,7 +459,7 @@ static int sae_derive_pwe_ecc(struct sae
 	 */
 	sae_pwd_seed_key(addr1, addr2, addrs);
 
-	addr[0] = password;
+       addr[0] = tmp_password;
 	len[0] = password_len;
 	addr[1] = &counter;
 	len[1] = sizeof(counter);
@@ -473,9 +469,8 @@ static int sae_derive_pwe_ecc(struct sae
 	 * 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 */
@@ -483,36 +478,46 @@ static int sae_derive_pwe_ecc(struct sae
 			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), 2, 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));
-
-			/*
-			 * 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);
-		}
+               /* 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);
+       }
+
+       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;
 	}
@@ -525,7 +530,6 @@ static int sae_derive_pwe_ecc(struct sae
 		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
@@ -537,6 +541,11 @@ static int sae_derive_pwe_ecc(struct sae
 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;
 }
