Skip to content

Commit

Permalink
More minor symbols Ruby depends on (#1837)
Browse files Browse the repository at this point in the history
We noticed three missing symbols after testing where we were at with our
support for Ruby. These are all pretty minor and are related to work
we've already done.
* The underlying work for `d2i_ECPKParameters_bio` and
`i2d_ECPKParameters_bio` was already completed with 6056999.
Coverage for actually parsing is included in that PR, so I've only added
brief tests to ensure that the same behavior applies to the BIO methods.
* `RAND_egd_bytes` is for querying the entropy gathering daemon EGD on
the socket path. We already no-op `RAND_egd` (which directly calls
`RAND_egd_bytes` in OpenSSL), so I've applied the same no-op behavior
here as well.

### Testing:
Minor tests for `d2i_ECPKParameters_bio` and `i2d_ECPKParameters_bio`.

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.
  • Loading branch information
samuel40791765 authored Sep 10, 2024
1 parent e4092fb commit 80d9c1e
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 41 deletions.
63 changes: 45 additions & 18 deletions crypto/ec_extra/ec_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@
#include <limits.h>
#include <string.h>

#include <openssl/bytestring.h>
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/nid.h>
Expand All @@ -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;
Expand Down Expand Up @@ -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 ||
Expand Down Expand Up @@ -264,16 +260,14 @@ static int parse_explicit_prime_curve(CBS *in,
int has_cofactor;
uint64_t version;
if (!CBS_get_asn1(in, &params, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1_uint64(&params, &version) ||
version != 1 ||
!CBS_get_asn1_uint64(&params, &version) || version != 1 ||
!CBS_get_asn1(&params, &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(&params, &curve, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1(&curve, &out->a, CBS_ASN1_OCTETSTRING) ||
!CBS_get_asn1(&curve, &out->b, CBS_ASN1_OCTETSTRING) ||
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down
9 changes: 9 additions & 0 deletions crypto/fipsmodule/ec/ec_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2551,3 +2551,12 @@ TEST(ECTest, ECEngine) {
EC_KEY_METHOD_free(eng_funcs);
}

TEST(ECTest, ECPKParmatersBio) {
bssl::UniquePtr<BIO> 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());
}
5 changes: 4 additions & 1 deletion crypto/fipsmodule/ec/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
4 changes: 4 additions & 0 deletions crypto/rand_extra/rand_extra.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
59 changes: 37 additions & 22 deletions include/openssl/ec_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down
3 changes: 3 additions & 0 deletions include/openssl/rand.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit 80d9c1e

Please sign in to comment.