From 3432648d2669b5c60786d353a050b69550b606fa Mon Sep 17 00:00:00 2001 From: samuel40791765 Date: Wed, 3 Jul 2024 00:11:25 +0000 Subject: [PATCH] Documentation and extra test --- crypto/ec_extra/ec_asn1.c | 7 +- crypto/fipsmodule/ec/ec_test.cc | 219 +++++++++++++++++++------------- include/openssl/ec.h | 31 +++-- 3 files changed, 153 insertions(+), 104 deletions(-) diff --git a/crypto/ec_extra/ec_asn1.c b/crypto/ec_extra/ec_asn1.c index b91991f2bb8..c15cae28314 100644 --- a/crypto/ec_extra/ec_asn1.c +++ b/crypto/ec_extra/ec_asn1.c @@ -617,10 +617,15 @@ BIGNUM *EC_POINT_point2bn(const EC_GROUP *group, const EC_POINT *point, EC_POINT *EC_POINT_bn2point(const EC_GROUP *group, const BIGNUM *bn, EC_POINT *point, BN_CTX *ctx) { + if (group == NULL || bn == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + // Allocate buffer and length. size_t buf_len = BN_num_bytes(bn); if (buf_len == 0) { - // See https://github.com/openssl/openssl/issues/10258 + // See https://github.com/openssl/openssl/issues/10258. buf_len = 1; } uint8_t *buf = OPENSSL_malloc(buf_len); diff --git a/crypto/fipsmodule/ec/ec_test.cc b/crypto/fipsmodule/ec/ec_test.cc index dc70464a845..d4b795240ac 100644 --- a/crypto/fipsmodule/ec/ec_test.cc +++ b/crypto/fipsmodule/ec/ec_test.cc @@ -938,56 +938,58 @@ TEST(ECTest, SpecifiedCurve) { EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size())); } +// An arbitrary curve which is identical to P-256. +static const uint8_t kP256P[] = { + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; +static const uint8_t kP256A[] = { + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, +}; +static const uint8_t kP256B[] = { + 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, + 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, + 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, +}; +static const uint8_t kP256X[] = { + 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, + 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, + 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, +}; +static const uint8_t kP256Y[] = { + 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, + 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, + 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, +}; +static const uint8_t kP256Order[] = { + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, + 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, +}; + TEST(ECTest, ArbitraryCurve) { // Make a P-256 key and extract the affine coordinates. bssl::UniquePtr key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); ASSERT_TRUE(key); ASSERT_TRUE(EC_KEY_generate_key(key.get())); - // Make an arbitrary curve which is identical to P-256. - static const uint8_t kP[] = { - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }; - static const uint8_t kA[] = { - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - }; - static const uint8_t kB[] = { - 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, - 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, - 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, - }; - static const uint8_t kX[] = { - 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, - 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, - 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, - }; - static const uint8_t kY[] = { - 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, - 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, - 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, - }; - static const uint8_t kOrder[] = { - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, - 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, - }; bssl::UniquePtr ctx(BN_CTX_new()); ASSERT_TRUE(ctx); - bssl::UniquePtr p(BN_bin2bn(kP, sizeof(kP), nullptr)); + bssl::UniquePtr p(BN_bin2bn(kP256P, sizeof(kP256P), nullptr)); ASSERT_TRUE(p); - bssl::UniquePtr a(BN_bin2bn(kA, sizeof(kA), nullptr)); + bssl::UniquePtr a(BN_bin2bn(kP256A, sizeof(kP256A), nullptr)); ASSERT_TRUE(a); - bssl::UniquePtr b(BN_bin2bn(kB, sizeof(kB), nullptr)); + bssl::UniquePtr b(BN_bin2bn(kP256B, sizeof(kP256B), nullptr)); ASSERT_TRUE(b); - bssl::UniquePtr gx(BN_bin2bn(kX, sizeof(kX), nullptr)); + bssl::UniquePtr gx(BN_bin2bn(kP256X, sizeof(kP256X), nullptr)); ASSERT_TRUE(gx); - bssl::UniquePtr gy(BN_bin2bn(kY, sizeof(kY), nullptr)); + bssl::UniquePtr gy(BN_bin2bn(kP256Y, sizeof(kP256Y), nullptr)); ASSERT_TRUE(gy); - bssl::UniquePtr order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr)); + bssl::UniquePtr order( + BN_bin2bn(kP256Order, sizeof(kP256Order), nullptr)); ASSERT_TRUE(order); bssl::UniquePtr group( @@ -1037,56 +1039,6 @@ TEST(ECTest, ArbitraryCurve) { EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group.get(), nullptr)); EXPECT_EQ(0, EC_GROUP_cmp(group2.get(), group.get(), nullptr)); - // Convert |EC_POINT| to |BIGNUM| in uncompressed format with - // |EC_POINT_point2bn| and ensure results are the same. - bssl::UniquePtr converted_bignum( - EC_POINT_point2bn(group.get(), generator.get(), - POINT_CONVERSION_UNCOMPRESSED, nullptr, nullptr)); - ASSERT_TRUE(converted_bignum); - bssl::UniquePtr converted_bignum2( - EC_POINT_point2bn(group2.get(), generator2.get(), - POINT_CONVERSION_UNCOMPRESSED, nullptr, nullptr)); - ASSERT_TRUE(converted_bignum2); - EXPECT_EQ(0, BN_cmp(converted_bignum.get(), converted_bignum2.get())); - - // Convert |BIGNUM| back to |EC_POINTS| with |EC_POINT_bn2point| and ensure - // output is identical to the original. - bssl::UniquePtr converted_generator( - EC_POINT_bn2point(group.get(), converted_bignum.get(), nullptr, nullptr)); - ASSERT_TRUE(converted_generator); - EXPECT_EQ(0, EC_POINT_cmp(group.get(), generator.get(), - converted_generator.get(), nullptr)); - bssl::UniquePtr converted_generator2(EC_POINT_bn2point( - group2.get(), converted_bignum2.get(), nullptr, nullptr)); - ASSERT_TRUE(converted_generator2); - EXPECT_EQ(0, EC_POINT_cmp(group2.get(), generator2.get(), - converted_generator2.get(), nullptr)); - - // Convert |EC_POINT|s in compressed format with |EC_POINT_point2bn| and - // ensure results are the same. - converted_bignum.reset(EC_POINT_point2bn(group.get(), generator.get(), - POINT_CONVERSION_COMPRESSED, nullptr, - nullptr)); - ASSERT_TRUE(converted_bignum); - converted_bignum2.reset(EC_POINT_point2bn(group2.get(), generator2.get(), - POINT_CONVERSION_COMPRESSED, - nullptr, nullptr)); - ASSERT_TRUE(converted_bignum2); - EXPECT_EQ(0, BN_cmp(converted_bignum.get(), converted_bignum2.get())); - - // Convert |BIGNUM| back to |EC_POINTS| with |EC_POINT_bn2point| and ensure - // output is identical to the original. - converted_generator.reset( - EC_POINT_bn2point(group.get(), converted_bignum.get(), nullptr, nullptr)); - ASSERT_TRUE(converted_generator); - EXPECT_EQ(0, EC_POINT_cmp(group.get(), generator.get(), - converted_generator.get(), nullptr)); - converted_generator2.reset(EC_POINT_bn2point( - group2.get(), converted_bignum2.get(), nullptr, nullptr)); - ASSERT_TRUE(converted_generator2); - EXPECT_EQ(0, EC_POINT_cmp(group2.get(), generator2.get(), - converted_generator2.get(), nullptr)); - // group3 uses the wrong generator. bssl::UniquePtr group3( EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get())); @@ -1141,6 +1093,99 @@ TEST(ECTest, ArbitraryCurve) { EXPECT_EQ(0, EC_GROUP_cmp(group5.get(), group.get(), NULL)); } +TEST(ECTest, BIGNUMConvert) { + bssl::UniquePtr ctx(BN_CTX_new()); + ASSERT_TRUE(ctx); + bssl::UniquePtr p(BN_bin2bn(kP256P, sizeof(kP256P), nullptr)); + ASSERT_TRUE(p); + bssl::UniquePtr a(BN_bin2bn(kP256A, sizeof(kP256A), nullptr)); + ASSERT_TRUE(a); + bssl::UniquePtr b(BN_bin2bn(kP256B, sizeof(kP256B), nullptr)); + ASSERT_TRUE(b); + bssl::UniquePtr gx(BN_bin2bn(kP256X, sizeof(kP256X), nullptr)); + ASSERT_TRUE(gx); + bssl::UniquePtr gy(BN_bin2bn(kP256Y, sizeof(kP256Y), nullptr)); + ASSERT_TRUE(gy); + bssl::UniquePtr order( + BN_bin2bn(kP256Order, sizeof(kP256Order), nullptr)); + ASSERT_TRUE(order); + + bssl::UniquePtr group( + EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get())); + ASSERT_TRUE(group); + bssl::UniquePtr generator(EC_POINT_new(group.get())); + ASSERT_TRUE(generator); + ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp( + group.get(), generator.get(), gx.get(), gy.get(), ctx.get())); + ASSERT_TRUE(EC_GROUP_set_generator(group.get(), generator.get(), order.get(), + BN_value_one())); + + // Make a second instance of |group|. + bssl::UniquePtr group2( + EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get())); + ASSERT_TRUE(group2); + bssl::UniquePtr generator2(EC_POINT_new(group2.get())); + ASSERT_TRUE(generator2); + ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp( + group2.get(), generator2.get(), gx.get(), gy.get(), ctx.get())); + ASSERT_TRUE(EC_GROUP_set_generator(group2.get(), generator2.get(), + order.get(), BN_value_one())); + + // Convert |EC_POINT| to |BIGNUM| in uncompressed format with + // |EC_POINT_point2bn| and ensure results are the same. + bssl::UniquePtr converted_bignum( + EC_POINT_point2bn(group.get(), generator.get(), + POINT_CONVERSION_UNCOMPRESSED, nullptr, nullptr)); + ASSERT_TRUE(converted_bignum); + bssl::UniquePtr converted_bignum2( + EC_POINT_point2bn(group2.get(), generator2.get(), + POINT_CONVERSION_UNCOMPRESSED, nullptr, nullptr)); + ASSERT_TRUE(converted_bignum2); + EXPECT_EQ(0, BN_cmp(converted_bignum.get(), converted_bignum2.get())); + + // Convert |BIGNUM| back to |EC_POINTS| with |EC_POINT_bn2point| and ensure + // output is identical to the original. + bssl::UniquePtr converted_generator( + EC_POINT_bn2point(group.get(), converted_bignum.get(), nullptr, nullptr)); + ASSERT_TRUE(converted_generator); + EXPECT_EQ(0, EC_POINT_cmp(group.get(), generator.get(), + converted_generator.get(), nullptr)); + bssl::UniquePtr converted_generator2(EC_POINT_bn2point( + group2.get(), converted_bignum2.get(), nullptr, nullptr)); + ASSERT_TRUE(converted_generator2); + EXPECT_EQ(0, EC_POINT_cmp(group2.get(), generator2.get(), + converted_generator2.get(), nullptr)); + + // Convert |EC_POINT|s in compressed format with |EC_POINT_point2bn| and + // ensure results are the same. + converted_bignum.reset(EC_POINT_point2bn(group.get(), generator.get(), + POINT_CONVERSION_COMPRESSED, nullptr, + nullptr)); + ASSERT_TRUE(converted_bignum); + converted_bignum2.reset(EC_POINT_point2bn(group2.get(), generator2.get(), + POINT_CONVERSION_COMPRESSED, + nullptr, nullptr)); + ASSERT_TRUE(converted_bignum2); + EXPECT_EQ(0, BN_cmp(converted_bignum.get(), converted_bignum2.get())); + + // Convert |BIGNUM| back to |EC_POINTS| with |EC_POINT_bn2point| and ensure + // output is identical to the original. + converted_generator.reset( + EC_POINT_bn2point(group.get(), converted_bignum.get(), nullptr, nullptr)); + ASSERT_TRUE(converted_generator); + EXPECT_EQ(0, EC_POINT_cmp(group.get(), generator.get(), + converted_generator.get(), nullptr)); + converted_generator2.reset(EC_POINT_bn2point( + group2.get(), converted_bignum2.get(), nullptr, nullptr)); + ASSERT_TRUE(converted_generator2); + EXPECT_EQ(0, EC_POINT_cmp(group2.get(), generator2.get(), + converted_generator2.get(), nullptr)); + + bssl::UniquePtr zero(BN_new()); + BN_zero(zero.get()); + EXPECT_TRUE(EC_POINT_bn2point(group.get(), zero.get(), nullptr, nullptr)); +} + TEST(ECTest, SetKeyWithoutGroup) { bssl::UniquePtr key(EC_KEY_new()); ASSERT_TRUE(key); diff --git a/include/openssl/ec.h b/include/openssl/ec.h index b4a405913d3..0497feddf3b 100644 --- a/include/openssl/ec.h +++ b/include/openssl/ec.h @@ -392,28 +392,27 @@ OPENSSL_EXPORT int EC_GROUP_set_generator(EC_GROUP *group, const BIGNUM *cofactor); -// EC_POINT_point2bn serialises |point| into the X9.62 form given by |form| -// and returns the |BIGNUM| representation of the serialised output. -// On success, it returns the BIGNUM pointer supplied or, if |ret| is NULL, -// allocates and returns a fresh |BIGNUM|. On error, it returns NULL. The |ctx| -// argument may be used if not NULL. +// EC_POINT_point2bn calls |EC_POINT_point2oct| to serialize |point| into the +// X9.62 form given by |form| and returns the serialized output as a |BIGNUM|. +// The returned |BIGNUM| is a representation of serialized bytes. On success, it +// returns the |BIGNUM| pointer supplied or, if |ret| is NULL, allocates and +// returns a fresh |BIGNUM|. On error, it returns NULL. The |ctx| argument may +// be used if not NULL. // -// Note: |EC_POINT| serialization formats are not individual big-endian -// integers, so these aren't particularly useful. Use |EC_POINT_point2oct| -// instead. +// Note: |EC_POINT|s are not individual |BIGNUM| integers, so these aren't +// particularly useful. Use |EC_POINT_point2oct| directly instead. OPENSSL_EXPORT OPENSSL_DEPRECATED BIGNUM *EC_POINT_point2bn( const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, BIGNUM *ret, BN_CTX *ctx); -// EC_POINT_bn2point is like |EC_POINT_point2bn|, but takes the |BIGNUM| -// representation and de-serialises it back to an |EC_POINT|. On success, -// it returns the EC_POINT pointer supplied or, if |ret| is NULL, allocates and -// returns a fresh |EC_POINT|. On error, it returns NULL. The |ctx| argument -// may be used if not NULL. +// EC_POINT_bn2point is like |EC_POINT_point2bn|, but calls |EC_POINT_oct2point| +// to de-serialize the |BIGNUM| representation of bytes back to an |EC_POINT|. +// On success, it returns the |EC_POINT| pointer supplied or, if |ret| is NULL, +// allocates and returns a fresh |EC_POINT|. On error, it returns NULL. The +// |ctx| argument may be used if not NULL. // -// Note: |EC_POINT| serialization formats are not individual big-endian -// integers, so these aren't particularly useful. Use |EC_POINT_oct2point| -// instead. +// Note: |EC_POINT|s are not individual |BIGNUM| integers, so these aren't +// particularly useful. Use |EC_POINT_oct2point| directly instead. OPENSSL_EXPORT OPENSSL_DEPRECATED EC_POINT *EC_POINT_bn2point( const EC_GROUP *group, const BIGNUM *bn, EC_POINT *point, BN_CTX *ctx);