110 lines
4.6 KiB
Diff
110 lines
4.6 KiB
Diff
From 603cd880e7f90595482658a7136fa6a7be5cb485 Mon Sep 17 00:00:00 2001
|
|
From: Jouni Malinen <j@w1.fi>
|
|
Date: Fri, 7 Jan 2022 18:52:27 +0200
|
|
Subject: [PATCH 4/4] EAP-pwd: Derive the y coordinate for PWE with own
|
|
implementation
|
|
|
|
The crypto_ec_point_solve_y_coord() wrapper function might not use
|
|
constant time operations in the crypto library and as such, could leak
|
|
side channel information about the password that is used to generate the
|
|
PWE in the hunting and pecking loop. As such, calculate the two possible
|
|
y coordinate values and pick the correct one to use with constant time
|
|
selection.
|
|
|
|
Signed-off-by: Jouni Malinen <j@w1.fi>
|
|
---
|
|
src/eap_common/eap_pwd_common.c | 42 +++++++++++++++++++++++++++++++++++------
|
|
1 file changed, 36 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
|
|
index 755aafb..ab8eb92 100644
|
|
--- a/src/eap_common/eap_pwd_common.c
|
|
+++ b/src/eap_common/eap_pwd_common.c
|
|
@@ -137,7 +137,8 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
|
|
u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN];
|
|
u8 x_bin[MAX_ECC_PRIME_LEN];
|
|
u8 prime_bin[MAX_ECC_PRIME_LEN];
|
|
- struct crypto_bignum *tmp1 = NULL, *tmp2 = NULL, *pm1 = NULL;
|
|
+ u8 x_y[2 * MAX_ECC_PRIME_LEN];
|
|
+ struct crypto_bignum *tmp1 = NULL, *tmp2 = NULL, *pm1 = NULL, *y = NULL;
|
|
struct crypto_hash *hash;
|
|
unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr;
|
|
int ret = 0, check, res;
|
|
@@ -149,6 +150,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
|
|
u8 mask, found_ctr = 0, is_odd = 0;
|
|
int cmp_prime;
|
|
unsigned int in_range;
|
|
+ unsigned int is_eq;
|
|
|
|
if (grp->pwe)
|
|
return -1;
|
|
@@ -161,7 +163,6 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
|
|
if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin),
|
|
primebytelen) < 0)
|
|
return -1;
|
|
- grp->pwe = crypto_ec_point_init(grp->group);
|
|
tmp1 = crypto_bignum_init();
|
|
pm1 = crypto_bignum_init();
|
|
one = crypto_bignum_init_set((const u8 *) "\x01", 1);
|
|
@@ -323,10 +324,37 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
|
|
*/
|
|
crypto_bignum_deinit(x_candidate, 1);
|
|
x_candidate = crypto_bignum_init_set(x_bin, primebytelen);
|
|
- if (!x_candidate ||
|
|
- crypto_ec_point_solve_y_coord(grp->group, grp->pwe, x_candidate,
|
|
- is_odd) != 0) {
|
|
- wpa_printf(MSG_INFO, "EAP-pwd: Could not solve for y");
|
|
+ if (!x_candidate)
|
|
+ goto fail;
|
|
+
|
|
+ /* y = sqrt(x^3 + ax + b) mod p
|
|
+ * if LSB(y) == LSB(pwd-seed): PWE = (x, y)
|
|
+ * else: PWE = (x, p - y)
|
|
+ *
|
|
+ * Calculate y and the two possible values for PWE and after that,
|
|
+ * use constant time selection to copy the correct alternative.
|
|
+ */
|
|
+ y = crypto_ec_point_compute_y_sqr(grp->group, x_candidate);
|
|
+ if (!y ||
|
|
+ dragonfly_sqrt(grp->group, y, y) < 0 ||
|
|
+ crypto_bignum_to_bin(y, x_y, MAX_ECC_PRIME_LEN, primebytelen) < 0 ||
|
|
+ crypto_bignum_sub(prime, y, y) < 0 ||
|
|
+ crypto_bignum_to_bin(y, x_y + MAX_ECC_PRIME_LEN,
|
|
+ MAX_ECC_PRIME_LEN, primebytelen) < 0) {
|
|
+ wpa_printf(MSG_DEBUG, "SAE: Could not solve y");
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ /* Constant time selection of the y coordinate from the two
|
|
+ * options */
|
|
+ is_eq = const_time_eq(is_odd, x_y[primebytelen - 1] & 0x01);
|
|
+ const_time_select_bin(is_eq, x_y, x_y + MAX_ECC_PRIME_LEN,
|
|
+ primebytelen, x_y + primebytelen);
|
|
+ os_memcpy(x_y, x_bin, primebytelen);
|
|
+ wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: PWE", x_y, 2 * primebytelen);
|
|
+ grp->pwe = crypto_ec_point_from_bin(grp->group, x_y);
|
|
+ if (!grp->pwe) {
|
|
+ wpa_printf(MSG_DEBUG, "EAP-pwd: Could not generate PWE");
|
|
goto fail;
|
|
}
|
|
|
|
@@ -353,6 +381,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
|
|
crypto_bignum_deinit(pm1, 0);
|
|
crypto_bignum_deinit(tmp1, 1);
|
|
crypto_bignum_deinit(tmp2, 1);
|
|
+ crypto_bignum_deinit(y, 1);
|
|
crypto_bignum_deinit(qr, 1);
|
|
crypto_bignum_deinit(qnr, 1);
|
|
crypto_bignum_deinit(qr_or_qnr, 1);
|
|
@@ -362,6 +391,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
|
|
os_memset(qnr_bin, 0, sizeof(qnr_bin));
|
|
os_memset(qr_or_qnr_bin, 0, sizeof(qr_or_qnr_bin));
|
|
os_memset(pwe_digest, 0, sizeof(pwe_digest));
|
|
+ forced_memzero(x_y, sizeof(x_y));
|
|
|
|
return ret;
|
|
}
|
|
--
|
|
1.8.3.1
|
|
|