diff options
Diffstat (limited to 'meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/CVE-2022-23303-4.patch')
-rw-r--r-- | meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/CVE-2022-23303-4.patch | 609 |
1 files changed, 609 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/CVE-2022-23303-4.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/CVE-2022-23303-4.patch new file mode 100644 index 0000000000..21e65ba961 --- /dev/null +++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/CVE-2022-23303-4.patch | |||
@@ -0,0 +1,609 @@ | |||
1 | From 208e5687ff2e48622e28d8888ce5444a54353bbd Mon Sep 17 00:00:00 2001 | ||
2 | From: Jouni Malinen <jouni@codeaurora.org> | ||
3 | Date: Tue, 27 Aug 2019 16:33:15 +0300 | ||
4 | Subject: [PATCH 1/4] crypto: Add more bignum/EC helper functions | ||
5 | |||
6 | These are needed for implementing SAE hash-to-element. | ||
7 | |||
8 | Signed-off-by: Jouni Malinen <jouni@codeaurora.org> | ||
9 | |||
10 | Upstream-Status: Backport | ||
11 | https://w1.fi/security/2022-1/ | ||
12 | |||
13 | CVE: CVE-2022-23303 CVE-2022-23304 | ||
14 | Signed-off-by: Steve Sakoman <steve@sakoman.com> | ||
15 | |||
16 | --- | ||
17 | src/crypto/crypto.h | 45 ++++++++++++++++++ | ||
18 | src/crypto/crypto_openssl.c | 94 +++++++++++++++++++++++++++++++++++++ | ||
19 | src/crypto/crypto_wolfssl.c | 66 ++++++++++++++++++++++++++ | ||
20 | 3 files changed, 205 insertions(+) | ||
21 | |||
22 | diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h | ||
23 | index 15f8ad04cea4..68476dbce96c 100644 | ||
24 | --- a/src/crypto/crypto.h | ||
25 | +++ b/src/crypto/crypto.h | ||
26 | @@ -518,6 +518,13 @@ struct crypto_bignum * crypto_bignum_init(void); | ||
27 | */ | ||
28 | struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len); | ||
29 | |||
30 | +/** | ||
31 | + * crypto_bignum_init_set - Allocate memory for bignum and set the value (uint) | ||
32 | + * @val: Value to set | ||
33 | + * Returns: Pointer to allocated bignum or %NULL on failure | ||
34 | + */ | ||
35 | +struct crypto_bignum * crypto_bignum_init_uint(unsigned int val); | ||
36 | + | ||
37 | /** | ||
38 | * crypto_bignum_deinit - Free bignum | ||
39 | * @n: Bignum from crypto_bignum_init() or crypto_bignum_init_set() | ||
40 | @@ -612,6 +619,19 @@ int crypto_bignum_div(const struct crypto_bignum *a, | ||
41 | const struct crypto_bignum *b, | ||
42 | struct crypto_bignum *c); | ||
43 | |||
44 | +/** | ||
45 | + * crypto_bignum_addmod - d = a + b (mod c) | ||
46 | + * @a: Bignum | ||
47 | + * @b: Bignum | ||
48 | + * @c: Bignum | ||
49 | + * @d: Bignum; used to store the result of (a + b) % c | ||
50 | + * Returns: 0 on success, -1 on failure | ||
51 | + */ | ||
52 | +int crypto_bignum_addmod(const struct crypto_bignum *a, | ||
53 | + const struct crypto_bignum *b, | ||
54 | + const struct crypto_bignum *c, | ||
55 | + struct crypto_bignum *d); | ||
56 | + | ||
57 | /** | ||
58 | * crypto_bignum_mulmod - d = a * b (mod c) | ||
59 | * @a: Bignum | ||
60 | @@ -625,6 +645,28 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a, | ||
61 | const struct crypto_bignum *c, | ||
62 | struct crypto_bignum *d); | ||
63 | |||
64 | +/** | ||
65 | + * crypto_bignum_sqrmod - c = a^2 (mod b) | ||
66 | + * @a: Bignum | ||
67 | + * @b: Bignum | ||
68 | + * @c: Bignum; used to store the result of a^2 % b | ||
69 | + * Returns: 0 on success, -1 on failure | ||
70 | + */ | ||
71 | +int crypto_bignum_sqrmod(const struct crypto_bignum *a, | ||
72 | + const struct crypto_bignum *b, | ||
73 | + struct crypto_bignum *c); | ||
74 | + | ||
75 | +/** | ||
76 | + * crypto_bignum_sqrtmod - returns sqrt(a) (mod b) | ||
77 | + * @a: Bignum | ||
78 | + * @b: Bignum | ||
79 | + * @c: Bignum; used to store the result | ||
80 | + * Returns: 0 on success, -1 on failure | ||
81 | + */ | ||
82 | +int crypto_bignum_sqrtmod(const struct crypto_bignum *a, | ||
83 | + const struct crypto_bignum *b, | ||
84 | + struct crypto_bignum *c); | ||
85 | + | ||
86 | /** | ||
87 | * crypto_bignum_rshift - r = a >> n | ||
88 | * @a: Bignum | ||
89 | @@ -731,6 +773,9 @@ const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e); | ||
90 | */ | ||
91 | const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e); | ||
92 | |||
93 | +const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e); | ||
94 | +const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e); | ||
95 | + | ||
96 | /** | ||
97 | * struct crypto_ec_point - Elliptic curve point | ||
98 | * | ||
99 | diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c | ||
100 | index bab33a537293..ed463105e8f1 100644 | ||
101 | --- a/src/crypto/crypto_openssl.c | ||
102 | +++ b/src/crypto/crypto_openssl.c | ||
103 | @@ -1283,6 +1283,24 @@ struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len) | ||
104 | } | ||
105 | |||
106 | |||
107 | +struct crypto_bignum * crypto_bignum_init_uint(unsigned int val) | ||
108 | +{ | ||
109 | + BIGNUM *bn; | ||
110 | + | ||
111 | + if (TEST_FAIL()) | ||
112 | + return NULL; | ||
113 | + | ||
114 | + bn = BN_new(); | ||
115 | + if (!bn) | ||
116 | + return NULL; | ||
117 | + if (BN_set_word(bn, val) != 1) { | ||
118 | + BN_free(bn); | ||
119 | + return NULL; | ||
120 | + } | ||
121 | + return (struct crypto_bignum *) bn; | ||
122 | +} | ||
123 | + | ||
124 | + | ||
125 | void crypto_bignum_deinit(struct crypto_bignum *n, int clear) | ||
126 | { | ||
127 | if (clear) | ||
128 | @@ -1449,6 +1467,28 @@ int crypto_bignum_div(const struct crypto_bignum *a, | ||
129 | } | ||
130 | |||
131 | |||
132 | +int crypto_bignum_addmod(const struct crypto_bignum *a, | ||
133 | + const struct crypto_bignum *b, | ||
134 | + const struct crypto_bignum *c, | ||
135 | + struct crypto_bignum *d) | ||
136 | +{ | ||
137 | + int res; | ||
138 | + BN_CTX *bnctx; | ||
139 | + | ||
140 | + if (TEST_FAIL()) | ||
141 | + return -1; | ||
142 | + | ||
143 | + bnctx = BN_CTX_new(); | ||
144 | + if (!bnctx) | ||
145 | + return -1; | ||
146 | + res = BN_mod_add((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b, | ||
147 | + (const BIGNUM *) c, bnctx); | ||
148 | + BN_CTX_free(bnctx); | ||
149 | + | ||
150 | + return res ? 0 : -1; | ||
151 | +} | ||
152 | + | ||
153 | + | ||
154 | int crypto_bignum_mulmod(const struct crypto_bignum *a, | ||
155 | const struct crypto_bignum *b, | ||
156 | const struct crypto_bignum *c, | ||
157 | @@ -1472,6 +1512,48 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a, | ||
158 | } | ||
159 | |||
160 | |||
161 | +int crypto_bignum_sqrmod(const struct crypto_bignum *a, | ||
162 | + const struct crypto_bignum *b, | ||
163 | + struct crypto_bignum *c) | ||
164 | +{ | ||
165 | + int res; | ||
166 | + BN_CTX *bnctx; | ||
167 | + | ||
168 | + if (TEST_FAIL()) | ||
169 | + return -1; | ||
170 | + | ||
171 | + bnctx = BN_CTX_new(); | ||
172 | + if (!bnctx) | ||
173 | + return -1; | ||
174 | + res = BN_mod_sqr((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b, | ||
175 | + bnctx); | ||
176 | + BN_CTX_free(bnctx); | ||
177 | + | ||
178 | + return res ? 0 : -1; | ||
179 | +} | ||
180 | + | ||
181 | + | ||
182 | +int crypto_bignum_sqrtmod(const struct crypto_bignum *a, | ||
183 | + const struct crypto_bignum *b, | ||
184 | + struct crypto_bignum *c) | ||
185 | +{ | ||
186 | + BN_CTX *bnctx; | ||
187 | + BIGNUM *res; | ||
188 | + | ||
189 | + if (TEST_FAIL()) | ||
190 | + return -1; | ||
191 | + | ||
192 | + bnctx = BN_CTX_new(); | ||
193 | + if (!bnctx) | ||
194 | + return -1; | ||
195 | + res = BN_mod_sqrt((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b, | ||
196 | + bnctx); | ||
197 | + BN_CTX_free(bnctx); | ||
198 | + | ||
199 | + return res ? 0 : -1; | ||
200 | +} | ||
201 | + | ||
202 | + | ||
203 | int crypto_bignum_rshift(const struct crypto_bignum *a, int n, | ||
204 | struct crypto_bignum *r) | ||
205 | { | ||
206 | @@ -1682,6 +1764,18 @@ const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e) | ||
207 | } | ||
208 | |||
209 | |||
210 | +const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e) | ||
211 | +{ | ||
212 | + return (const struct crypto_bignum *) e->a; | ||
213 | +} | ||
214 | + | ||
215 | + | ||
216 | +const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e) | ||
217 | +{ | ||
218 | + return (const struct crypto_bignum *) e->b; | ||
219 | +} | ||
220 | + | ||
221 | + | ||
222 | void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear) | ||
223 | { | ||
224 | if (clear) | ||
225 | diff --git a/src/crypto/crypto_wolfssl.c b/src/crypto/crypto_wolfssl.c | ||
226 | index 4cedab4367cd..e9894b335e53 100644 | ||
227 | --- a/src/crypto/crypto_wolfssl.c | ||
228 | +++ b/src/crypto/crypto_wolfssl.c | ||
229 | @@ -1042,6 +1042,26 @@ struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len) | ||
230 | } | ||
231 | |||
232 | |||
233 | +struct crypto_bignum * crypto_bignum_init_uint(unsigned int val) | ||
234 | +{ | ||
235 | + mp_int *a; | ||
236 | + | ||
237 | + if (TEST_FAIL()) | ||
238 | + return NULL; | ||
239 | + | ||
240 | + a = (mp_int *) crypto_bignum_init(); | ||
241 | + if (!a) | ||
242 | + return NULL; | ||
243 | + | ||
244 | + if (mp_set_int(a, val) != MP_OKAY) { | ||
245 | + os_free(a); | ||
246 | + a = NULL; | ||
247 | + } | ||
248 | + | ||
249 | + return (struct crypto_bignum *) a; | ||
250 | +} | ||
251 | + | ||
252 | + | ||
253 | void crypto_bignum_deinit(struct crypto_bignum *n, int clear) | ||
254 | { | ||
255 | if (!n) | ||
256 | @@ -1168,6 +1188,19 @@ int crypto_bignum_div(const struct crypto_bignum *a, | ||
257 | } | ||
258 | |||
259 | |||
260 | +int crypto_bignum_addmod(const struct crypto_bignum *a, | ||
261 | + const struct crypto_bignum *b, | ||
262 | + const struct crypto_bignum *c, | ||
263 | + struct crypto_bignum *d) | ||
264 | +{ | ||
265 | + if (TEST_FAIL()) | ||
266 | + return -1; | ||
267 | + | ||
268 | + return mp_addmod((mp_int *) a, (mp_int *) b, (mp_int *) c, | ||
269 | + (mp_int *) d) == MP_OKAY ? 0 : -1; | ||
270 | +} | ||
271 | + | ||
272 | + | ||
273 | int crypto_bignum_mulmod(const struct crypto_bignum *a, | ||
274 | const struct crypto_bignum *b, | ||
275 | const struct crypto_bignum *m, | ||
276 | @@ -1181,6 +1214,27 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a, | ||
277 | } | ||
278 | |||
279 | |||
280 | +int crypto_bignum_sqrmod(const struct crypto_bignum *a, | ||
281 | + const struct crypto_bignum *b, | ||
282 | + struct crypto_bignum *c) | ||
283 | +{ | ||
284 | + if (TEST_FAIL()) | ||
285 | + return -1; | ||
286 | + | ||
287 | + return mp_sqrmod((mp_int *) a, (mp_int *) b, | ||
288 | + (mp_int *) c) == MP_OKAY ? 0 : -1; | ||
289 | +} | ||
290 | + | ||
291 | + | ||
292 | +int crypto_bignum_sqrtmod(const struct crypto_bignum *a, | ||
293 | + const struct crypto_bignum *b, | ||
294 | + struct crypto_bignum *c) | ||
295 | +{ | ||
296 | + /* TODO */ | ||
297 | + return -1; | ||
298 | +} | ||
299 | + | ||
300 | + | ||
301 | int crypto_bignum_rshift(const struct crypto_bignum *a, int n, | ||
302 | struct crypto_bignum *r) | ||
303 | { | ||
304 | @@ -1386,6 +1440,18 @@ const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e) | ||
305 | } | ||
306 | |||
307 | |||
308 | +const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e) | ||
309 | +{ | ||
310 | + return (const struct crypto_bignum *) &e->a; | ||
311 | +} | ||
312 | + | ||
313 | + | ||
314 | +const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e) | ||
315 | +{ | ||
316 | + return (const struct crypto_bignum *) &e->b; | ||
317 | +} | ||
318 | + | ||
319 | + | ||
320 | void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear) | ||
321 | { | ||
322 | ecc_point *point = (ecc_point *) p; | ||
323 | -- | ||
324 | 2.25.1 | ||
325 | |||
326 | From 2232d3d5f188b65dbb6c823ac62175412739eb16 Mon Sep 17 00:00:00 2001 | ||
327 | From: Jouni Malinen <j@w1.fi> | ||
328 | Date: Fri, 7 Jan 2022 13:47:16 +0200 | ||
329 | Subject: [PATCH 2/4] dragonfly: Add sqrt() helper function | ||
330 | |||
331 | This is a backport of "SAE: Move sqrt() implementation into a helper | ||
332 | function" to introduce the helper function needed for the following | ||
333 | patches. | ||
334 | |||
335 | Signed-off-by: Jouni Malinen <j@w1.fi> | ||
336 | --- | ||
337 | src/common/dragonfly.c | 34 ++++++++++++++++++++++++++++++++++ | ||
338 | src/common/dragonfly.h | 2 ++ | ||
339 | 2 files changed, 36 insertions(+) | ||
340 | |||
341 | diff --git a/src/common/dragonfly.c b/src/common/dragonfly.c | ||
342 | index 547be66f1561..1e842716668e 100644 | ||
343 | --- a/src/common/dragonfly.c | ||
344 | +++ b/src/common/dragonfly.c | ||
345 | @@ -213,3 +213,37 @@ int dragonfly_generate_scalar(const struct crypto_bignum *order, | ||
346 | "dragonfly: Unable to get randomness for own scalar"); | ||
347 | return -1; | ||
348 | } | ||
349 | + | ||
350 | + | ||
351 | +/* res = sqrt(val) */ | ||
352 | +int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val, | ||
353 | + struct crypto_bignum *res) | ||
354 | +{ | ||
355 | + const struct crypto_bignum *prime; | ||
356 | + struct crypto_bignum *tmp, *one; | ||
357 | + int ret = 0; | ||
358 | + u8 prime_bin[DRAGONFLY_MAX_ECC_PRIME_LEN]; | ||
359 | + size_t prime_len; | ||
360 | + | ||
361 | + /* For prime p such that p = 3 mod 4, sqrt(w) = w^((p+1)/4) mod p */ | ||
362 | + | ||
363 | + prime = crypto_ec_get_prime(ec); | ||
364 | + prime_len = crypto_ec_prime_len(ec); | ||
365 | + tmp = crypto_bignum_init(); | ||
366 | + one = crypto_bignum_init_uint(1); | ||
367 | + | ||
368 | + if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin), | ||
369 | + prime_len) < 0 || | ||
370 | + (prime_bin[prime_len - 1] & 0x03) != 3 || | ||
371 | + !tmp || !one || | ||
372 | + /* tmp = (p+1)/4 */ | ||
373 | + crypto_bignum_add(prime, one, tmp) < 0 || | ||
374 | + crypto_bignum_rshift(tmp, 2, tmp) < 0 || | ||
375 | + /* res = sqrt(val) */ | ||
376 | + crypto_bignum_exptmod(val, tmp, prime, res) < 0) | ||
377 | + ret = -1; | ||
378 | + | ||
379 | + crypto_bignum_deinit(tmp, 0); | ||
380 | + crypto_bignum_deinit(one, 0); | ||
381 | + return ret; | ||
382 | +} | ||
383 | diff --git a/src/common/dragonfly.h b/src/common/dragonfly.h | ||
384 | index ec3dd593eda4..84d67f575c54 100644 | ||
385 | --- a/src/common/dragonfly.h | ||
386 | +++ b/src/common/dragonfly.h | ||
387 | @@ -27,5 +27,7 @@ int dragonfly_generate_scalar(const struct crypto_bignum *order, | ||
388 | struct crypto_bignum *_rand, | ||
389 | struct crypto_bignum *_mask, | ||
390 | struct crypto_bignum *scalar); | ||
391 | +int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val, | ||
392 | + struct crypto_bignum *res); | ||
393 | |||
394 | #endif /* DRAGONFLY_H */ | ||
395 | -- | ||
396 | 2.25.1 | ||
397 | |||
398 | From fe534b0baaa8c0e6ddeb24cf529d6e50e33dc501 Mon Sep 17 00:00:00 2001 | ||
399 | From: Jouni Malinen <j@w1.fi> | ||
400 | Date: Fri, 7 Jan 2022 13:47:16 +0200 | ||
401 | Subject: [PATCH 3/4] SAE: Derive the y coordinate for PWE with own | ||
402 | implementation | ||
403 | |||
404 | The crypto_ec_point_solve_y_coord() wrapper function might not use | ||
405 | constant time operations in the crypto library and as such, could leak | ||
406 | side channel information about the password that is used to generate the | ||
407 | PWE in the hunting and pecking loop. As such, calculate the two possible | ||
408 | y coordinate values and pick the correct one to use with constant time | ||
409 | selection. | ||
410 | |||
411 | Signed-off-by: Jouni Malinen <j@w1.fi> | ||
412 | --- | ||
413 | src/common/sae.c | 47 +++++++++++++++++++++++++++++++++-------------- | ||
414 | 1 file changed, 33 insertions(+), 14 deletions(-) | ||
415 | |||
416 | diff --git a/src/common/sae.c b/src/common/sae.c | ||
417 | index 08fdbfd18173..8d79ed962768 100644 | ||
418 | --- a/src/common/sae.c | ||
419 | +++ b/src/common/sae.c | ||
420 | @@ -286,14 +286,16 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, | ||
421 | int pwd_seed_odd = 0; | ||
422 | u8 prime[SAE_MAX_ECC_PRIME_LEN]; | ||
423 | size_t prime_len; | ||
424 | - struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL; | ||
425 | + struct crypto_bignum *x = NULL, *y = NULL, *qr = NULL, *qnr = NULL; | ||
426 | u8 x_bin[SAE_MAX_ECC_PRIME_LEN]; | ||
427 | u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN]; | ||
428 | u8 qr_bin[SAE_MAX_ECC_PRIME_LEN]; | ||
429 | u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN]; | ||
430 | + u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN]; | ||
431 | int res = -1; | ||
432 | u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_* | ||
433 | * mask */ | ||
434 | + unsigned int is_eq; | ||
435 | |||
436 | os_memset(x_bin, 0, sizeof(x_bin)); | ||
437 | |||
438 | @@ -402,25 +404,42 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, | ||
439 | goto fail; | ||
440 | } | ||
441 | |||
442 | - if (!sae->tmp->pwe_ecc) | ||
443 | - sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec); | ||
444 | - if (!sae->tmp->pwe_ecc) | ||
445 | - res = -1; | ||
446 | - else | ||
447 | - res = crypto_ec_point_solve_y_coord(sae->tmp->ec, | ||
448 | - sae->tmp->pwe_ecc, x, | ||
449 | - pwd_seed_odd); | ||
450 | - if (res < 0) { | ||
451 | - /* | ||
452 | - * This should not happen since we already checked that there | ||
453 | - * is a result. | ||
454 | - */ | ||
455 | + /* y = sqrt(x^3 + ax + b) mod p | ||
456 | + * if LSB(save) == LSB(y): PWE = (x, y) | ||
457 | + * else: PWE = (x, p - y) | ||
458 | + * | ||
459 | + * Calculate y and the two possible values for PWE and after that, | ||
460 | + * use constant time selection to copy the correct alternative. | ||
461 | + */ | ||
462 | + y = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x); | ||
463 | + if (!y || | ||
464 | + dragonfly_sqrt(sae->tmp->ec, y, y) < 0 || | ||
465 | + crypto_bignum_to_bin(y, x_y, SAE_MAX_ECC_PRIME_LEN, | ||
466 | + prime_len) < 0 || | ||
467 | + crypto_bignum_sub(sae->tmp->prime, y, y) < 0 || | ||
468 | + crypto_bignum_to_bin(y, x_y + SAE_MAX_ECC_PRIME_LEN, | ||
469 | + SAE_MAX_ECC_PRIME_LEN, prime_len) < 0) { | ||
470 | wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); | ||
471 | + goto fail; | ||
472 | + } | ||
473 | + | ||
474 | + is_eq = const_time_eq(pwd_seed_odd, x_y[prime_len - 1] & 0x01); | ||
475 | + const_time_select_bin(is_eq, x_y, x_y + SAE_MAX_ECC_PRIME_LEN, | ||
476 | + prime_len, x_y + prime_len); | ||
477 | + os_memcpy(x_y, x_bin, prime_len); | ||
478 | + wpa_hexdump_key(MSG_DEBUG, "SAE: PWE", x_y, 2 * prime_len); | ||
479 | + crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1); | ||
480 | + sae->tmp->pwe_ecc = crypto_ec_point_from_bin(sae->tmp->ec, x_y); | ||
481 | + if (!sae->tmp->pwe_ecc) { | ||
482 | + wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE"); | ||
483 | + res = -1; | ||
484 | } | ||
485 | |||
486 | fail: | ||
487 | + forced_memzero(x_y, sizeof(x_y)); | ||
488 | crypto_bignum_deinit(qr, 0); | ||
489 | crypto_bignum_deinit(qnr, 0); | ||
490 | + crypto_bignum_deinit(y, 1); | ||
491 | os_free(dummy_password); | ||
492 | bin_clear_free(tmp_password, password_len); | ||
493 | crypto_bignum_deinit(x, 1); | ||
494 | -- | ||
495 | 2.25.1 | ||
496 | |||
497 | From 603cd880e7f90595482658a7136fa6a7be5cb485 Mon Sep 17 00:00:00 2001 | ||
498 | From: Jouni Malinen <j@w1.fi> | ||
499 | Date: Fri, 7 Jan 2022 18:52:27 +0200 | ||
500 | Subject: [PATCH 4/4] EAP-pwd: Derive the y coordinate for PWE with own | ||
501 | implementation | ||
502 | |||
503 | The crypto_ec_point_solve_y_coord() wrapper function might not use | ||
504 | constant time operations in the crypto library and as such, could leak | ||
505 | side channel information about the password that is used to generate the | ||
506 | PWE in the hunting and pecking loop. As such, calculate the two possible | ||
507 | y coordinate values and pick the correct one to use with constant time | ||
508 | selection. | ||
509 | |||
510 | Signed-off-by: Jouni Malinen <j@w1.fi> | ||
511 | --- | ||
512 | src/eap_common/eap_pwd_common.c | 46 ++++++++++++++++++++++++++------- | ||
513 | 1 file changed, 36 insertions(+), 10 deletions(-) | ||
514 | |||
515 | diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c | ||
516 | index 2b2b8efdbd01..ff22b29b087a 100644 | ||
517 | --- a/src/eap_common/eap_pwd_common.c | ||
518 | +++ b/src/eap_common/eap_pwd_common.c | ||
519 | @@ -127,7 +127,8 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, | ||
520 | u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN]; | ||
521 | u8 x_bin[MAX_ECC_PRIME_LEN]; | ||
522 | u8 prime_bin[MAX_ECC_PRIME_LEN]; | ||
523 | - struct crypto_bignum *tmp2 = NULL; | ||
524 | + u8 x_y[2 * MAX_ECC_PRIME_LEN]; | ||
525 | + struct crypto_bignum *tmp2 = NULL, *y = NULL; | ||
526 | struct crypto_hash *hash; | ||
527 | unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr; | ||
528 | int ret = 0, res; | ||
529 | @@ -139,6 +140,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, | ||
530 | u8 found_ctr = 0, is_odd = 0; | ||
531 | int cmp_prime; | ||
532 | unsigned int in_range; | ||
533 | + unsigned int is_eq; | ||
534 | |||
535 | if (grp->pwe) | ||
536 | return -1; | ||
537 | @@ -151,11 +153,6 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, | ||
538 | if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin), | ||
539 | primebytelen) < 0) | ||
540 | return -1; | ||
541 | - grp->pwe = crypto_ec_point_init(grp->group); | ||
542 | - if (!grp->pwe) { | ||
543 | - wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums"); | ||
544 | - goto fail; | ||
545 | - } | ||
546 | |||
547 | if ((prfbuf = os_malloc(primebytelen)) == NULL) { | ||
548 | wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf " | ||
549 | @@ -261,10 +258,37 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, | ||
550 | */ | ||
551 | crypto_bignum_deinit(x_candidate, 1); | ||
552 | x_candidate = crypto_bignum_init_set(x_bin, primebytelen); | ||
553 | - if (!x_candidate || | ||
554 | - crypto_ec_point_solve_y_coord(grp->group, grp->pwe, x_candidate, | ||
555 | - is_odd) != 0) { | ||
556 | - wpa_printf(MSG_INFO, "EAP-pwd: Could not solve for y"); | ||
557 | + if (!x_candidate) | ||
558 | + goto fail; | ||
559 | + | ||
560 | + /* y = sqrt(x^3 + ax + b) mod p | ||
561 | + * if LSB(y) == LSB(pwd-seed): PWE = (x, y) | ||
562 | + * else: PWE = (x, p - y) | ||
563 | + * | ||
564 | + * Calculate y and the two possible values for PWE and after that, | ||
565 | + * use constant time selection to copy the correct alternative. | ||
566 | + */ | ||
567 | + y = crypto_ec_point_compute_y_sqr(grp->group, x_candidate); | ||
568 | + if (!y || | ||
569 | + dragonfly_sqrt(grp->group, y, y) < 0 || | ||
570 | + crypto_bignum_to_bin(y, x_y, MAX_ECC_PRIME_LEN, primebytelen) < 0 || | ||
571 | + crypto_bignum_sub(prime, y, y) < 0 || | ||
572 | + crypto_bignum_to_bin(y, x_y + MAX_ECC_PRIME_LEN, | ||
573 | + MAX_ECC_PRIME_LEN, primebytelen) < 0) { | ||
574 | + wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); | ||
575 | + goto fail; | ||
576 | + } | ||
577 | + | ||
578 | + /* Constant time selection of the y coordinate from the two | ||
579 | + * options */ | ||
580 | + is_eq = const_time_eq(is_odd, x_y[primebytelen - 1] & 0x01); | ||
581 | + const_time_select_bin(is_eq, x_y, x_y + MAX_ECC_PRIME_LEN, | ||
582 | + primebytelen, x_y + primebytelen); | ||
583 | + os_memcpy(x_y, x_bin, primebytelen); | ||
584 | + wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: PWE", x_y, 2 * primebytelen); | ||
585 | + grp->pwe = crypto_ec_point_from_bin(grp->group, x_y); | ||
586 | + if (!grp->pwe) { | ||
587 | + wpa_printf(MSG_DEBUG, "EAP-pwd: Could not generate PWE"); | ||
588 | goto fail; | ||
589 | } | ||
590 | |||
591 | @@ -289,6 +313,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, | ||
592 | /* cleanliness and order.... */ | ||
593 | crypto_bignum_deinit(x_candidate, 1); | ||
594 | crypto_bignum_deinit(tmp2, 1); | ||
595 | + crypto_bignum_deinit(y, 1); | ||
596 | crypto_bignum_deinit(qr, 1); | ||
597 | crypto_bignum_deinit(qnr, 1); | ||
598 | bin_clear_free(prfbuf, primebytelen); | ||
599 | @@ -296,6 +321,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, | ||
600 | os_memset(qnr_bin, 0, sizeof(qnr_bin)); | ||
601 | os_memset(qr_or_qnr_bin, 0, sizeof(qr_or_qnr_bin)); | ||
602 | os_memset(pwe_digest, 0, sizeof(pwe_digest)); | ||
603 | + forced_memzero(x_y, sizeof(x_y)); | ||
604 | |||
605 | return ret; | ||
606 | } | ||
607 | -- | ||
608 | 2.25.1 | ||
609 | |||