Revert "[wpa_supplicant] Cumulative patch from b8491ae5a"

This reverts commit 878cf7bcbf2d7d8f08c3d060b8c5fbfcf0743eda.

Reason for revert: git_master/sdk_phone_armv7-sdk

Change-Id: I6070fc5c1f9c20867f6dfce90e529e35578d572e
diff --git a/src/common/sae.c b/src/common/sae.c
index 0da7145..0d56e55 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -15,22 +15,35 @@
 #include "crypto/random.h"
 #include "crypto/dh_groups.h"
 #include "ieee802_11_defs.h"
-#include "dragonfly.h"
 #include "sae.h"
 
 
+static int sae_suitable_group(int group)
+{
+#ifdef CONFIG_TESTING_OPTIONS
+	/* Allow all groups for testing purposes in non-production builds. */
+	return 1;
+#else /* CONFIG_TESTING_OPTIONS */
+	/* Enforce REVmd rules on which SAE groups are suitable for production
+	 * purposes: FFC groups whose prime is >= 3072 bits and ECC groups
+	 * defined over a prime field whose prime is >= 256 bits. Furthermore,
+	 * ECC groups defined over a characteristic 2 finite field and ECC
+	 * groups with a co-factor greater than 1 are not suitable. */
+	return group == 19 || group == 20 || group == 21 ||
+		group == 28 || group == 29 || group == 30 ||
+		group == 15 || group == 16 || group == 17 || group == 18;
+#endif /* CONFIG_TESTING_OPTIONS */
+}
+
+
 int sae_set_group(struct sae_data *sae, int group)
 {
 	struct sae_temporary_data *tmp;
 
-#ifdef CONFIG_TESTING_OPTIONS
-	/* Allow all groups for testing purposes in non-production builds. */
-#else /* CONFIG_TESTING_OPTIONS */
-	if (!dragonfly_suitable_group(group, 0)) {
+	if (!sae_suitable_group(group)) {
 		wpa_printf(MSG_DEBUG, "SAE: Reject unsuitable group %d", group);
 		return -1;
 	}
-#endif /* CONFIG_TESTING_OPTIONS */
 
 	sae_clear_data(sae);
 	tmp = sae->tmp = os_zalloc(sizeof(*tmp));
@@ -121,6 +134,58 @@
 }
 
 
+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;
+}
+
+
+static struct crypto_bignum * sae_get_rand(struct sae_data *sae)
+{
+	u8 val[SAE_MAX_PRIME_LEN];
+	int iter = 0;
+	struct crypto_bignum *bn = NULL;
+	int order_len_bits = crypto_bignum_bits(sae->tmp->order);
+	size_t order_len = (order_len_bits + 7) / 8;
+
+	if (order_len > sizeof(val))
+		return NULL;
+
+	for (;;) {
+		if (iter++ > 100 || random_get_bytes(val, order_len) < 0)
+			return NULL;
+		if (order_len_bits % 8)
+			buf_shift_right(val, order_len, 8 - order_len_bits % 8);
+		bn = crypto_bignum_init_set(val, order_len);
+		if (bn == NULL)
+			return NULL;
+		if (crypto_bignum_is_zero(bn) ||
+		    crypto_bignum_is_one(bn) ||
+		    crypto_bignum_cmp(bn, sae->tmp->order) >= 0) {
+			crypto_bignum_deinit(bn, 0);
+			continue;
+		}
+		break;
+	}
+
+	os_memset(val, 0, order_len);
+	return bn;
+}
+
+
+static struct crypto_bignum * sae_get_rand_and_mask(struct sae_data *sae)
+{
+	crypto_bignum_deinit(sae->tmp->sae_rand, 1);
+	sae->tmp->sae_rand = sae_get_rand(sae);
+	if (sae->tmp->sae_rand == NULL)
+		return NULL;
+	return sae_get_rand(sae);
+}
+
+
 static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key)
 {
 	wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR
@@ -135,6 +200,103 @@
 }
 
 
+static struct crypto_bignum *
+get_rand_1_to_p_1(const u8 *prime, size_t prime_len, size_t prime_bits,
+		  int *r_odd)
+{
+	for (;;) {
+		struct crypto_bignum *r;
+		u8 tmp[SAE_MAX_ECC_PRIME_LEN];
+
+		if (random_get_bytes(tmp, prime_len) < 0)
+			break;
+		if (prime_bits % 8)
+			buf_shift_right(tmp, prime_len, 8 - prime_bits % 8);
+		if (os_memcmp(tmp, prime, prime_len) >= 0)
+			continue;
+		r = crypto_bignum_init_set(tmp, prime_len);
+		if (!r)
+			break;
+		if (crypto_bignum_is_zero(r)) {
+			crypto_bignum_deinit(r, 0);
+			continue;
+		}
+
+		*r_odd = tmp[prime_len - 1] & 0x01;
+		return r;
+	}
+
+	return NULL;
+}
+
+
+static int is_quadratic_residue_blind(struct sae_data *sae,
+				      const u8 *prime, size_t bits,
+				      const u8 *qr, const u8 *qnr,
+				      const struct crypto_bignum *y_sqr)
+{
+	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
+	 * whether it is a quadratic residue modulo p to avoid leaking
+	 * timing information while determining the Legendre symbol.
+	 *
+	 * v = y_sqr
+	 * r = a random number between 1 and p-1, inclusive
+	 * num = (v * r * r) modulo p
+	 */
+	r = get_rand_1_to_p_1(prime, prime_len, bits, &r_odd);
+	if (!r)
+		return -1;
+
+	num = crypto_bignum_init();
+	if (!num ||
+	    crypto_bignum_mulmod(y_sqr, r, sae->tmp->prime, num) < 0 ||
+	    crypto_bignum_mulmod(num, r, sae->tmp->prime, num) < 0)
+		goto fail;
+
+	/*
+	 * 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;
+	}
+	/* 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 u8 *qr, const u8 *qnr,
 				 u8 *pwd_value)
@@ -142,8 +304,6 @@
 	struct crypto_bignum *y_sqr, *x_cand;
 	int res;
 	size_t bits;
-	int cmp_prime;
-	unsigned int in_range;
 
 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
 
@@ -157,13 +317,8 @@
 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
 			pwd_value, sae->tmp->prime_len);
 
-	cmp_prime = const_time_memcmp(pwd_value, prime, sae->tmp->prime_len);
-	/* Create a const_time mask for selection based on prf result
-	 * being smaller than prime. */
-	in_range = const_time_fill_msb((unsigned int) cmp_prime);
-	/* The algorithm description would skip the next steps if
-	 * cmp_prime >= 0 (reutnr 0 here), but go through them regardless to
-	 * minimize externally observable differences in behavior. */
+	if (const_time_memcmp(pwd_value, prime, sae->tmp->prime_len) >= 0)
+		return 0;
 
 	x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
 	if (!x_cand)
@@ -173,12 +328,9 @@
 	if (!y_sqr)
 		return -1;
 
-	res = dragonfly_is_quadratic_residue_blind(sae->tmp->ec, qr, qnr,
-						   y_sqr);
+	res = is_quadratic_residue_blind(sae, prime, bits, qr, qnr, y_sqr);
 	crypto_bignum_deinit(y_sqr, 1);
-	if (res < 0)
-		return res;
-	return const_time_select_int(in_range, res, 0);
+	return res;
 }
 
 
@@ -271,6 +423,42 @@
 }
 
 
+static int get_random_qr_qnr(const u8 *prime, size_t prime_len,
+			     const struct crypto_bignum *prime_bn,
+			     size_t prime_bits, struct crypto_bignum **qr,
+			     struct crypto_bignum **qnr)
+{
+	*qr = NULL;
+	*qnr = NULL;
+
+	while (!(*qr) || !(*qnr)) {
+		u8 tmp[SAE_MAX_ECC_PRIME_LEN];
+		struct crypto_bignum *q;
+		int res;
+
+		if (random_get_bytes(tmp, prime_len) < 0)
+			break;
+		if (prime_bits % 8)
+			buf_shift_right(tmp, prime_len, 8 - prime_bits % 8);
+		if (os_memcmp(tmp, prime, prime_len) >= 0)
+			continue;
+		q = crypto_bignum_init_set(tmp, prime_len);
+		if (!q)
+			break;
+		res = crypto_bignum_legendre(q, prime_bn);
+
+		if (res == 1 && !(*qr))
+			*qr = q;
+		else if (res == -1 && !(*qnr))
+			*qnr = q;
+		else
+			crypto_bignum_deinit(q, 0);
+	}
+
+	return (*qr && *qnr) ? 0 : -1;
+}
+
+
 static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
 			      const u8 *addr2, const u8 *password,
 			      size_t password_len, const char *identifier)
@@ -289,6 +477,7 @@
 	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_*
 		       * mask */
@@ -305,12 +494,14 @@
 	if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
 				 prime_len) < 0)
 		goto fail;
+	bits = crypto_ec_prime_len_bits(sae->tmp->ec);
 
 	/*
 	 * Create a random quadratic residue (qr) and quadratic non-residue
 	 * (qnr) modulo p for blinding purposes during the loop.
 	 */
-	if (dragonfly_get_random_qr_qnr(sae->tmp->prime, &qr, &qnr) < 0 ||
+	if (get_random_qr_qnr(prime, prime_len, sae->tmp->prime, bits,
+			      &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;
@@ -577,23 +768,48 @@
 static int sae_derive_commit(struct sae_data *sae)
 {
 	struct crypto_bignum *mask;
-	int ret;
+	int ret = -1;
+	unsigned int counter = 0;
 
-	mask = crypto_bignum_init();
-	if (!sae->tmp->sae_rand)
-		sae->tmp->sae_rand = crypto_bignum_init();
-	if (!sae->tmp->own_commit_scalar)
-		sae->tmp->own_commit_scalar = crypto_bignum_init();
-	ret = !mask || !sae->tmp->sae_rand || !sae->tmp->own_commit_scalar ||
-		dragonfly_generate_scalar(sae->tmp->order, sae->tmp->sae_rand,
-					  mask,
-					  sae->tmp->own_commit_scalar) < 0 ||
-		(sae->tmp->ec &&
-		 sae_derive_commit_element_ecc(sae, mask) < 0) ||
-		(sae->tmp->dh &&
-		 sae_derive_commit_element_ffc(sae, mask) < 0);
+	do {
+		counter++;
+		if (counter > 100) {
+			/*
+			 * This cannot really happen in practice if the random
+			 * number generator is working. Anyway, to avoid even a
+			 * theoretical infinite loop, break out after 100
+			 * attemps.
+			 */
+			return -1;
+		}
+
+		mask = sae_get_rand_and_mask(sae);
+		if (mask == NULL) {
+			wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask");
+			return -1;
+		}
+
+		/* commit-scalar = (rand + mask) modulo r */
+		if (!sae->tmp->own_commit_scalar) {
+			sae->tmp->own_commit_scalar = crypto_bignum_init();
+			if (!sae->tmp->own_commit_scalar)
+				goto fail;
+		}
+		crypto_bignum_add(sae->tmp->sae_rand, mask,
+				  sae->tmp->own_commit_scalar);
+		crypto_bignum_mod(sae->tmp->own_commit_scalar, sae->tmp->order,
+				  sae->tmp->own_commit_scalar);
+	} while (crypto_bignum_is_zero(sae->tmp->own_commit_scalar) ||
+		 crypto_bignum_is_one(sae->tmp->own_commit_scalar));
+
+	if ((sae->tmp->ec && sae_derive_commit_element_ecc(sae, mask) < 0) ||
+	    (sae->tmp->dh && sae_derive_commit_element_ffc(sae, mask) < 0))
+		goto fail;
+
+	ret = 0;
+fail:
 	crypto_bignum_deinit(mask, 1);
-	return ret ? -1 : 0;
+	return ret;
 }