xref: /freebsd/contrib/wpa/src/common/dragonfly.c (revision ec080394e21815b6852dee5cba6155bbba26a3ff)
1206b73d0SCy Schubert /*
2206b73d0SCy Schubert  * Shared Dragonfly functionality
3206b73d0SCy Schubert  * Copyright (c) 2012-2016, Jouni Malinen <j@w1.fi>
4206b73d0SCy Schubert  * Copyright (c) 2019, The Linux Foundation
5206b73d0SCy Schubert  *
6206b73d0SCy Schubert  * This software may be distributed under the terms of the BSD license.
7206b73d0SCy Schubert  * See README for more details.
8206b73d0SCy Schubert  */
9206b73d0SCy Schubert 
10206b73d0SCy Schubert #include "utils/includes.h"
11206b73d0SCy Schubert 
12206b73d0SCy Schubert #include "utils/common.h"
13206b73d0SCy Schubert #include "utils/const_time.h"
14206b73d0SCy Schubert #include "crypto/crypto.h"
15206b73d0SCy Schubert #include "dragonfly.h"
16206b73d0SCy Schubert 
17206b73d0SCy Schubert 
18206b73d0SCy Schubert int dragonfly_suitable_group(int group, int ecc_only)
19206b73d0SCy Schubert {
20206b73d0SCy Schubert 	/* Enforce REVmd rules on which SAE groups are suitable for production
21206b73d0SCy Schubert 	 * purposes: FFC groups whose prime is >= 3072 bits and ECC groups
22206b73d0SCy Schubert 	 * defined over a prime field whose prime is >= 256 bits. Furthermore,
23206b73d0SCy Schubert 	 * ECC groups defined over a characteristic 2 finite field and ECC
24206b73d0SCy Schubert 	 * groups with a co-factor greater than 1 are not suitable. Disable
25206b73d0SCy Schubert 	 * groups that use Brainpool curves as well for now since they leak more
26206b73d0SCy Schubert 	 * timing information due to the prime not being close to a power of
27206b73d0SCy Schubert 	 * two. */
28206b73d0SCy Schubert 	return group == 19 || group == 20 || group == 21 ||
29206b73d0SCy Schubert 		(!ecc_only &&
30206b73d0SCy Schubert 		 (group == 15 || group == 16 || group == 17 || group == 18));
31206b73d0SCy Schubert }
32206b73d0SCy Schubert 
33206b73d0SCy Schubert 
34206b73d0SCy Schubert unsigned int dragonfly_min_pwe_loop_iter(int group)
35206b73d0SCy Schubert {
36206b73d0SCy Schubert 	if (group == 22 || group == 23 || group == 24) {
37206b73d0SCy Schubert 		/* FFC groups for which pwd-value is likely to be >= p
38206b73d0SCy Schubert 		 * frequently */
39206b73d0SCy Schubert 		return 40;
40206b73d0SCy Schubert 	}
41206b73d0SCy Schubert 
42206b73d0SCy Schubert 	if (group == 1 || group == 2 || group == 5 || group == 14 ||
43206b73d0SCy Schubert 	    group == 15 || group == 16 || group == 17 || group == 18) {
44206b73d0SCy Schubert 		/* FFC groups that have prime that is close to a power of two */
45206b73d0SCy Schubert 		return 1;
46206b73d0SCy Schubert 	}
47206b73d0SCy Schubert 
48206b73d0SCy Schubert 	/* Default to 40 (this covers most ECC groups) */
49206b73d0SCy Schubert 	return 40;
50206b73d0SCy Schubert }
51206b73d0SCy Schubert 
52206b73d0SCy Schubert 
53206b73d0SCy Schubert int dragonfly_get_random_qr_qnr(const struct crypto_bignum *prime,
54206b73d0SCy Schubert 				struct crypto_bignum **qr,
55206b73d0SCy Schubert 				struct crypto_bignum **qnr)
56206b73d0SCy Schubert {
57206b73d0SCy Schubert 	*qr = *qnr = NULL;
58206b73d0SCy Schubert 
59206b73d0SCy Schubert 	while (!(*qr) || !(*qnr)) {
60206b73d0SCy Schubert 		struct crypto_bignum *tmp;
61206b73d0SCy Schubert 		int res;
62206b73d0SCy Schubert 
63206b73d0SCy Schubert 		tmp = crypto_bignum_init();
64206b73d0SCy Schubert 		if (!tmp || crypto_bignum_rand(tmp, prime) < 0) {
65206b73d0SCy Schubert 			crypto_bignum_deinit(tmp, 0);
66206b73d0SCy Schubert 			break;
67206b73d0SCy Schubert 		}
68206b73d0SCy Schubert 
69206b73d0SCy Schubert 		res = crypto_bignum_legendre(tmp, prime);
70206b73d0SCy Schubert 		if (res == 1 && !(*qr))
71206b73d0SCy Schubert 			*qr = tmp;
72206b73d0SCy Schubert 		else if (res == -1 && !(*qnr))
73206b73d0SCy Schubert 			*qnr = tmp;
74206b73d0SCy Schubert 		else
75206b73d0SCy Schubert 			crypto_bignum_deinit(tmp, 0);
76206b73d0SCy Schubert 	}
77206b73d0SCy Schubert 
78206b73d0SCy Schubert 	if (*qr && *qnr)
79206b73d0SCy Schubert 		return 0;
80206b73d0SCy Schubert 	crypto_bignum_deinit(*qr, 0);
81206b73d0SCy Schubert 	crypto_bignum_deinit(*qnr, 0);
82206b73d0SCy Schubert 	*qr = *qnr = NULL;
83206b73d0SCy Schubert 	return -1;
84206b73d0SCy Schubert }
85206b73d0SCy Schubert 
86206b73d0SCy Schubert 
87206b73d0SCy Schubert static struct crypto_bignum *
88206b73d0SCy Schubert dragonfly_get_rand_1_to_p_1(const struct crypto_bignum *prime)
89206b73d0SCy Schubert {
90206b73d0SCy Schubert 	struct crypto_bignum *tmp, *pm1, *one;
91206b73d0SCy Schubert 
92206b73d0SCy Schubert 	tmp = crypto_bignum_init();
93206b73d0SCy Schubert 	pm1 = crypto_bignum_init();
94206b73d0SCy Schubert 	one = crypto_bignum_init_set((const u8 *) "\x01", 1);
95206b73d0SCy Schubert 	if (!tmp || !pm1 || !one ||
96206b73d0SCy Schubert 	    crypto_bignum_sub(prime, one, pm1) < 0 ||
97206b73d0SCy Schubert 	    crypto_bignum_rand(tmp, pm1) < 0 ||
98206b73d0SCy Schubert 	    crypto_bignum_add(tmp, one, tmp) < 0) {
99206b73d0SCy Schubert 		crypto_bignum_deinit(tmp, 0);
100206b73d0SCy Schubert 		tmp = NULL;
101206b73d0SCy Schubert 	}
102206b73d0SCy Schubert 
103206b73d0SCy Schubert 	crypto_bignum_deinit(pm1, 0);
104206b73d0SCy Schubert 	crypto_bignum_deinit(one, 0);
105206b73d0SCy Schubert 	return tmp;
106206b73d0SCy Schubert }
107206b73d0SCy Schubert 
108206b73d0SCy Schubert 
109206b73d0SCy Schubert int dragonfly_is_quadratic_residue_blind(struct crypto_ec *ec,
110206b73d0SCy Schubert 					 const u8 *qr, const u8 *qnr,
111206b73d0SCy Schubert 					 const struct crypto_bignum *val)
112206b73d0SCy Schubert {
113206b73d0SCy Schubert 	struct crypto_bignum *r, *num, *qr_or_qnr = NULL;
114206b73d0SCy Schubert 	int check, res = -1;
115206b73d0SCy Schubert 	u8 qr_or_qnr_bin[DRAGONFLY_MAX_ECC_PRIME_LEN];
116206b73d0SCy Schubert 	const struct crypto_bignum *prime;
117206b73d0SCy Schubert 	size_t prime_len;
118206b73d0SCy Schubert 	unsigned int mask;
119206b73d0SCy Schubert 
120206b73d0SCy Schubert 	prime = crypto_ec_get_prime(ec);
121206b73d0SCy Schubert 	prime_len = crypto_ec_prime_len(ec);
122206b73d0SCy Schubert 
123206b73d0SCy Schubert 	/*
124206b73d0SCy Schubert 	 * Use a blinding technique to mask val while determining whether it is
125206b73d0SCy Schubert 	 * a quadratic residue modulo p to avoid leaking timing information
126206b73d0SCy Schubert 	 * while determining the Legendre symbol.
127206b73d0SCy Schubert 	 *
128206b73d0SCy Schubert 	 * v = val
129206b73d0SCy Schubert 	 * r = a random number between 1 and p-1, inclusive
130206b73d0SCy Schubert 	 * num = (v * r * r) modulo p
131206b73d0SCy Schubert 	 */
132206b73d0SCy Schubert 	r = dragonfly_get_rand_1_to_p_1(prime);
133206b73d0SCy Schubert 	if (!r)
134206b73d0SCy Schubert 		return -1;
135206b73d0SCy Schubert 
136206b73d0SCy Schubert 	num = crypto_bignum_init();
137206b73d0SCy Schubert 	if (!num ||
138206b73d0SCy Schubert 	    crypto_bignum_mulmod(val, r, prime, num) < 0 ||
139206b73d0SCy Schubert 	    crypto_bignum_mulmod(num, r, prime, num) < 0)
140206b73d0SCy Schubert 		goto fail;
141206b73d0SCy Schubert 
142206b73d0SCy Schubert 	/*
143206b73d0SCy Schubert 	 * Need to minimize differences in handling different cases, so try to
144206b73d0SCy Schubert 	 * avoid branches and timing differences.
145206b73d0SCy Schubert 	 *
146206b73d0SCy Schubert 	 * If r is odd:
147206b73d0SCy Schubert 	 * num = (num * qr) module p
148206b73d0SCy Schubert 	 * LGR(num, p) = 1 ==> quadratic residue
149206b73d0SCy Schubert 	 * else:
150206b73d0SCy Schubert 	 * num = (num * qnr) module p
151206b73d0SCy Schubert 	 * LGR(num, p) = -1 ==> quadratic residue
152206b73d0SCy Schubert 	 *
153206b73d0SCy Schubert 	 * mask is set to !odd(r)
154206b73d0SCy Schubert 	 */
155206b73d0SCy Schubert 	mask = const_time_is_zero(crypto_bignum_is_odd(r));
156206b73d0SCy Schubert 	const_time_select_bin(mask, qnr, qr, prime_len, qr_or_qnr_bin);
157206b73d0SCy Schubert 	qr_or_qnr = crypto_bignum_init_set(qr_or_qnr_bin, prime_len);
158206b73d0SCy Schubert 	if (!qr_or_qnr ||
159206b73d0SCy Schubert 	    crypto_bignum_mulmod(num, qr_or_qnr, prime, num) < 0)
160206b73d0SCy Schubert 		goto fail;
161206b73d0SCy Schubert 	/* branchless version of check = odd(r) ? 1 : -1, */
162206b73d0SCy Schubert 	check = const_time_select_int(mask, -1, 1);
163206b73d0SCy Schubert 
164206b73d0SCy Schubert 	/* Determine the Legendre symbol on the masked value */
165206b73d0SCy Schubert 	res = crypto_bignum_legendre(num, prime);
166206b73d0SCy Schubert 	if (res == -2) {
167206b73d0SCy Schubert 		res = -1;
168206b73d0SCy Schubert 		goto fail;
169206b73d0SCy Schubert 	}
170206b73d0SCy Schubert 	/* branchless version of res = res == check
171206b73d0SCy Schubert 	 * (res is -1, 0, or 1; check is -1 or 1) */
172206b73d0SCy Schubert 	mask = const_time_eq(res, check);
173206b73d0SCy Schubert 	res = const_time_select_int(mask, 1, 0);
174206b73d0SCy Schubert fail:
175206b73d0SCy Schubert 	crypto_bignum_deinit(num, 1);
176206b73d0SCy Schubert 	crypto_bignum_deinit(r, 1);
177206b73d0SCy Schubert 	crypto_bignum_deinit(qr_or_qnr, 1);
178206b73d0SCy Schubert 	return res;
179206b73d0SCy Schubert }
180206b73d0SCy Schubert 
181206b73d0SCy Schubert 
182206b73d0SCy Schubert static int dragonfly_get_rand_2_to_r_1(struct crypto_bignum *val,
183206b73d0SCy Schubert 				       const struct crypto_bignum *order)
184206b73d0SCy Schubert {
185206b73d0SCy Schubert 	return crypto_bignum_rand(val, order) == 0 &&
186206b73d0SCy Schubert 		!crypto_bignum_is_zero(val) &&
187206b73d0SCy Schubert 		!crypto_bignum_is_one(val);
188206b73d0SCy Schubert }
189206b73d0SCy Schubert 
190206b73d0SCy Schubert 
191206b73d0SCy Schubert int dragonfly_generate_scalar(const struct crypto_bignum *order,
192206b73d0SCy Schubert 			      struct crypto_bignum *_rand,
193206b73d0SCy Schubert 			      struct crypto_bignum *_mask,
194206b73d0SCy Schubert 			      struct crypto_bignum *scalar)
195206b73d0SCy Schubert {
196206b73d0SCy Schubert 	int count;
197206b73d0SCy Schubert 
198206b73d0SCy Schubert 	/* Select two random values rand,mask such that 1 < rand,mask < r and
199206b73d0SCy Schubert 	 * rand + mask mod r > 1. */
200206b73d0SCy Schubert 	for (count = 0; count < 100; count++) {
201206b73d0SCy Schubert 		if (dragonfly_get_rand_2_to_r_1(_rand, order) &&
202206b73d0SCy Schubert 		    dragonfly_get_rand_2_to_r_1(_mask, order) &&
203206b73d0SCy Schubert 		    crypto_bignum_add(_rand, _mask, scalar) == 0 &&
204206b73d0SCy Schubert 		    crypto_bignum_mod(scalar, order, scalar) == 0 &&
205206b73d0SCy Schubert 		    !crypto_bignum_is_zero(scalar) &&
206206b73d0SCy Schubert 		    !crypto_bignum_is_one(scalar))
207206b73d0SCy Schubert 			return 0;
208206b73d0SCy Schubert 	}
209206b73d0SCy Schubert 
210206b73d0SCy Schubert 	/* This should not be reachable in practice if the random number
211206b73d0SCy Schubert 	 * generation is working. */
212206b73d0SCy Schubert 	wpa_printf(MSG_INFO,
213206b73d0SCy Schubert 		   "dragonfly: Unable to get randomness for own scalar");
214206b73d0SCy Schubert 	return -1;
215206b73d0SCy Schubert }
216*ec080394SCy Schubert 
217*ec080394SCy Schubert 
218*ec080394SCy Schubert /* res = sqrt(val) */
219*ec080394SCy Schubert int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val,
220*ec080394SCy Schubert 		   struct crypto_bignum *res)
221*ec080394SCy Schubert {
222*ec080394SCy Schubert 	const struct crypto_bignum *prime;
223*ec080394SCy Schubert 	struct crypto_bignum *tmp, *one;
224*ec080394SCy Schubert 	int ret = 0;
225*ec080394SCy Schubert 	u8 prime_bin[DRAGONFLY_MAX_ECC_PRIME_LEN];
226*ec080394SCy Schubert 	size_t prime_len;
227*ec080394SCy Schubert 
228*ec080394SCy Schubert 	/* For prime p such that p = 3 mod 4, sqrt(w) = w^((p+1)/4) mod p */
229*ec080394SCy Schubert 
230*ec080394SCy Schubert 	prime = crypto_ec_get_prime(ec);
231*ec080394SCy Schubert 	prime_len = crypto_ec_prime_len(ec);
232*ec080394SCy Schubert 	tmp = crypto_bignum_init();
233*ec080394SCy Schubert 	one = crypto_bignum_init_uint(1);
234*ec080394SCy Schubert 
235*ec080394SCy Schubert 	if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin),
236*ec080394SCy Schubert 				 prime_len) < 0 ||
237*ec080394SCy Schubert 	    (prime_bin[prime_len - 1] & 0x03) != 3 ||
238*ec080394SCy Schubert 	    !tmp || !one ||
239*ec080394SCy Schubert 	    /* tmp = (p+1)/4 */
240*ec080394SCy Schubert 	    crypto_bignum_add(prime, one, tmp) < 0 ||
241*ec080394SCy Schubert 	    crypto_bignum_rshift(tmp, 2, tmp) < 0 ||
242*ec080394SCy Schubert 	    /* res = sqrt(val) */
243*ec080394SCy Schubert 	    crypto_bignum_exptmod(val, tmp, prime, res) < 0)
244*ec080394SCy Schubert 		ret = -1;
245*ec080394SCy Schubert 
246*ec080394SCy Schubert 	crypto_bignum_deinit(tmp, 0);
247*ec080394SCy Schubert 	crypto_bignum_deinit(one, 0);
248*ec080394SCy Schubert 	return ret;
249*ec080394SCy Schubert }
250