[wpa_supplicant] Cumulative patch from b8491ae5a

Also revert local solution for encrypted IMSI and use the upstream version.

Bug: 134177972
Test: Device boots up and connects to WPA3/OWE wifi networks, run traffic.
Test: Able to turn on/off softap, associate wifi STA, run traffic.
Test: Regression test passed (Bug: 137653009)
Change-Id: Ie34a0138a3a2039b03101c788b43acbb33f8332a
diff --git a/src/common/sae.c b/src/common/sae.c
index 0d56e55..0da7145 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -15,35 +15,22 @@
 #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;
 
-	if (!sae_suitable_group(group)) {
+#ifdef CONFIG_TESTING_OPTIONS
+	/* Allow all groups for testing purposes in non-production builds. */
+#else /* CONFIG_TESTING_OPTIONS */
+	if (!dragonfly_suitable_group(group, 0)) {
 		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));
@@ -134,58 +121,6 @@
 }
 
 
-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
@@ -200,103 +135,6 @@
 }
 
 
-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)
@@ -304,6 +142,8 @@
 	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);
 
@@ -317,8 +157,13 @@
 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
 			pwd_value, sae->tmp->prime_len);
 
-	if (const_time_memcmp(pwd_value, prime, sae->tmp->prime_len) >= 0)
-		return 0;
+	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. */
 
 	x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
 	if (!x_cand)
@@ -328,9 +173,12 @@
 	if (!y_sqr)
 		return -1;
 
-	res = is_quadratic_residue_blind(sae, prime, bits, qr, qnr, y_sqr);
+	res = dragonfly_is_quadratic_residue_blind(sae->tmp->ec, qr, qnr,
+						   y_sqr);
 	crypto_bignum_deinit(y_sqr, 1);
-	return res;
+	if (res < 0)
+		return res;
+	return const_time_select_int(in_range, res, 0);
 }
 
 
@@ -423,42 +271,6 @@
 }
 
 
-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)
@@ -477,7 +289,6 @@
 	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 */
@@ -494,14 +305,12 @@
 	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 (get_random_qr_qnr(prime, prime_len, sae->tmp->prime, bits,
-			      &qr, &qnr) < 0 ||
+	if (dragonfly_get_random_qr_qnr(sae->tmp->prime, &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;
@@ -768,48 +577,23 @@
 static int sae_derive_commit(struct sae_data *sae)
 {
 	struct crypto_bignum *mask;
-	int ret = -1;
-	unsigned int counter = 0;
+	int ret;
 
-	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:
+	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);
 	crypto_bignum_deinit(mask, 1);
-	return ret;
+	return ret ? -1 : 0;
 }