Remove some unnecessary dependencies on EVP_PKEY_set_type EVP_PKEY_set_type needs to pull in every supported EVP_PKEY type, but most of our calls within the library already know what type they're working with. Have them call evp_pkey_set_method directly. Bug: 497 Change-Id: I17cb9a0dff0da55206686bce1d8e1df4773f6f4d Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/67127 Reviewed-by: Bob Beck <bbe@google.com> Auto-Submit: David Benjamin <davidben@google.com> Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/evp/evp.c b/crypto/evp/evp.c index f3f3d7e..babf709 100644 --- a/crypto/evp/evp.c +++ b/crypto/evp/evp.c
@@ -149,9 +149,7 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { if (to->type == EVP_PKEY_NONE) { - if (!EVP_PKEY_set_type(to, from->type)) { - return 0; - } + evp_pkey_set_method(to, from->ameth); } else if (to->type != from->type) { OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES); return 0; @@ -225,8 +223,7 @@ } } -static void evp_pkey_set_method(EVP_PKEY *pkey, - const EVP_PKEY_ASN1_METHOD *method) { +void evp_pkey_set_method(EVP_PKEY *pkey, const EVP_PKEY_ASN1_METHOD *method) { free_it(pkey); pkey->ameth = method; pkey->type = pkey->ameth->pkey_id;
diff --git a/crypto/evp/evp_asn1.c b/crypto/evp/evp_asn1.c index f270c3e..8f341e9 100644 --- a/crypto/evp/evp_asn1.c +++ b/crypto/evp/evp_asn1.c
@@ -77,28 +77,26 @@ &x25519_asn1_meth, }; -static int parse_key_type(CBS *cbs, int *out_type) { +static const EVP_PKEY_ASN1_METHOD *parse_key_type(CBS *cbs) { CBS oid; if (!CBS_get_asn1(cbs, &oid, CBS_ASN1_OBJECT)) { - return 0; + return NULL; } for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kASN1Methods); i++) { const EVP_PKEY_ASN1_METHOD *method = kASN1Methods[i]; if (CBS_len(&oid) == method->oid_len && OPENSSL_memcmp(CBS_data(&oid), method->oid, method->oid_len) == 0) { - *out_type = method->pkey_id; - return 1; + return method; } } - return 0; + return NULL; } EVP_PKEY *EVP_parse_public_key(CBS *cbs) { // Parse the SubjectPublicKeyInfo. CBS spki, algorithm, key; - int type; uint8_t padding; if (!CBS_get_asn1(cbs, &spki, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || @@ -107,7 +105,8 @@ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return NULL; } - if (!parse_key_type(&algorithm, &type)) { + const EVP_PKEY_ASN1_METHOD *method = parse_key_type(&algorithm); + if (method == NULL) { OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); return NULL; } @@ -121,10 +120,10 @@ // Set up an |EVP_PKEY| of the appropriate type. EVP_PKEY *ret = EVP_PKEY_new(); - if (ret == NULL || - !EVP_PKEY_set_type(ret, type)) { + if (ret == NULL) { goto err; } + evp_pkey_set_method(ret, method); // Call into the type-specific SPKI decoding function. if (ret->ameth->pub_decode == NULL) { @@ -155,7 +154,6 @@ // Parse the PrivateKeyInfo. CBS pkcs8, algorithm, key; uint64_t version; - int type; if (!CBS_get_asn1(cbs, &pkcs8, CBS_ASN1_SEQUENCE) || !CBS_get_asn1_uint64(&pkcs8, &version) || version != 0 || @@ -164,7 +162,8 @@ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return NULL; } - if (!parse_key_type(&algorithm, &type)) { + const EVP_PKEY_ASN1_METHOD *method = parse_key_type(&algorithm); + if (method == NULL) { OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); return NULL; } @@ -173,10 +172,10 @@ // Set up an |EVP_PKEY| of the appropriate type. EVP_PKEY *ret = EVP_PKEY_new(); - if (ret == NULL || - !EVP_PKEY_set_type(ret, type)) { + if (ret == NULL) { goto err; } + evp_pkey_set_method(ret, method); // Call into the type-specific PrivateKeyInfo decoding function. if (ret->ameth->priv_decode == NULL) {
diff --git a/crypto/evp/internal.h b/crypto/evp/internal.h index 6678c41..cf287c8 100644 --- a/crypto/evp/internal.h +++ b/crypto/evp/internal.h
@@ -295,6 +295,10 @@ extern const EVP_PKEY_METHOD x25519_pkey_meth; extern const EVP_PKEY_METHOD hkdf_pkey_meth; +// evp_pkey_set_method behaves like |EVP_PKEY_set_type|, but takes a pointer to +// a method table. This avoids depending on every |EVP_PKEY_ASN1_METHOD|. +void evp_pkey_set_method(EVP_PKEY *pkey, const EVP_PKEY_ASN1_METHOD *method); + #if defined(__cplusplus) } // extern C
diff --git a/crypto/evp/p_ed25519.c b/crypto/evp/p_ed25519.c index 647ea05..66e7197 100644 --- a/crypto/evp/p_ed25519.c +++ b/crypto/evp/p_ed25519.c
@@ -30,10 +30,7 @@ return 0; } - if (!EVP_PKEY_set_type(pkey, EVP_PKEY_ED25519)) { - OPENSSL_free(key); - return 0; - } + evp_pkey_set_method(pkey, &ed25519_asn1_meth); uint8_t pubkey_unused[32]; ED25519_keypair(pubkey_unused, key->key);
diff --git a/crypto/evp/p_x25519.c b/crypto/evp/p_x25519.c index 6218943..a4c9136 100644 --- a/crypto/evp/p_x25519.c +++ b/crypto/evp/p_x25519.c
@@ -30,10 +30,7 @@ return 0; } - if (!EVP_PKEY_set_type(pkey, EVP_PKEY_X25519)) { - OPENSSL_free(key); - return 0; - } + evp_pkey_set_method(pkey, &x25519_asn1_meth); X25519_keypair(key->pub, key->priv); key->has_private = 1;