diff -Nur orig-wpa_supplicant-2.6/src/eap_common/eap_pwd_common.c wpa_supplicant-2.6/src/eap_common/eap_pwd_common.c
--- orig-wpa_supplicant-2.6/src/eap_common/eap_pwd_common.c	2020-02-04 01:25:30.586304407 +0800
+++ wpa_supplicant-2.6/src/eap_common/eap_pwd_common.c	2020-02-04 01:58:33.502654599 +0800
@@ -8,11 +8,15 @@
 
 #include "includes.h"
 #include "common.h"
+#include "utils/const_time.h"
 #include "crypto/sha256.h"
 #include "crypto/crypto.h"
 #include "eap_defs.h"
 #include "eap_pwd_common.h"
 
+#define MAX_ECC_PRIME_LEN 66
+
+
 /* The random function H(x) = HMAC-SHA256(0^32, x) */
 struct crypto_hash * eap_pwd_h_init(void)
 {
@@ -99,7 +103,16 @@
 
         return grp;
 }
-+
+
+
+static void buf_shift_right(u8 *buf, size_t len, size_t bits)
+{
+        size_t i;
+        for (i = len - 1; i > 0; i--)
+                buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits);
+        buf[0] >>= bits;
+}
+
 
 /*
  * compute a "random" secret point on an elliptic curve based
@@ -112,17 +125,27 @@
 			     const u8 *token)
 {
         struct crypto_bignum *qr = NULL, *qnr = NULL, *one = NULL;
+        struct crypto_bignum *qr_or_qnr = NULL;
+        u8 qr_bin[MAX_ECC_PRIME_LEN];
+        u8 qnr_bin[MAX_ECC_PRIME_LEN];
+        u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN];
+        u8 x_bin[MAX_ECC_PRIME_LEN];
         struct crypto_bignum *tmp1 = NULL, *tmp2 = NULL, *pm1 = NULL;
 	struct crypto_hash *hash;
 	unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr;
-        int is_odd, ret = 0, check, found = 0;
-	size_t primebytelen, primebitlen;
-        struct crypto_bignum *x_candidate = NULL, *rnd = NULL, *cofactor = NULL;
+        int ret = 0, check, res;
+        u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
+                       * mask */
+        size_t primebytelen = 0, primebitlen;
+        struct crypto_bignum *x_candidate = NULL, *cofactor = NULL; 
         const struct crypto_bignum *prime;
+        u8 mask, found_ctr = 0, is_odd = 0;
 
         if (grp->pwe)
                 return -1;
 
+        os_memset(x_bin, 0, sizeof(x_bin));
+
         prime = crypto_ec_get_prime(grp->group);
         cofactor = crypto_bignum_init();
         grp->pwe = crypto_ec_point_init(grp->group);
@@ -151,8 +174,6 @@
 
         /* get a random quadratic residue and nonresidue */
         while (!qr || !qnr) {
-                int res;
-
                 if (crypto_bignum_rand(tmp1, prime) < 0)
 			goto fail;
                 res = crypto_bignum_legendre(tmp1, prime);
@@ -166,6 +187,11 @@
                 if (!tmp1)
                         goto fail;
         }
+        if (crypto_bignum_to_bin(qr, qr_bin, sizeof(qr_bin),
+                                 primebytelen) < 0 ||
+            crypto_bignum_to_bin(qnr, qnr_bin, sizeof(qnr_bin),
+                                 primebytelen) < 0)
+                goto fail;
 
         os_memset(prfbuf, 0, primebytelen);
         ctr = 0;
@@ -193,17 +219,16 @@
 		eap_pwd_h_update(hash, &ctr, sizeof(ctr));
 		eap_pwd_h_final(hash, pwe_digest);
 
-                crypto_bignum_deinit(rnd, 1);
-                rnd = crypto_bignum_init_set(pwe_digest, SHA256_MAC_LEN);
-                if (!rnd) {
-                        wpa_printf(MSG_INFO, "EAP-pwd: unable to create rnd");
-                        goto fail;
-                }
+                is_odd = const_time_select_u8(
+                        found, is_odd, pwe_digest[SHA256_MAC_LEN - 1] & 0x01);
 		if (eap_pwd_kdf(pwe_digest, SHA256_MAC_LEN,
 				(u8 *) "EAP-pwd Hunting And Pecking",
 				os_strlen("EAP-pwd Hunting And Pecking"),
 				prfbuf, primebitlen) < 0)
 			goto fail;
+                if (primebitlen % 8)
+                        buf_shift_right(prfbuf, primebytelen,
+                                        8 - primebitlen % 8);
 
                 crypto_bignum_deinit(x_candidate, 1);
                 x_candidate = crypto_bignum_init_set(prfbuf, primebytelen);
@@ -213,24 +238,13 @@
                         goto fail;
                 }
 
-		/*
-		 * eap_pwd_kdf() returns a string of bits 0..primebitlen but
-		 * BN_bin2bn will treat that string of bits as a big endian
-		 * number. If the primebitlen is not an even multiple of 8
-		 * then excessive bits-- those _after_ primebitlen-- so now
-		 * we have to shift right the amount we masked off.
-		 */
-                if ((primebitlen % 8) &&
-                    crypto_bignum_rshift(x_candidate,
-                                         (8 - (primebitlen % 8)),
-                                         x_candidate) < 0)
-                        goto fail;
-
                 if (crypto_bignum_cmp(x_candidate, prime) >= 0)
 			continue;
 
-		wpa_hexdump(MSG_DEBUG, "EAP-pwd: x_candidate",
-			    prfbuf, primebytelen);
+                wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: x_candidate",
+                                prfbuf, primebytelen);
+                const_time_select_bin(found, x_bin, prfbuf, primebytelen,
+                                      x_bin);
 
 		/*
                  * compute y^2 using the equation of the curve
@@ -264,13 +278,15 @@
                         wpa_printf(MSG_INFO, "EAP-pwd: Could not solve for y");
 			continue;
                 }
-                if (crypto_bignum_is_odd(tmp1)) {
-                        crypto_bignum_mulmod(tmp2, qr, prime, tmp2);
-                        check = 1;
-                } else {
-                        crypto_bignum_mulmod(tmp2, qnr, prime, tmp2);
-                        check = -1;
-                }
+                mask = const_time_eq_u8(crypto_bignum_is_odd(tmp1), 1);
+                check = const_time_select_s8(mask, 1, -1);
+                const_time_select_bin(mask, qr_bin, qnr_bin, primebytelen,
+                                      qr_or_qnr_bin);
+                crypto_bignum_deinit(qr_or_qnr, 1);
+                qr_or_qnr = crypto_bignum_init_set(qr_or_qnr_bin, primebytelen);
+                if (!qr_or_qnr ||
+                    crypto_bignum_mulmod(tmp2, qr_or_qnr, prime, tmp2) < 0)
+                        goto fail;
 
 		/*
                  * Now it's safe to do legendre, if check is 1 then it's
@@ -278,59 +294,12 @@
                  * change result), if check is -1 then it's the opposite test
                  * (multiplying a qr by qnr would make a qnr).
 		 */
-                if (crypto_bignum_legendre(tmp2, prime) == check) {
-                        if (found == 1)
-                                continue;
- 
-                        /* need to unambiguously identify the solution */
-                        is_odd = crypto_bignum_is_odd(rnd);
-
-                        /*
-                         * We know x_candidate is a quadratic residue so set
-                         * it here.
-                         */
-                        if (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");
-				continue;
-			}
-
-                        /*
-                         * If there's a solution to the equation then the point
-                         * must be on the curve so why check again explicitly?
-                         * OpenSSL code says this is required by X9.62. We're
-                         * not X9.62 but it can't hurt just to be sure.
-                         */
-                        if (!crypto_ec_point_is_on_curve(grp->group,
-                                                         grp->pwe)) {
-                                wpa_printf(MSG_INFO,
-                                           "EAP-pwd: point is not on curve");
-				continue;
-			}
-
-                        if (!crypto_bignum_is_one(cofactor)) {
-                                /* make sure the point is not in a small
-                                 * sub-group */
-                                if (crypto_ec_point_mul(grp->group, grp->pwe,
-                                                        cofactor,
-                                                        grp->pwe) != 0) {
-                                        wpa_printf(MSG_INFO,
-                                                   "EAP-pwd: cannot multiply generator by order");
-                                        continue;
-                                }
-                                if (crypto_ec_point_is_at_infinity(grp->group,
-                                                                   grp->pwe)) {
-                                        wpa_printf(MSG_INFO,
-                                                   "EAP-pwd: point is at infinity");
-                                        continue;
-                                }
-                        }
-                        wpa_printf(MSG_DEBUG,
-                                   "EAP-pwd: found a PWE in %d tries", ctr);
-                        found = 1;
-		}
+                res = crypto_bignum_legendre(tmp2, prime);
+                if (res == -2)
+                        goto fail;
+                mask = const_time_eq(res, check);
+                found_ctr = const_time_select_u8(found, found_ctr, ctr);
+                found |= mask;
 	}
         if (found == 0) {
                 wpa_printf(MSG_INFO,
@@ -338,6 +307,44 @@
                            num);
                 goto fail;
         }
+
+        /*
+         * We know x_candidate is a quadratic residue so set it here.
+         */
+        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");
+                goto fail;
+        }
+
+        /*
+         * If there's a solution to the equation then the point must be on the
+         * curve so why check again explicitly? OpenSSL code says this is
+         * required by X9.62. We're not X9.62 but it can't hurt just to be sure.
+         */
+        if (!crypto_ec_point_is_on_curve(grp->group, grp->pwe)) {
+                wpa_printf(MSG_INFO, "EAP-pwd: point is not on curve");
+                goto fail;
+        }
+
+        if (!crypto_bignum_is_one(cofactor)) {
+                /* make sure the point is not in a small sub-group */
+                if (crypto_ec_point_mul(grp->group, grp->pwe, cofactor,
+                                        grp->pwe) != 0) {
+                        wpa_printf(MSG_INFO,
+                                   "EAP-pwd: cannot multiply generator by order");
+                        goto fail;
+                }
+                if (crypto_ec_point_is_at_infinity(grp->group, grp->pwe)) {
+                        wpa_printf(MSG_INFO, "EAP-pwd: point is at infinity");
+                        goto fail;
+                }
+        }
+        wpa_printf(MSG_DEBUG, "EAP-pwd: found a PWE in %02d tries", found_ctr);
+
 	if (0) {
  fail:
                 crypto_ec_point_deinit(grp->pwe, 1);
@@ -347,14 +354,18 @@
 	/* cleanliness and order.... */
         crypto_bignum_deinit(cofactor, 1);
         crypto_bignum_deinit(x_candidate, 1);
-        crypto_bignum_deinit(rnd, 1);
         crypto_bignum_deinit(pm1, 0);
         crypto_bignum_deinit(tmp1, 1);
         crypto_bignum_deinit(tmp2, 1);
         crypto_bignum_deinit(qr, 1);
         crypto_bignum_deinit(qnr, 1);
+        crypto_bignum_deinit(qr_or_qnr, 1);
         crypto_bignum_deinit(one, 0);
-	os_free(prfbuf);
+        bin_clear_free(prfbuf, primebytelen);
+        os_memset(qr_bin, 0, sizeof(qr_bin));
+        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));
 
 	return ret;
 }
