Forbid setting EC public key to point at infinity

The point at infinity is not a valid EC public key. We already refuse to
parse it. This CL makes it forbidden to set an EC public key to a
manually-constructed point at infinity.

This change will allow callers to assume that ECDH is infallible
given a valid peer public key.

Update-Note: EC_KEY_set_public_key will now return an error if
configuring the point at infinity as a public key. This does not impact
parsing, which already rejected such a point, and the resulting key
would have failed all operations already.

Change-Id: I202307a510543f4305b1cb46094d2c83174047af
Fixed: 438493754
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/81267
Commit-Queue: Lily Chen <chlily@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/fipsmodule/ec/ec_key.cc.inc b/crypto/fipsmodule/ec/ec_key.cc.inc
index d471e84..754998a 100644
--- a/crypto/fipsmodule/ec/ec_key.cc.inc
+++ b/crypto/fipsmodule/ec/ec_key.cc.inc
@@ -213,6 +213,11 @@
     return 0;
   }
 
+  if (pub_key != NULL && EC_POINT_is_at_infinity(pub_key->group, pub_key)) {
+    OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
+    return 0;
+  }
+
   if (pub_key != NULL && EC_GROUP_cmp(key->group, pub_key->group, NULL) != 0) {
     OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
     return 0;
diff --git a/crypto/fipsmodule/ec/ec_test.cc b/crypto/fipsmodule/ec/ec_test.cc
index 4be8d5b..2f269fa 100644
--- a/crypto/fipsmodule/ec/ec_test.cc
+++ b/crypto/fipsmodule/ec/ec_test.cc
@@ -453,6 +453,17 @@
   EXPECT_FALSE(EC_KEY_get0_public_key(key.get()));
 }
 
+TEST(ECTest, PointAtInfinity) {
+  bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+  ASSERT_TRUE(key);
+
+  bssl::UniquePtr<EC_POINT> inf(EC_POINT_new(key->group));
+  ASSERT_TRUE(inf);
+  ASSERT_TRUE(EC_POINT_set_to_infinity(key->group, inf.get()));
+  // Configuring a public key with the point at infinity is invalid.
+  EXPECT_FALSE(EC_KEY_set_public_key(key.get(), inf.get()));
+}
+
 TEST(ECTest, GroupMismatch) {
   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_secp384r1));
   ASSERT_TRUE(key);
diff --git a/include/openssl/ec_key.h b/include/openssl/ec_key.h
index 1133a37..47d5063 100644
--- a/include/openssl/ec_key.h
+++ b/include/openssl/ec_key.h
@@ -87,7 +87,7 @@
 // EC_KEY_set_public_key sets the public key of |key| to |pub|, by copying it.
 // It returns one on success and zero otherwise. |key| must already have had a
 // group configured (see |EC_KEY_set_group| and |EC_KEY_new_by_curve_name|), and
-// |pub| must also belong to that group.
+// |pub| must also belong to that group, and must not be the point at infinity.
 OPENSSL_EXPORT int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub);
 
 #define EC_PKEY_NO_PARAMETERS 0x001