xref: /aosp_15_r20/external/wpa_supplicant_8/src/common/dragonfly.c (revision 03f9172ca588f91df233974f4258bab95191f931)
1*03f9172cSAndroid Build Coastguard Worker /*
2*03f9172cSAndroid Build Coastguard Worker  * Shared Dragonfly functionality
3*03f9172cSAndroid Build Coastguard Worker  * Copyright (c) 2012-2016, Jouni Malinen <[email protected]>
4*03f9172cSAndroid Build Coastguard Worker  * Copyright (c) 2019, The Linux Foundation
5*03f9172cSAndroid Build Coastguard Worker  *
6*03f9172cSAndroid Build Coastguard Worker  * This software may be distributed under the terms of the BSD license.
7*03f9172cSAndroid Build Coastguard Worker  * See README for more details.
8*03f9172cSAndroid Build Coastguard Worker  */
9*03f9172cSAndroid Build Coastguard Worker 
10*03f9172cSAndroid Build Coastguard Worker #include "utils/includes.h"
11*03f9172cSAndroid Build Coastguard Worker 
12*03f9172cSAndroid Build Coastguard Worker #include "utils/common.h"
13*03f9172cSAndroid Build Coastguard Worker #include "utils/const_time.h"
14*03f9172cSAndroid Build Coastguard Worker #include "crypto/crypto.h"
15*03f9172cSAndroid Build Coastguard Worker #include "dragonfly.h"
16*03f9172cSAndroid Build Coastguard Worker 
17*03f9172cSAndroid Build Coastguard Worker 
dragonfly_suitable_group(int group,int ecc_only)18*03f9172cSAndroid Build Coastguard Worker int dragonfly_suitable_group(int group, int ecc_only)
19*03f9172cSAndroid Build Coastguard Worker {
20*03f9172cSAndroid Build Coastguard Worker 	/* Enforce REVmd rules on which SAE groups are suitable for production
21*03f9172cSAndroid Build Coastguard Worker 	 * purposes: FFC groups whose prime is >= 3072 bits and ECC groups
22*03f9172cSAndroid Build Coastguard Worker 	 * defined over a prime field whose prime is >= 256 bits. Furthermore,
23*03f9172cSAndroid Build Coastguard Worker 	 * ECC groups defined over a characteristic 2 finite field and ECC
24*03f9172cSAndroid Build Coastguard Worker 	 * groups with a co-factor greater than 1 are not suitable. Disable
25*03f9172cSAndroid Build Coastguard Worker 	 * groups that use Brainpool curves as well for now since they leak more
26*03f9172cSAndroid Build Coastguard Worker 	 * timing information due to the prime not being close to a power of
27*03f9172cSAndroid Build Coastguard Worker 	 * two. */
28*03f9172cSAndroid Build Coastguard Worker 	return group == 19 || group == 20 || group == 21 ||
29*03f9172cSAndroid Build Coastguard Worker 		(!ecc_only &&
30*03f9172cSAndroid Build Coastguard Worker 		 (group == 15 || group == 16 || group == 17 || group == 18));
31*03f9172cSAndroid Build Coastguard Worker }
32*03f9172cSAndroid Build Coastguard Worker 
33*03f9172cSAndroid Build Coastguard Worker 
dragonfly_min_pwe_loop_iter(int group)34*03f9172cSAndroid Build Coastguard Worker unsigned int dragonfly_min_pwe_loop_iter(int group)
35*03f9172cSAndroid Build Coastguard Worker {
36*03f9172cSAndroid Build Coastguard Worker 	if (group == 22 || group == 23 || group == 24) {
37*03f9172cSAndroid Build Coastguard Worker 		/* FFC groups for which pwd-value is likely to be >= p
38*03f9172cSAndroid Build Coastguard Worker 		 * frequently */
39*03f9172cSAndroid Build Coastguard Worker 		return 40;
40*03f9172cSAndroid Build Coastguard Worker 	}
41*03f9172cSAndroid Build Coastguard Worker 
42*03f9172cSAndroid Build Coastguard Worker 	if (group == 1 || group == 2 || group == 5 || group == 14 ||
43*03f9172cSAndroid Build Coastguard Worker 	    group == 15 || group == 16 || group == 17 || group == 18) {
44*03f9172cSAndroid Build Coastguard Worker 		/* FFC groups that have prime that is close to a power of two */
45*03f9172cSAndroid Build Coastguard Worker 		return 1;
46*03f9172cSAndroid Build Coastguard Worker 	}
47*03f9172cSAndroid Build Coastguard Worker 
48*03f9172cSAndroid Build Coastguard Worker 	/* Default to 40 (this covers most ECC groups) */
49*03f9172cSAndroid Build Coastguard Worker 	return 40;
50*03f9172cSAndroid Build Coastguard Worker }
51*03f9172cSAndroid Build Coastguard Worker 
52*03f9172cSAndroid Build Coastguard Worker 
dragonfly_get_random_qr_qnr(const struct crypto_bignum * prime,struct crypto_bignum ** qr,struct crypto_bignum ** qnr)53*03f9172cSAndroid Build Coastguard Worker int dragonfly_get_random_qr_qnr(const struct crypto_bignum *prime,
54*03f9172cSAndroid Build Coastguard Worker 				struct crypto_bignum **qr,
55*03f9172cSAndroid Build Coastguard Worker 				struct crypto_bignum **qnr)
56*03f9172cSAndroid Build Coastguard Worker {
57*03f9172cSAndroid Build Coastguard Worker 	*qr = *qnr = NULL;
58*03f9172cSAndroid Build Coastguard Worker 
59*03f9172cSAndroid Build Coastguard Worker 	while (!(*qr) || !(*qnr)) {
60*03f9172cSAndroid Build Coastguard Worker 		struct crypto_bignum *tmp;
61*03f9172cSAndroid Build Coastguard Worker 		int res;
62*03f9172cSAndroid Build Coastguard Worker 
63*03f9172cSAndroid Build Coastguard Worker 		tmp = crypto_bignum_init();
64*03f9172cSAndroid Build Coastguard Worker 		if (!tmp || crypto_bignum_rand(tmp, prime) < 0) {
65*03f9172cSAndroid Build Coastguard Worker 			crypto_bignum_deinit(tmp, 0);
66*03f9172cSAndroid Build Coastguard Worker 			break;
67*03f9172cSAndroid Build Coastguard Worker 		}
68*03f9172cSAndroid Build Coastguard Worker 
69*03f9172cSAndroid Build Coastguard Worker 		res = crypto_bignum_legendre(tmp, prime);
70*03f9172cSAndroid Build Coastguard Worker 		if (res == 1 && !(*qr)) {
71*03f9172cSAndroid Build Coastguard Worker 			*qr = tmp;
72*03f9172cSAndroid Build Coastguard Worker 		} else if (res == -1 && !(*qnr)) {
73*03f9172cSAndroid Build Coastguard Worker 			*qnr = tmp;
74*03f9172cSAndroid Build Coastguard Worker 		} else {
75*03f9172cSAndroid Build Coastguard Worker 			crypto_bignum_deinit(tmp, 0);
76*03f9172cSAndroid Build Coastguard Worker 			if (res == -2)
77*03f9172cSAndroid Build Coastguard Worker 				break;
78*03f9172cSAndroid Build Coastguard Worker 		}
79*03f9172cSAndroid Build Coastguard Worker 	}
80*03f9172cSAndroid Build Coastguard Worker 
81*03f9172cSAndroid Build Coastguard Worker 	if (*qr && *qnr)
82*03f9172cSAndroid Build Coastguard Worker 		return 0;
83*03f9172cSAndroid Build Coastguard Worker 	crypto_bignum_deinit(*qr, 0);
84*03f9172cSAndroid Build Coastguard Worker 	crypto_bignum_deinit(*qnr, 0);
85*03f9172cSAndroid Build Coastguard Worker 	*qr = *qnr = NULL;
86*03f9172cSAndroid Build Coastguard Worker 	return -1;
87*03f9172cSAndroid Build Coastguard Worker }
88*03f9172cSAndroid Build Coastguard Worker 
89*03f9172cSAndroid Build Coastguard Worker 
90*03f9172cSAndroid Build Coastguard Worker static struct crypto_bignum *
dragonfly_get_rand_1_to_p_1(const struct crypto_bignum * prime)91*03f9172cSAndroid Build Coastguard Worker dragonfly_get_rand_1_to_p_1(const struct crypto_bignum *prime)
92*03f9172cSAndroid Build Coastguard Worker {
93*03f9172cSAndroid Build Coastguard Worker 	struct crypto_bignum *tmp, *pm1, *one;
94*03f9172cSAndroid Build Coastguard Worker 
95*03f9172cSAndroid Build Coastguard Worker 	tmp = crypto_bignum_init();
96*03f9172cSAndroid Build Coastguard Worker 	pm1 = crypto_bignum_init();
97*03f9172cSAndroid Build Coastguard Worker 	one = crypto_bignum_init_set((const u8 *) "\x01", 1);
98*03f9172cSAndroid Build Coastguard Worker 	if (!tmp || !pm1 || !one ||
99*03f9172cSAndroid Build Coastguard Worker 	    crypto_bignum_sub(prime, one, pm1) < 0 ||
100*03f9172cSAndroid Build Coastguard Worker 	    crypto_bignum_rand(tmp, pm1) < 0 ||
101*03f9172cSAndroid Build Coastguard Worker 	    crypto_bignum_add(tmp, one, tmp) < 0) {
102*03f9172cSAndroid Build Coastguard Worker 		crypto_bignum_deinit(tmp, 0);
103*03f9172cSAndroid Build Coastguard Worker 		tmp = NULL;
104*03f9172cSAndroid Build Coastguard Worker 	}
105*03f9172cSAndroid Build Coastguard Worker 
106*03f9172cSAndroid Build Coastguard Worker 	crypto_bignum_deinit(pm1, 0);
107*03f9172cSAndroid Build Coastguard Worker 	crypto_bignum_deinit(one, 0);
108*03f9172cSAndroid Build Coastguard Worker 	return tmp;
109*03f9172cSAndroid Build Coastguard Worker }
110*03f9172cSAndroid Build Coastguard Worker 
111*03f9172cSAndroid Build Coastguard Worker 
dragonfly_is_quadratic_residue_blind(struct crypto_ec * ec,const u8 * qr,const u8 * qnr,const struct crypto_bignum * val)112*03f9172cSAndroid Build Coastguard Worker int dragonfly_is_quadratic_residue_blind(struct crypto_ec *ec,
113*03f9172cSAndroid Build Coastguard Worker 					 const u8 *qr, const u8 *qnr,
114*03f9172cSAndroid Build Coastguard Worker 					 const struct crypto_bignum *val)
115*03f9172cSAndroid Build Coastguard Worker {
116*03f9172cSAndroid Build Coastguard Worker 	struct crypto_bignum *r, *num, *qr_or_qnr = NULL;
117*03f9172cSAndroid Build Coastguard Worker 	int check, res = -1;
118*03f9172cSAndroid Build Coastguard Worker 	u8 qr_or_qnr_bin[DRAGONFLY_MAX_ECC_PRIME_LEN];
119*03f9172cSAndroid Build Coastguard Worker 	const struct crypto_bignum *prime;
120*03f9172cSAndroid Build Coastguard Worker 	size_t prime_len;
121*03f9172cSAndroid Build Coastguard Worker 	unsigned int mask;
122*03f9172cSAndroid Build Coastguard Worker 
123*03f9172cSAndroid Build Coastguard Worker 	prime = crypto_ec_get_prime(ec);
124*03f9172cSAndroid Build Coastguard Worker 	prime_len = crypto_ec_prime_len(ec);
125*03f9172cSAndroid Build Coastguard Worker 
126*03f9172cSAndroid Build Coastguard Worker 	/*
127*03f9172cSAndroid Build Coastguard Worker 	 * Use a blinding technique to mask val while determining whether it is
128*03f9172cSAndroid Build Coastguard Worker 	 * a quadratic residue modulo p to avoid leaking timing information
129*03f9172cSAndroid Build Coastguard Worker 	 * while determining the Legendre symbol.
130*03f9172cSAndroid Build Coastguard Worker 	 *
131*03f9172cSAndroid Build Coastguard Worker 	 * v = val
132*03f9172cSAndroid Build Coastguard Worker 	 * r = a random number between 1 and p-1, inclusive
133*03f9172cSAndroid Build Coastguard Worker 	 * num = (v * r * r) modulo p
134*03f9172cSAndroid Build Coastguard Worker 	 */
135*03f9172cSAndroid Build Coastguard Worker 	r = dragonfly_get_rand_1_to_p_1(prime);
136*03f9172cSAndroid Build Coastguard Worker 	if (!r)
137*03f9172cSAndroid Build Coastguard Worker 		return -1;
138*03f9172cSAndroid Build Coastguard Worker 
139*03f9172cSAndroid Build Coastguard Worker 	num = crypto_bignum_init();
140*03f9172cSAndroid Build Coastguard Worker 	if (!num ||
141*03f9172cSAndroid Build Coastguard Worker 	    crypto_bignum_mulmod(val, r, prime, num) < 0 ||
142*03f9172cSAndroid Build Coastguard Worker 	    crypto_bignum_mulmod(num, r, prime, num) < 0)
143*03f9172cSAndroid Build Coastguard Worker 		goto fail;
144*03f9172cSAndroid Build Coastguard Worker 
145*03f9172cSAndroid Build Coastguard Worker 	/*
146*03f9172cSAndroid Build Coastguard Worker 	 * Need to minimize differences in handling different cases, so try to
147*03f9172cSAndroid Build Coastguard Worker 	 * avoid branches and timing differences.
148*03f9172cSAndroid Build Coastguard Worker 	 *
149*03f9172cSAndroid Build Coastguard Worker 	 * If r is odd:
150*03f9172cSAndroid Build Coastguard Worker 	 * num = (num * qr) module p
151*03f9172cSAndroid Build Coastguard Worker 	 * LGR(num, p) = 1 ==> quadratic residue
152*03f9172cSAndroid Build Coastguard Worker 	 * else:
153*03f9172cSAndroid Build Coastguard Worker 	 * num = (num * qnr) module p
154*03f9172cSAndroid Build Coastguard Worker 	 * LGR(num, p) = -1 ==> quadratic residue
155*03f9172cSAndroid Build Coastguard Worker 	 *
156*03f9172cSAndroid Build Coastguard Worker 	 * mask is set to !odd(r)
157*03f9172cSAndroid Build Coastguard Worker 	 */
158*03f9172cSAndroid Build Coastguard Worker 	mask = const_time_is_zero(crypto_bignum_is_odd(r));
159*03f9172cSAndroid Build Coastguard Worker 	const_time_select_bin(mask, qnr, qr, prime_len, qr_or_qnr_bin);
160*03f9172cSAndroid Build Coastguard Worker 	qr_or_qnr = crypto_bignum_init_set(qr_or_qnr_bin, prime_len);
161*03f9172cSAndroid Build Coastguard Worker 	if (!qr_or_qnr ||
162*03f9172cSAndroid Build Coastguard Worker 	    crypto_bignum_mulmod(num, qr_or_qnr, prime, num) < 0)
163*03f9172cSAndroid Build Coastguard Worker 		goto fail;
164*03f9172cSAndroid Build Coastguard Worker 	/* branchless version of check = odd(r) ? 1 : -1, */
165*03f9172cSAndroid Build Coastguard Worker 	check = const_time_select_int(mask, -1, 1);
166*03f9172cSAndroid Build Coastguard Worker 
167*03f9172cSAndroid Build Coastguard Worker 	/* Determine the Legendre symbol on the masked value */
168*03f9172cSAndroid Build Coastguard Worker 	res = crypto_bignum_legendre(num, prime);
169*03f9172cSAndroid Build Coastguard Worker 	if (res == -2) {
170*03f9172cSAndroid Build Coastguard Worker 		res = -1;
171*03f9172cSAndroid Build Coastguard Worker 		goto fail;
172*03f9172cSAndroid Build Coastguard Worker 	}
173*03f9172cSAndroid Build Coastguard Worker 	/* branchless version of res = res == check
174*03f9172cSAndroid Build Coastguard Worker 	 * (res is -1, 0, or 1; check is -1 or 1) */
175*03f9172cSAndroid Build Coastguard Worker 	mask = const_time_eq(res, check);
176*03f9172cSAndroid Build Coastguard Worker 	res = const_time_select_int(mask, 1, 0);
177*03f9172cSAndroid Build Coastguard Worker fail:
178*03f9172cSAndroid Build Coastguard Worker 	crypto_bignum_deinit(num, 1);
179*03f9172cSAndroid Build Coastguard Worker 	crypto_bignum_deinit(r, 1);
180*03f9172cSAndroid Build Coastguard Worker 	crypto_bignum_deinit(qr_or_qnr, 1);
181*03f9172cSAndroid Build Coastguard Worker 	return res;
182*03f9172cSAndroid Build Coastguard Worker }
183*03f9172cSAndroid Build Coastguard Worker 
184*03f9172cSAndroid Build Coastguard Worker 
dragonfly_get_rand_2_to_r_1(struct crypto_bignum * val,const struct crypto_bignum * order)185*03f9172cSAndroid Build Coastguard Worker static int dragonfly_get_rand_2_to_r_1(struct crypto_bignum *val,
186*03f9172cSAndroid Build Coastguard Worker 				       const struct crypto_bignum *order)
187*03f9172cSAndroid Build Coastguard Worker {
188*03f9172cSAndroid Build Coastguard Worker 	return crypto_bignum_rand(val, order) == 0 &&
189*03f9172cSAndroid Build Coastguard Worker 		!crypto_bignum_is_zero(val) &&
190*03f9172cSAndroid Build Coastguard Worker 		!crypto_bignum_is_one(val);
191*03f9172cSAndroid Build Coastguard Worker }
192*03f9172cSAndroid Build Coastguard Worker 
193*03f9172cSAndroid Build Coastguard Worker 
dragonfly_generate_scalar(const struct crypto_bignum * order,struct crypto_bignum * _rand,struct crypto_bignum * _mask,struct crypto_bignum * scalar)194*03f9172cSAndroid Build Coastguard Worker int dragonfly_generate_scalar(const struct crypto_bignum *order,
195*03f9172cSAndroid Build Coastguard Worker 			      struct crypto_bignum *_rand,
196*03f9172cSAndroid Build Coastguard Worker 			      struct crypto_bignum *_mask,
197*03f9172cSAndroid Build Coastguard Worker 			      struct crypto_bignum *scalar)
198*03f9172cSAndroid Build Coastguard Worker {
199*03f9172cSAndroid Build Coastguard Worker 	int count;
200*03f9172cSAndroid Build Coastguard Worker 
201*03f9172cSAndroid Build Coastguard Worker 	/* Select two random values rand,mask such that 1 < rand,mask < r and
202*03f9172cSAndroid Build Coastguard Worker 	 * rand + mask mod r > 1. */
203*03f9172cSAndroid Build Coastguard Worker 	for (count = 0; count < 100; count++) {
204*03f9172cSAndroid Build Coastguard Worker 		if (dragonfly_get_rand_2_to_r_1(_rand, order) &&
205*03f9172cSAndroid Build Coastguard Worker 		    dragonfly_get_rand_2_to_r_1(_mask, order) &&
206*03f9172cSAndroid Build Coastguard Worker 		    crypto_bignum_add(_rand, _mask, scalar) == 0 &&
207*03f9172cSAndroid Build Coastguard Worker 		    crypto_bignum_mod(scalar, order, scalar) == 0 &&
208*03f9172cSAndroid Build Coastguard Worker 		    !crypto_bignum_is_zero(scalar) &&
209*03f9172cSAndroid Build Coastguard Worker 		    !crypto_bignum_is_one(scalar))
210*03f9172cSAndroid Build Coastguard Worker 			return 0;
211*03f9172cSAndroid Build Coastguard Worker 	}
212*03f9172cSAndroid Build Coastguard Worker 
213*03f9172cSAndroid Build Coastguard Worker 	/* This should not be reachable in practice if the random number
214*03f9172cSAndroid Build Coastguard Worker 	 * generation is working. */
215*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_INFO,
216*03f9172cSAndroid Build Coastguard Worker 		   "dragonfly: Unable to get randomness for own scalar");
217*03f9172cSAndroid Build Coastguard Worker 	return -1;
218*03f9172cSAndroid Build Coastguard Worker }
219*03f9172cSAndroid Build Coastguard Worker 
220*03f9172cSAndroid Build Coastguard Worker 
221*03f9172cSAndroid Build Coastguard Worker /* res = sqrt(val) */
dragonfly_sqrt(struct crypto_ec * ec,const struct crypto_bignum * val,struct crypto_bignum * res)222*03f9172cSAndroid Build Coastguard Worker int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val,
223*03f9172cSAndroid Build Coastguard Worker 		   struct crypto_bignum *res)
224*03f9172cSAndroid Build Coastguard Worker {
225*03f9172cSAndroid Build Coastguard Worker 	const struct crypto_bignum *prime;
226*03f9172cSAndroid Build Coastguard Worker 	struct crypto_bignum *tmp, *one;
227*03f9172cSAndroid Build Coastguard Worker 	int ret = 0;
228*03f9172cSAndroid Build Coastguard Worker 	u8 prime_bin[DRAGONFLY_MAX_ECC_PRIME_LEN];
229*03f9172cSAndroid Build Coastguard Worker 	size_t prime_len;
230*03f9172cSAndroid Build Coastguard Worker 
231*03f9172cSAndroid Build Coastguard Worker 	/* For prime p such that p = 3 mod 4, sqrt(w) = w^((p+1)/4) mod p */
232*03f9172cSAndroid Build Coastguard Worker 
233*03f9172cSAndroid Build Coastguard Worker 	prime = crypto_ec_get_prime(ec);
234*03f9172cSAndroid Build Coastguard Worker 	prime_len = crypto_ec_prime_len(ec);
235*03f9172cSAndroid Build Coastguard Worker 	tmp = crypto_bignum_init();
236*03f9172cSAndroid Build Coastguard Worker 	one = crypto_bignum_init_uint(1);
237*03f9172cSAndroid Build Coastguard Worker 
238*03f9172cSAndroid Build Coastguard Worker 	if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin),
239*03f9172cSAndroid Build Coastguard Worker 				 prime_len) < 0 ||
240*03f9172cSAndroid Build Coastguard Worker 	    (prime_bin[prime_len - 1] & 0x03) != 3 ||
241*03f9172cSAndroid Build Coastguard Worker 	    !tmp || !one ||
242*03f9172cSAndroid Build Coastguard Worker 	    /* tmp = (p+1)/4 */
243*03f9172cSAndroid Build Coastguard Worker 	    crypto_bignum_add(prime, one, tmp) < 0 ||
244*03f9172cSAndroid Build Coastguard Worker 	    crypto_bignum_rshift(tmp, 2, tmp) < 0 ||
245*03f9172cSAndroid Build Coastguard Worker 	    /* res = sqrt(val) */
246*03f9172cSAndroid Build Coastguard Worker 	    crypto_bignum_exptmod(val, tmp, prime, res) < 0)
247*03f9172cSAndroid Build Coastguard Worker 		ret = -1;
248*03f9172cSAndroid Build Coastguard Worker 
249*03f9172cSAndroid Build Coastguard Worker 	crypto_bignum_deinit(tmp, 0);
250*03f9172cSAndroid Build Coastguard Worker 	crypto_bignum_deinit(one, 0);
251*03f9172cSAndroid Build Coastguard Worker 	return ret;
252*03f9172cSAndroid Build Coastguard Worker }
253