| 
					
				 | 
			
			
				@@ -0,0 +1,242 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+From 6513db3e96c43c2e36805cf5ead349765d18eaf7 Mon Sep 17 00:00:00 2001 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+From: Jouni Malinen <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+Date: Tue, 26 Feb 2019 13:05:09 +0200 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+Subject: [PATCH 05/14] SAE: Minimize timing differences in PWE derivation 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+The QR test result can provide information about the password to an 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+attacker, so try to minimize differences in how the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+sae_test_pwd_seed_ecc() result is used. (CVE-2019-9494) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+Use heap memory for the dummy password to allow the same password length 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+to be used even with long passwords. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+Use constant time selection functions to track the real vs. dummy 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+variables so that the exact same operations can be performed for both QR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+test results. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+Signed-off-by: Jouni Malinen <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+--- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ src/common/sae.c | 106 ++++++++++++++++++++++++++++++------------------------- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 1 file changed, 57 insertions(+), 49 deletions(-) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+--- a/src/common/sae.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++++ b/src/common/sae.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@@ -9,6 +9,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ #include "includes.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ #include "common.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++#include "utils/const_time.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ #include "crypto/crypto.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ #include "crypto/sha256.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ #include "crypto/random.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@@ -269,15 +270,12 @@ static int sae_test_pwd_seed_ecc(struct 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 				 const u8 *prime, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 				 const struct crypto_bignum *qr, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 				 const struct crypto_bignum *qnr, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-				 struct crypto_bignum **ret_x_cand) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++				 u8 *pwd_value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	u8 pwd_value[SAE_MAX_ECC_PRIME_LEN]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	struct crypto_bignum *y_sqr, *x_cand; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	int res; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	size_t bits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	*ret_x_cand = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	/* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@@ -286,7 +284,7 @@ static int sae_test_pwd_seed_ecc(struct 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 			    prime, sae->tmp->prime_len, pwd_value, bits) < 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	if (bits % 8) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-		buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		buf_shift_right(pwd_value, sae->tmp->prime_len, 8 - bits % 8); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 			pwd_value, sae->tmp->prime_len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@@ -297,20 +295,13 @@ static int sae_test_pwd_seed_ecc(struct 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	if (!x_cand) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	if (!y_sqr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-		crypto_bignum_deinit(x_cand, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	crypto_bignum_deinit(x_cand, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	if (!y_sqr) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	res = is_quadratic_residue_blind(sae, prime, bits, qr, qnr, y_sqr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	crypto_bignum_deinit(y_sqr, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	if (res <= 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-		crypto_bignum_deinit(x_cand, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-		return res; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	*ret_x_cand = x_cand; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	return 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	return res; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@@ -431,25 +422,30 @@ static int sae_derive_pwe_ecc(struct sae 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	const u8 *addr[3]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	size_t len[3]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	size_t num_elem; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	u8 dummy_password[32]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	size_t dummy_password_len; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	u8 *dummy_password, *tmp_password; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	int pwd_seed_odd = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	u8 prime[SAE_MAX_ECC_PRIME_LEN]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	size_t prime_len; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	struct crypto_bignum *x = NULL, *qr, *qnr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	u8 x_bin[SAE_MAX_ECC_PRIME_LEN]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	size_t bits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	int res; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	dummy_password_len = password_len; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	if (dummy_password_len > sizeof(dummy_password)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-		dummy_password_len = sizeof(dummy_password); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	if (random_get_bytes(dummy_password, dummy_password_len) < 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-		return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	int res = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		       * mask */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	os_memset(x_bin, 0, sizeof(x_bin)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	dummy_password = os_malloc(password_len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	tmp_password = os_malloc(password_len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	if (!dummy_password || !tmp_password || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	    random_get_bytes(dummy_password, password_len) < 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		goto fail; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	prime_len = sae->tmp->prime_len; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 				 prime_len) < 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-		return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		goto fail; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	bits = crypto_ec_prime_len_bits(sae->tmp->ec); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@@ -458,7 +454,7 @@ static int sae_derive_pwe_ecc(struct sae 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	if (get_random_qr_qnr(prime, prime_len, sae->tmp->prime, bits, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 			      &qr, &qnr) < 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-		return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		goto fail; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 			      password, password_len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@@ -474,7 +470,7 @@ static int sae_derive_pwe_ecc(struct sae 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	sae_pwd_seed_key(addr1, addr2, addrs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	addr[0] = password; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	addr[0] = tmp_password; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	len[0] = password_len; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	num_elem = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	if (identifier) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@@ -491,9 +487,8 @@ static int sae_derive_pwe_ecc(struct sae 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	 * attacks that attempt to determine the number of iterations required 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	 * in the loop. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	for (counter = 1; counter <= k || !x; counter++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	for (counter = 1; counter <= k || !found; counter++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		u8 pwd_seed[SHA256_MAC_LEN]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-		struct crypto_bignum *x_cand; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		if (counter > 200) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 			/* This should not happen in practice */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@@ -501,40 +496,49 @@ static int sae_derive_pwe_ecc(struct sae 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-		wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		const_time_select_bin(found, dummy_password, password, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++				      password_len, tmp_password); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 				       addr, len, pwd_seed) < 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		res = sae_test_pwd_seed_ecc(sae, pwd_seed, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-					    prime, qr, qnr, &x_cand); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++					    prime, qr, qnr, x_cand_bin); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		const_time_select_bin(found, x_bin, x_cand_bin, prime_len, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++				      x_bin); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		pwd_seed_odd = const_time_select_u8( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++			found, pwd_seed_odd, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++			pwd_seed[SHA256_MAC_LEN - 1] & 0x01); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		os_memset(pwd_seed, 0, sizeof(pwd_seed)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		if (res < 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 			goto fail; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-		if (res > 0 && !x) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-			wpa_printf(MSG_DEBUG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-				   "SAE: Selected pwd-seed with counter %u", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-				   counter); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-			x = x_cand; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-			pwd_seed_odd = pwd_seed[SHA256_MAC_LEN - 1] & 0x01; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-			os_memset(pwd_seed, 0, sizeof(pwd_seed)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-			/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-			 * Use a dummy password for the following rounds, if 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-			 * any. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-			 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-			addr[0] = dummy_password; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-			len[0] = dummy_password_len; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-		} else if (res > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-			crypto_bignum_deinit(x_cand, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		/* Need to minimize differences in handling res == 0 and 1 here 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		 * to avoid differences in timing and instruction cache access, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		 * so use const_time_select_*() to make local copies of the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		 * values based on whether this loop iteration was the one that 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		 * found the pwd-seed/x. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		/* found is 0 or 0xff here and res is 0 or 1. Bitwise OR of them 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		 * (with res converted to 0/0xff) handles this in constant time. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		found |= res * 0xff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		wpa_printf(MSG_DEBUG, "SAE: pwd-seed result %d found=0x%02x", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++			   res, found); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	if (!x) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	if (!found) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		res = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		goto fail; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	x = crypto_bignum_init_set(x_bin, prime_len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	if (!x) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		res = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++		goto fail; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	if (!sae->tmp->pwe_ecc) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	if (!sae->tmp->pwe_ecc) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@@ -543,7 +547,6 @@ static int sae_derive_pwe_ecc(struct sae 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		res = crypto_ec_point_solve_y_coord(sae->tmp->ec, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 						    sae->tmp->pwe_ecc, x, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 						    pwd_seed_odd); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+-	crypto_bignum_deinit(x, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	if (res < 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 		 * This should not happen since we already checked that there 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@@ -555,6 +558,11 @@ static int sae_derive_pwe_ecc(struct sae 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ fail: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	crypto_bignum_deinit(qr, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	crypto_bignum_deinit(qnr, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	os_free(dummy_password); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	bin_clear_free(tmp_password, password_len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	crypto_bignum_deinit(x, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	os_memset(x_bin, 0, sizeof(x_bin)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				++	os_memset(x_cand_bin, 0, sizeof(x_cand_bin)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 	return res; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ } 
			 |