diff --git a/crypto/ec_extra/ec_asn1.c b/crypto/ec_extra/ec_asn1.c index c01aaa08d2..e867a390df 100644 --- a/crypto/ec_extra/ec_asn1.c +++ b/crypto/ec_extra/ec_asn1.c @@ -56,8 +56,9 @@ #include #include -#include +#include #include +#include #include #include #include @@ -76,19 +77,15 @@ static const CBS_ASN1_TAG kPublicKeyTag = // acceptable groups, so parsers don't have to pull in all four. typedef const EC_GROUP *(*ec_group_func)(void); static const ec_group_func kAllGroups[] = { - &EC_group_p224, - &EC_group_p256, - &EC_group_p384, - &EC_group_p521, - &EC_group_secp256k1, + &EC_group_p224, &EC_group_p256, &EC_group_p384, + &EC_group_p521, &EC_group_secp256k1, }; EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) { CBS ec_private_key, private_key; uint64_t version; if (!CBS_get_asn1(cbs, &ec_private_key, CBS_ASN1_SEQUENCE) || - !CBS_get_asn1_uint64(&ec_private_key, &version) || - version != 1 || + !CBS_get_asn1_uint64(&ec_private_key, &version) || version != 1 || !CBS_get_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING)) { OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); return NULL; @@ -151,8 +148,7 @@ EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) { !CBS_get_asn1(&child, &public_key, CBS_ASN1_BITSTRING) || // As in a SubjectPublicKeyInfo, the byte-encoded public key is then // encoded as a BIT STRING with bits ordered as in the DER encoding. - !CBS_get_u8(&public_key, &padding) || - padding != 0 || + !CBS_get_u8(&public_key, &padding) || padding != 0 || // Explicitly check |public_key| is non-empty to save the conversion // form later. CBS_len(&public_key) == 0 || @@ -264,16 +260,14 @@ static int parse_explicit_prime_curve(CBS *in, int has_cofactor; uint64_t version; if (!CBS_get_asn1(in, ¶ms, CBS_ASN1_SEQUENCE) || - !CBS_get_asn1_uint64(¶ms, &version) || - version != 1 || + !CBS_get_asn1_uint64(¶ms, &version) || version != 1 || !CBS_get_asn1(¶ms, &field_id, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&field_id, &field_type, CBS_ASN1_OBJECT) || CBS_len(&field_type) != sizeof(kPrimeField) || OPENSSL_memcmp(CBS_data(&field_type), kPrimeField, sizeof(kPrimeField)) != 0 || !CBS_get_asn1(&field_id, &out->prime, CBS_ASN1_INTEGER) || - !CBS_is_unsigned_asn1_integer(&out->prime) || - CBS_len(&field_id) != 0 || + !CBS_is_unsigned_asn1_integer(&out->prime) || CBS_len(&field_id) != 0 || !CBS_get_asn1(¶ms, &curve, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&curve, &out->a, CBS_ASN1_OCTETSTRING) || !CBS_get_asn1(&curve, &out->b, CBS_ASN1_OCTETSTRING) || @@ -292,8 +286,7 @@ static int parse_explicit_prime_curve(CBS *in, if (has_cofactor) { // We only support prime-order curves so the cofactor must be one. - if (CBS_len(&cofactor) != 1 || - CBS_data(&cofactor)[0] != 1) { + if (CBS_len(&cofactor) != 1 || CBS_data(&cofactor)[0] != 1) { OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP); return 0; } @@ -546,6 +539,40 @@ int i2d_ECPKParameters(const EC_GROUP *group, uint8_t **outp) { return CBB_finish_i2d(&cbb, outp); } +EC_GROUP *d2i_ECPKParameters_bio(BIO *bio, EC_GROUP **out_group) { + if (bio == NULL) { + OPENSSL_PUT_ERROR(PKCS7, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + uint8_t *data; + size_t len; + if (!BIO_read_asn1(bio, &data, &len, INT_MAX)) { + return NULL; + } + const uint8_t *ptr = data; + EC_GROUP *ret = d2i_ECPKParameters(out_group, &ptr, len); + OPENSSL_free(data); + return ret; +} + +int i2d_ECPKParameters_bio(BIO *bio, const EC_GROUP *group) { + if (bio == NULL || group == NULL) { + OPENSSL_PUT_ERROR(PKCS7, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + uint8_t *out = NULL; + int len = i2d_ECPKParameters(group, &out); + if (out == NULL) { + return 0; + } + + int ret = BIO_write_all(bio, out, len); + OPENSSL_free(out); + return ret; +} + EC_KEY *o2i_ECPublicKey(EC_KEY **keyp, const uint8_t **inp, long len) { EC_KEY *ret = NULL; @@ -599,8 +626,8 @@ size_t EC_get_builtin_curves(EC_builtin_curve *out_curves, } static size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point, - point_conversion_form_t form, - uint8_t **pbuf, BN_CTX *ctx) { + point_conversion_form_t form, uint8_t **pbuf, + BN_CTX *ctx) { size_t len; uint8_t *buf; diff --git a/crypto/fipsmodule/ec/ec_test.cc b/crypto/fipsmodule/ec/ec_test.cc index 20d91a9018..18a58ee49c 100644 --- a/crypto/fipsmodule/ec/ec_test.cc +++ b/crypto/fipsmodule/ec/ec_test.cc @@ -2551,3 +2551,12 @@ TEST(ECTest, ECEngine) { EC_KEY_METHOD_free(eng_funcs); } +TEST(ECTest, ECPKParmatersBio) { + bssl::UniquePtr bio(BIO_new(BIO_s_mem())); + + EXPECT_TRUE(i2d_ECPKParameters_bio(bio.get(), EC_group_p256())); + EXPECT_EQ(d2i_ECPKParameters_bio(bio.get(), nullptr), EC_group_p256()); + + EXPECT_TRUE(i2d_ECPKParameters_bio(bio.get(), EC_group_secp256k1())); + EXPECT_EQ(d2i_ECPKParameters_bio(bio.get(), nullptr), EC_group_secp256k1()); +} diff --git a/crypto/fipsmodule/ec/internal.h b/crypto/fipsmodule/ec/internal.h index 86e7dfb202..70f493238e 100644 --- a/crypto/fipsmodule/ec/internal.h +++ b/crypto/fipsmodule/ec/internal.h @@ -823,7 +823,10 @@ struct ec_key_st { // d2i_ECPKParameters deserializes the |ECPKParameters| specified in RFC 3279 // to an |EC_GROUP| from |inp|. Only deserialization of namedCurves or -// explicitly-encoded versions of namedCurves are supported. +// explicitly-encoded versions of namedCurves are supported. If |*out_group| is +// non-null, the original |*out_group| is freed and the returned |EC_GROUP| is +// also written to |*out_group|. The user continues to maintain the memory +// assigned to |*out_group| if non-null. EC_GROUP *d2i_ECPKParameters(EC_GROUP **out_group, const uint8_t **inp, long len); diff --git a/crypto/rand_extra/rand_extra.c b/crypto/rand_extra/rand_extra.c index 48176e7bf9..65ba63d0b3 100644 --- a/crypto/rand_extra/rand_extra.c +++ b/crypto/rand_extra/rand_extra.c @@ -46,6 +46,10 @@ int RAND_egd(const char *path) { return 255; } +int RAND_egd_bytes(const char *path, int bytes) { + return bytes; +} + int RAND_poll(void) { return 1; } diff --git a/include/openssl/ec_key.h b/include/openssl/ec_key.h index 3a826ba87a..824c043ac0 100644 --- a/include/openssl/ec_key.h +++ b/include/openssl/ec_key.h @@ -312,6 +312,22 @@ OPENSSL_EXPORT EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp, // are supported. OPENSSL_EXPORT int i2d_ECParameters(const EC_KEY *key, uint8_t **outp); +// d2i_ECPKParameters_bio deserializes the |ECPKParameters| specified in RFC +// 3279 from |bio| and returns the corresponding |EC_GROUP|. If |*out_group| is +// non-null, the original |*out_group| is freed and the returned |EC_GROUP| is +// also written to |*out_group|. The user continues to maintain the memory +// assigned to |*out_group| if non-null. +// +// Only deserialization of namedCurves or +// explicitly-encoded versions of namedCurves are supported. +OPENSSL_EXPORT EC_GROUP *d2i_ECPKParameters_bio(BIO *bio, EC_GROUP **out_group); + +// i2d_ECPKParameters_bio serializes an |EC_GROUP| to |bio| according to the +// |ECPKParameters| specified in RFC 3279. It returns 1 on success and 0 on +// failure. +// Only serialization of namedCurves are supported. +OPENSSL_EXPORT int i2d_ECPKParameters_bio(BIO *bio, const EC_GROUP *group); + // o2i_ECPublicKey parses an EC point from |len| bytes at |*inp| into // |*out_key|. Note that this differs from the d2i format in that |*out_key| // must be non-NULL with a group set. On successful exit, |*inp| is advanced by @@ -361,7 +377,8 @@ OPENSSL_EXPORT const EC_KEY_METHOD *EC_KEY_OpenSSL(void); // returned |EC_KEY_METHOD| object will be initialized to the values from // |eckey_meth|. If |eckey_meth| is NULL, the returned object will be // initialized using the value returned from |EC_KEY_get_default_method|. -OPENSSL_EXPORT EC_KEY_METHOD *EC_KEY_METHOD_new(const EC_KEY_METHOD *eckey_meth); +OPENSSL_EXPORT EC_KEY_METHOD *EC_KEY_METHOD_new( + const EC_KEY_METHOD *eckey_meth); // EC_KEY_METHOD_free frees the memory associated with |eckey_meth| OPENSSL_EXPORT void EC_KEY_METHOD_free(EC_KEY_METHOD *eckey_meth); @@ -379,42 +396,40 @@ OPENSSL_EXPORT const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *ec); // EC_KEY_METHOD_set_sign_awslc sets the |sign| and |sign_sig| pointers on // |meth|. -OPENSSL_EXPORT void EC_KEY_METHOD_set_sign_awslc(EC_KEY_METHOD *meth, - int (*sign)(int type, const uint8_t *digest, - int digest_len, uint8_t *sig, - unsigned int *siglen, - const BIGNUM *k_inv, - const BIGNUM *r, EC_KEY *eckey), - ECDSA_SIG *(*sign_sig)(const uint8_t *digest, - int digest_len, - const BIGNUM *in_kinv, - const BIGNUM *in_r, - EC_KEY *eckey)); +OPENSSL_EXPORT void EC_KEY_METHOD_set_sign_awslc( + EC_KEY_METHOD *meth, + int (*sign)(int type, const uint8_t *digest, int digest_len, uint8_t *sig, + unsigned int *siglen, const BIGNUM *k_inv, const BIGNUM *r, + EC_KEY *eckey), + ECDSA_SIG *(*sign_sig)(const uint8_t *digest, int digest_len, + const BIGNUM *in_kinv, const BIGNUM *in_r, + EC_KEY *eckey)); // EC_KEY_METHOD_set_sign sets function pointers on |meth|. AWS-LC currently // supports setting |sign| and |sign_sig|. |sign_setup| must be set to NULL in // order to compile with AWS-LC. -#define EC_KEY_METHOD_set_sign(meth, sign, sign_setup, sign_sig) \ - OPENSSL_STATIC_ASSERT((sign_setup) == NULL, \ - EC_KEY_METHOD_sign_setup_field_must_be_NULL); \ +#define EC_KEY_METHOD_set_sign(meth, sign, sign_setup, sign_sig) \ + OPENSSL_STATIC_ASSERT((sign_setup) == NULL, \ + EC_KEY_METHOD_sign_setup_field_must_be_NULL); \ EC_KEY_METHOD_set_sign_awslc(meth, sign, sign_sig); // EC_KEY_METHOD_set_init_awslc sets the |init| and |finish| pointers on |meth|. OPENSSL_EXPORT void EC_KEY_METHOD_set_init_awslc(EC_KEY_METHOD *meth, - int (*init)(EC_KEY *key), - void (*finish)(EC_KEY *key)); + int (*init)(EC_KEY *key), + void (*finish)(EC_KEY *key)); // EC_KEY_METHOD_set_init sets function pointers on |meth|. AWS-LC // currently only supports setting the |init| and |finish| fields. |copy|, // |set_group|, |set_private|, and |set_public| cannot be set yet and must // be NULL. -#define EC_KEY_METHOD_set_init(meth, init, finish, copy, set_group, \ - set_private, set_public) \ - OPENSSL_STATIC_ASSERT((copy) == NULL && (set_group) == NULL && \ - (set_private) == NULL && (set_public) == NULL, \ - EC_KEY_METHOD_copy_set_group_set_private_and_set_public_fields_must_be_NULL);\ +#define EC_KEY_METHOD_set_init(meth, init, finish, copy, set_group, \ + set_private, set_public) \ + OPENSSL_STATIC_ASSERT( \ + (copy) == NULL && (set_group) == NULL && (set_private) == NULL && \ + (set_public) == NULL, \ + EC_KEY_METHOD_copy_set_group_set_private_and_set_public_fields_must_be_NULL); \ EC_KEY_METHOD_set_init_awslc(meth, init, finish); // EC_KEY_METHOD_set_flags sets |flags| on |meth|. Currently, the only supported diff --git a/include/openssl/rand.h b/include/openssl/rand.h index d317da6016..fddb890f0c 100644 --- a/include/openssl/rand.h +++ b/include/openssl/rand.h @@ -104,6 +104,9 @@ OPENSSL_EXPORT OPENSSL_DEPRECATED void RAND_add(const void *buf, int num, // RAND_egd returns 255. OPENSSL_EXPORT OPENSSL_DEPRECATED int RAND_egd(const char *); +// RAND_egd_bytes returns |bytes|. +OPENSSL_EXPORT OPENSSL_DEPRECATED int RAND_egd_bytes(const char *, int bytes); + // RAND_poll returns one. OPENSSL_EXPORT OPENSSL_DEPRECATED int RAND_poll(void);