Skip to content

Commit c15e28d

Browse files
authored
Reject point at infinity in EC_KEY_set_public_key (#3101)
Add an explicit check in EC_KEY_set_public_key to reject the point at infinity. The point at infinity is not a valid public key. This matches the hardening added in BoringSSL google/boringssl@a135fe1. Call-outs: Parsing (EC_POINT_oct2point) continues to accept the infinity encoding for OpenSSL compatibility, as added in de33f5e, but it can no longer be installed as a public key on an EC_KEY. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.
1 parent 4738958 commit c15e28d

File tree

4 files changed

+32
-3
lines changed

4 files changed

+32
-3
lines changed

crypto/ec_extra/ec_asn1.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,10 @@ EC_KEY *o2i_ECPublicKey(EC_KEY **keyp, const uint8_t **inp, long len) {
562562
OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
563563
return NULL;
564564
}
565+
if (EC_POINT_is_at_infinity(ret->group, ret->pub_key)) {
566+
OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
567+
return NULL;
568+
}
565569
// save the point conversion form
566570
ret->conv_form = (point_conversion_form_t)(*inp[0] & ~0x01);
567571
*inp += len;

crypto/fipsmodule/ec/ec_key.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) {
206206
return 0;
207207
}
208208

209+
if (pub_key != NULL && EC_POINT_is_at_infinity(key->group, pub_key)) {
210+
OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
211+
return 0;
212+
}
213+
209214
if (pub_key != NULL && EC_GROUP_cmp(key->group, pub_key->group, NULL) != 0) {
210215
OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
211216
return 0;

crypto/fipsmodule/ec/ec_test.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,12 @@ struct InvalidECPublicKey {
957957
size_t input_key_len;
958958
int nid;
959959
} kInvalidECPublicKeyInputs[] = {
960+
/* Test 0: point at infinity. */
961+
{
962+
(const uint8_t *)"\x00",
963+
1,
964+
NID_X9_62_prime256v1
965+
},
960966
/* Test 1: incorrect compresion representation. */
961967
{
962968
kP224PublicKey_wrong_compressed_byte,
@@ -1354,6 +1360,19 @@ TEST(ECTest, SetNULLKey) {
13541360
EXPECT_FALSE(EC_KEY_get0_public_key(key.get()));
13551361
}
13561362

1363+
TEST(ECTest, PointAtInfinity) {
1364+
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
1365+
ASSERT_TRUE(key);
1366+
1367+
bssl::UniquePtr<EC_POINT> inf(
1368+
EC_POINT_new(EC_KEY_get0_group(key.get())));
1369+
ASSERT_TRUE(inf);
1370+
ASSERT_TRUE(
1371+
EC_POINT_set_to_infinity(EC_KEY_get0_group(key.get()), inf.get()));
1372+
// Configuring a public key with the point at infinity is invalid.
1373+
EXPECT_FALSE(EC_KEY_set_public_key(key.get(), inf.get()));
1374+
}
1375+
13571376
TEST(ECTest, GroupMismatch) {
13581377
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_secp384r1));
13591378
ASSERT_TRUE(key);

include/openssl/ec_key.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ OPENSSL_EXPORT const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key);
8282
// EC_KEY_set_public_key sets the public key of |key| to |pub|, by copying it.
8383
// It returns one on success and zero otherwise. |key| must already have had a
8484
// group configured (see |EC_KEY_set_group| and |EC_KEY_new_by_curve_name|), and
85-
// |pub| must also belong to that group.
85+
// |pub| must also belong to that group, and must not be the point at infinity.
8686
OPENSSL_EXPORT int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub);
8787

8888
#define EC_PKEY_NO_PARAMETERS 0x001
@@ -273,8 +273,9 @@ OPENSSL_EXPORT int i2d_ECPKParameters_bio(BIO *bio, const EC_GROUP *group);
273273

274274
// o2i_ECPublicKey parses an EC point from |len| bytes at |*inp| into
275275
// |*out_key|. Note that this differs from the d2i format in that |*out_key|
276-
// must be non-NULL with a group set. On successful exit, |*inp| is advanced by
277-
// |len| bytes. It returns |*out_key| or NULL on error.
276+
// must be non-NULL with a group set. The point must not be the point at
277+
// infinity. On successful exit, |*inp| is advanced by |len| bytes. It returns
278+
// |*out_key| or NULL on error.
278279
//
279280
// Use |EC_POINT_oct2point| instead.
280281
OPENSSL_EXPORT EC_KEY *o2i_ECPublicKey(EC_KEY **out_key, const uint8_t **inp,

0 commit comments

Comments
 (0)