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;