Cumulative patch from commit 8c43ef8449bd4d2d0983db394770bd73f572b12d

8c43ef8 P2PS: Fix attribute addition in p2p_buf_add_service_instance()
a9ea609 P2PS: Fix p2p_find last parameter handling
6c73149 AP: Increase maximum value accepted for cwmin/cwmax
575e4f5 SAE: Reject FFC commit-element with value p-1
a406244 P2PS: Do not reply to ProbeReq on another channel when starting Listen
0c2b3f6 SAE: Reject commit-scalar value 1
4f39908 Send CTRL-EVENT-NETWORK-NOT-FOUND if no suitable network was found
123df27 D-Bus: Fix typos in debug print
ded14ce Android: Fix nl80211 build if BOARD_*_PRIVATE_LIB is unspecified
a140721 Android: Rename ANDROID_P2P_STUB to ANDROID_LIB_STUB
2ba4de3 D-Bus: Add documentation for wpas_dbus_signal_peer_groups_changed()
e48b5e2 D-Bus: Fix typo in dbus signal function documentation
09d5048 D-Bus: Add function documentation for wpas_dbus_unregister_interface()
adfbbd2 D-Bus: Add function documentation for wpas_dbus_register_interface()
c5967f0 D-Bus: Fix wpas_dbus_signal_p2p_invitation_result() documentation
4457f41 radius: Fix NULL dereference issue on allocation failure
f826fb1 OpenSSL: Handle EC_POINT_is_on_curve() error case
bbb5008 SAE: Use random "password" in extra hunting-and-pecking loops
eb5fee0 SAE: Add side-channel protection to PWE derivation with ECC
16841ab crypto: Add functions for computing the Legendre symbol and EC y^2
c4a13b4 OpenSSL: Add support for Brainpool Elliptic Curves
4584b66 SAE: Increase security parameter k to 40 based on Dragonfly recommendation
fdd731b SAE: Fix PWE generation to use minimum loop count (k) properly
8ec3332 SAE: Merge sae_derive_commit() error case return statements
d93abd4 SAE: Merge sae_get_rand() error case return statements
6a58444 SAE: Verify that own/peer commit-scalar and COMMIT-ELEMENT are different
4e7e688 Add crypto_ec_point_cmp()
8e2a3a4 dbus: Do not initialize variable twice
c1a14ef Do not check unsigned size is less than zero
fdc5608 OpenSSL: Remove SSL_CTX_{get,set}_app_data() compatibility wrapper
ba54933 libtommath: Fix mp_init_multi() stdarg use on error path
f6332b0 wpa_gui: Initialize WpaGuiApp::w in the constructor
f6df3f3 Use os_* wrapper more consistently
91b7a5e Use unsigned/signed printf format more consistently
59bae74 HS 2.0R2: Fix memory leak on error path in hs20-osu-client
c5ca73d P2P: Use offsetof() instead of local implementation
c3c5b5f ERP server: Make erp_send_finish_reauth() easier for static analyzers
6ce1bea bsd: Remove redundant NULL check in bsd_init()
c99df20 Remove redundant NULL check in ieee802_1x_encapsulate_radius()
2eb5967 AP: Add more 2.4 GHz channels for 20/40 MHz HT co-ex scan
5ed6519 hw_features: Merge similar return cases
4e37dd6 SAE: Simplify sae_prepare_commit() error path
04e6c4c Fix SAE group selection in an error case
3dce85c HS 2.0: Add WLAN RADIUS attributes in OSEN case
efd5d26 Remove unnecessary wpa_ie_len check from wpa_parse_wpa_ie_wpa()
ce8963f Remove WEP40/WEP104 cipher suite support for WPA/WPA2
ee140ef FT: Stop association attempt if Auth response processing fails (SME)
1887be4 Make check_20mhz_bss() static

Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>

Bug: 22062116
Change-Id: Ie1d175f1faab24bf39ce81ead7a078e1e236badd
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index 9834b25..3703b93 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -1107,6 +1107,42 @@
 }
 
 
+int crypto_bignum_legendre(const struct crypto_bignum *a,
+			   const struct crypto_bignum *p)
+{
+	BN_CTX *bnctx;
+	BIGNUM *exp = NULL, *tmp = NULL;
+	int res = -2;
+
+	bnctx = BN_CTX_new();
+	if (bnctx == NULL)
+		return -2;
+
+	exp = BN_new();
+	tmp = BN_new();
+	if (!exp || !tmp ||
+	    /* exp = (p-1) / 2 */
+	    !BN_sub(exp, (const BIGNUM *) p, BN_value_one()) ||
+	    !BN_rshift1(exp, exp) ||
+	    !BN_mod_exp(tmp, (const BIGNUM *) a, exp, (const BIGNUM *) p,
+			bnctx))
+		goto fail;
+
+	if (BN_is_word(tmp, 1))
+		res = 1;
+	else if (BN_is_zero(tmp))
+		res = 0;
+	else
+		res = -1;
+
+fail:
+	BN_clear_free(tmp);
+	BN_clear_free(exp);
+	BN_CTX_free(bnctx);
+	return res;
+}
+
+
 #ifdef CONFIG_ECC
 
 struct crypto_ec {
@@ -1114,6 +1150,8 @@
 	BN_CTX *bnctx;
 	BIGNUM *prime;
 	BIGNUM *order;
+	BIGNUM *a;
+	BIGNUM *b;
 };
 
 struct crypto_ec * crypto_ec_init(int group)
@@ -1138,6 +1176,26 @@
 	case 26:
 		nid = NID_secp224r1;
 		break;
+#ifdef NID_brainpoolP224r1
+	case 27:
+		nid = NID_brainpoolP224r1;
+		break;
+#endif /* NID_brainpoolP224r1 */
+#ifdef NID_brainpoolP256r1
+	case 28:
+		nid = NID_brainpoolP256r1;
+		break;
+#endif /* NID_brainpoolP256r1 */
+#ifdef NID_brainpoolP384r1
+	case 29:
+		nid = NID_brainpoolP384r1;
+		break;
+#endif /* NID_brainpoolP384r1 */
+#ifdef NID_brainpoolP512r1
+	case 30:
+		nid = NID_brainpoolP512r1;
+		break;
+#endif /* NID_brainpoolP512r1 */
 	default:
 		return NULL;
 	}
@@ -1150,9 +1208,11 @@
 	e->group = EC_GROUP_new_by_curve_name(nid);
 	e->prime = BN_new();
 	e->order = BN_new();
+	e->a = BN_new();
+	e->b = BN_new();
 	if (e->group == NULL || e->bnctx == NULL || e->prime == NULL ||
-	    e->order == NULL ||
-	    !EC_GROUP_get_curve_GFp(e->group, e->prime, NULL, NULL, e->bnctx) ||
+	    e->order == NULL || e->a == NULL || e->b == NULL ||
+	    !EC_GROUP_get_curve_GFp(e->group, e->prime, e->a, e->b, e->bnctx) ||
 	    !EC_GROUP_get_order(e->group, e->order, e->bnctx)) {
 		crypto_ec_deinit(e);
 		e = NULL;
@@ -1166,6 +1226,8 @@
 {
 	if (e == NULL)
 		return;
+	BN_clear_free(e->b);
+	BN_clear_free(e->a);
 	BN_clear_free(e->order);
 	BN_clear_free(e->prime);
 	EC_GROUP_free(e->group);
@@ -1313,6 +1375,33 @@
 }
 
 
+struct crypto_bignum *
+crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
+			      const struct crypto_bignum *x)
+{
+	BIGNUM *tmp, *tmp2, *y_sqr = NULL;
+
+	tmp = BN_new();
+	tmp2 = BN_new();
+
+	/* y^2 = x^3 + ax + b */
+	if (tmp && tmp2 &&
+	    BN_mod_sqr(tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
+	    BN_mod_mul(tmp, tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
+	    BN_mod_mul(tmp2, e->a, (const BIGNUM *) x, e->prime, e->bnctx) &&
+	    BN_mod_add_quick(tmp2, tmp2, tmp, e->prime) &&
+	    BN_mod_add_quick(tmp2, tmp2, e->b, e->prime)) {
+		y_sqr = tmp2;
+		tmp2 = NULL;
+	}
+
+	BN_clear_free(tmp);
+	BN_clear_free(tmp2);
+
+	return (struct crypto_bignum *) y_sqr;
+}
+
+
 int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
 				   const struct crypto_ec_point *p)
 {
@@ -1323,7 +1412,17 @@
 int crypto_ec_point_is_on_curve(struct crypto_ec *e,
 				const struct crypto_ec_point *p)
 {
-	return EC_POINT_is_on_curve(e->group, (const EC_POINT *) p, e->bnctx);
+	return EC_POINT_is_on_curve(e->group, (const EC_POINT *) p,
+				    e->bnctx) == 1;
+}
+
+
+int crypto_ec_point_cmp(const struct crypto_ec *e,
+			const struct crypto_ec_point *a,
+			const struct crypto_ec_point *b)
+{
+	return EC_POINT_cmp(e->group, (const EC_POINT *) a,
+			    (const EC_POINT *) b, e->bnctx);
 }
 
 #endif /* CONFIG_ECC */