hostapd: Apply SAE/EAP-pwd side-channel attack update 2
[openwrt/staging/pepe2k.git] / package / network / services / hostapd / patches / 084-EAP-pwd-Derive-the-y-coordinate-for-PWE-with-own-imp.patch
1 From 603cd880e7f90595482658a7136fa6a7be5cb485 Mon Sep 17 00:00:00 2001
2 From: Jouni Malinen <j@w1.fi>
3 Date: Fri, 7 Jan 2022 18:52:27 +0200
4 Subject: [PATCH 4/4] EAP-pwd: Derive the y coordinate for PWE with own
5 implementation
6
7 The crypto_ec_point_solve_y_coord() wrapper function might not use
8 constant time operations in the crypto library and as such, could leak
9 side channel information about the password that is used to generate the
10 PWE in the hunting and pecking loop. As such, calculate the two possible
11 y coordinate values and pick the correct one to use with constant time
12 selection.
13
14 Signed-off-by: Jouni Malinen <j@w1.fi>
15 ---
16 src/eap_common/eap_pwd_common.c | 46 ++++++++++++++++++++++++++-------
17 1 file changed, 36 insertions(+), 10 deletions(-)
18
19 --- a/src/eap_common/eap_pwd_common.c
20 +++ b/src/eap_common/eap_pwd_common.c
21 @@ -127,7 +127,8 @@ int compute_password_element(EAP_PWD_gro
22 u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN];
23 u8 x_bin[MAX_ECC_PRIME_LEN];
24 u8 prime_bin[MAX_ECC_PRIME_LEN];
25 - struct crypto_bignum *tmp2 = NULL;
26 + u8 x_y[2 * MAX_ECC_PRIME_LEN];
27 + struct crypto_bignum *tmp2 = NULL, *y = NULL;
28 struct crypto_hash *hash;
29 unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr;
30 int ret = 0, res;
31 @@ -139,6 +140,7 @@ int compute_password_element(EAP_PWD_gro
32 u8 found_ctr = 0, is_odd = 0;
33 int cmp_prime;
34 unsigned int in_range;
35 + unsigned int is_eq;
36
37 if (grp->pwe)
38 return -1;
39 @@ -151,11 +153,6 @@ int compute_password_element(EAP_PWD_gro
40 if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin),
41 primebytelen) < 0)
42 return -1;
43 - grp->pwe = crypto_ec_point_init(grp->group);
44 - if (!grp->pwe) {
45 - wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums");
46 - goto fail;
47 - }
48
49 if ((prfbuf = os_malloc(primebytelen)) == NULL) {
50 wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf "
51 @@ -261,10 +258,37 @@ int compute_password_element(EAP_PWD_gro
52 */
53 crypto_bignum_deinit(x_candidate, 1);
54 x_candidate = crypto_bignum_init_set(x_bin, primebytelen);
55 - if (!x_candidate ||
56 - crypto_ec_point_solve_y_coord(grp->group, grp->pwe, x_candidate,
57 - is_odd) != 0) {
58 - wpa_printf(MSG_INFO, "EAP-pwd: Could not solve for y");
59 + if (!x_candidate)
60 + goto fail;
61 +
62 + /* y = sqrt(x^3 + ax + b) mod p
63 + * if LSB(y) == LSB(pwd-seed): PWE = (x, y)
64 + * else: PWE = (x, p - y)
65 + *
66 + * Calculate y and the two possible values for PWE and after that,
67 + * use constant time selection to copy the correct alternative.
68 + */
69 + y = crypto_ec_point_compute_y_sqr(grp->group, x_candidate);
70 + if (!y ||
71 + dragonfly_sqrt(grp->group, y, y) < 0 ||
72 + crypto_bignum_to_bin(y, x_y, MAX_ECC_PRIME_LEN, primebytelen) < 0 ||
73 + crypto_bignum_sub(prime, y, y) < 0 ||
74 + crypto_bignum_to_bin(y, x_y + MAX_ECC_PRIME_LEN,
75 + MAX_ECC_PRIME_LEN, primebytelen) < 0) {
76 + wpa_printf(MSG_DEBUG, "SAE: Could not solve y");
77 + goto fail;
78 + }
79 +
80 + /* Constant time selection of the y coordinate from the two
81 + * options */
82 + is_eq = const_time_eq(is_odd, x_y[primebytelen - 1] & 0x01);
83 + const_time_select_bin(is_eq, x_y, x_y + MAX_ECC_PRIME_LEN,
84 + primebytelen, x_y + primebytelen);
85 + os_memcpy(x_y, x_bin, primebytelen);
86 + wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: PWE", x_y, 2 * primebytelen);
87 + grp->pwe = crypto_ec_point_from_bin(grp->group, x_y);
88 + if (!grp->pwe) {
89 + wpa_printf(MSG_DEBUG, "EAP-pwd: Could not generate PWE");
90 goto fail;
91 }
92
93 @@ -289,6 +313,7 @@ int compute_password_element(EAP_PWD_gro
94 /* cleanliness and order.... */
95 crypto_bignum_deinit(x_candidate, 1);
96 crypto_bignum_deinit(tmp2, 1);
97 + crypto_bignum_deinit(y, 1);
98 crypto_bignum_deinit(qr, 1);
99 crypto_bignum_deinit(qnr, 1);
100 bin_clear_free(prfbuf, primebytelen);
101 @@ -296,6 +321,7 @@ int compute_password_element(EAP_PWD_gro
102 os_memset(qnr_bin, 0, sizeof(qnr_bin));
103 os_memset(qr_or_qnr_bin, 0, sizeof(qr_or_qnr_bin));
104 os_memset(pwe_digest, 0, sizeof(pwe_digest));
105 + forced_memzero(x_y, sizeof(x_y));
106
107 return ret;
108 }