diff --git a/crypto/evp_extra/internal.h b/crypto/evp_extra/internal.h index d3103f38b32..1623c89c682 100644 --- a/crypto/evp_extra/internal.h +++ b/crypto/evp_extra/internal.h @@ -37,6 +37,8 @@ typedef struct { #endif +extern const size_t asn1_evp_pkey_methods_size; +extern const EVP_PKEY_ASN1_METHOD *const asn1_evp_pkey_methods[]; extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meth; extern const EVP_PKEY_ASN1_METHOD ec_asn1_meth; extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meth; diff --git a/crypto/evp_extra/p_dsa_asn1.c b/crypto/evp_extra/p_dsa_asn1.c index 69530b14f89..9520397e137 100644 --- a/crypto/evp_extra/p_dsa_asn1.c +++ b/crypto/evp_extra/p_dsa_asn1.c @@ -260,6 +260,10 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = { // 1.2.840.10040.4.1 {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01}, 7, + EVP_PKEY_DSA, + "DSA", + "OpenSSL DSA method", + dsa_pub_decode, dsa_pub_encode, dsa_pub_cmp, diff --git a/crypto/evp_extra/p_ec_asn1.c b/crypto/evp_extra/p_ec_asn1.c index 6e5a8cc0d29..31da8fb96de 100644 --- a/crypto/evp_extra/p_ec_asn1.c +++ b/crypto/evp_extra/p_ec_asn1.c @@ -253,6 +253,10 @@ const EVP_PKEY_ASN1_METHOD ec_asn1_meth = { // 1.2.840.10045.2.1 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01}, 7, + EVP_PKEY_EC, + "EC", + "OpenSSL EC algorithm", + eckey_pub_decode, eckey_pub_encode, eckey_pub_cmp, diff --git a/crypto/evp_extra/p_ed25519_asn1.c b/crypto/evp_extra/p_ed25519_asn1.c index 37b6cd00d96..723f72a0218 100644 --- a/crypto/evp_extra/p_ed25519_asn1.c +++ b/crypto/evp_extra/p_ed25519_asn1.c @@ -261,6 +261,9 @@ const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = { EVP_PKEY_ED25519, {0x2b, 0x65, 0x70}, 3, + EVP_PKEY_ED25519, + "ED25519", + "OpenSSL ED25519 algorithm", ed25519_pub_decode, ed25519_pub_encode, ed25519_pub_cmp, diff --git a/crypto/evp_extra/p_hmac_asn1.c b/crypto/evp_extra/p_hmac_asn1.c index bea66838b33..caa5052098f 100644 --- a/crypto/evp_extra/p_hmac_asn1.c +++ b/crypto/evp_extra/p_hmac_asn1.c @@ -121,6 +121,11 @@ const EVP_PKEY_ASN1_METHOD hmac_asn1_meth = { EVP_PKEY_HMAC, {0xff} /* placeholder oid */, 0 /* oid_len */, + + EVP_PKEY_HMAC, + "HMAC", + "AWS-LC HMAC method", + NULL /* pub_decode */, NULL /* pub_encode */, NULL /* pub_cmp */, diff --git a/crypto/evp_extra/p_kem_asn1.c b/crypto/evp_extra/p_kem_asn1.c index b57b7031131..19c1d7f237e 100644 --- a/crypto/evp_extra/p_kem_asn1.c +++ b/crypto/evp_extra/p_kem_asn1.c @@ -119,6 +119,11 @@ const EVP_PKEY_ASN1_METHOD kem_asn1_meth = { // TODO(awslc): this is a placeholder OID. Do we need OID for KEM at all? {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 11, + + EVP_PKEY_KEM, + "KEM", + "AWS-LC KEM method", + NULL, // pub_decode NULL, // pub_encode kem_pub_cmp, diff --git a/crypto/evp_extra/p_methods.c b/crypto/evp_extra/p_methods.c index 63679e84596..2c5d7a840d2 100644 --- a/crypto/evp_extra/p_methods.c +++ b/crypto/evp_extra/p_methods.c @@ -16,7 +16,7 @@ static const EVP_PKEY_METHOD *const non_fips_pkey_evp_methods[] = { &kem_pkey_meth, }; -static const EVP_PKEY_ASN1_METHOD *const asn1_evp_pkey_methods[] = { +const EVP_PKEY_ASN1_METHOD *const asn1_evp_pkey_methods[] = { &rsa_asn1_meth, &rsa_pss_asn1_meth, &ec_asn1_meth, @@ -29,6 +29,7 @@ static const EVP_PKEY_ASN1_METHOD *const asn1_evp_pkey_methods[] = { &kem_asn1_meth, &hmac_asn1_meth }; +const size_t asn1_evp_pkey_methods_size = sizeof(asn1_evp_pkey_methods)/sizeof(asn1_evp_pkey_methods[0]); OPENSSL_STATIC_ASSERT( NON_FIPS_EVP_PKEY_METHODS == OPENSSL_ARRAY_SIZE(non_fips_pkey_evp_methods), diff --git a/crypto/evp_extra/p_rsa_asn1.c b/crypto/evp_extra/p_rsa_asn1.c index d44f71e64c9..7e614fafe58 100644 --- a/crypto/evp_extra/p_rsa_asn1.c +++ b/crypto/evp_extra/p_rsa_asn1.c @@ -224,6 +224,10 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = { // 1.2.840.113549.1.1.1 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01}, 9, + EVP_PKEY_RSA, + "RSA", + "OpenSSL RSA method", + rsa_pub_decode, rsa_pub_encode, rsa_pub_cmp, @@ -252,6 +256,10 @@ const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth = { // 1.2.840.113549.1.1.10 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a}, 9, + EVP_PKEY_RSA_PSS, + "RSA-PSS", + "OpenSSL RSA-PSS method", + rsa_pss_pub_decode, NULL /* pub_encode */, rsa_pub_cmp, diff --git a/crypto/evp_extra/p_x25519_asn1.c b/crypto/evp_extra/p_x25519_asn1.c index 5149f8da4f1..85fcf048651 100644 --- a/crypto/evp_extra/p_x25519_asn1.c +++ b/crypto/evp_extra/p_x25519_asn1.c @@ -252,6 +252,11 @@ const EVP_PKEY_ASN1_METHOD x25519_asn1_meth = { EVP_PKEY_X25519, {0x2b, 0x65, 0x6e}, 3, + + EVP_PKEY_X25519, + "X25519", + "OpenSSL X25519 algorithm", + x25519_pub_decode, x25519_pub_encode, x25519_pub_cmp, diff --git a/crypto/fipsmodule/evp/evp.c b/crypto/fipsmodule/evp/evp.c index 4587f8a36ab..a2255c1a3c1 100644 --- a/crypto/fipsmodule/evp/evp.c +++ b/crypto/fipsmodule/evp/evp.c @@ -847,3 +847,74 @@ size_t EVP_PKEY_get1_tls_encodedpoint(const EVP_PKEY *pkey, uint8_t **out_ptr) { err: return 0; } + +// ASN1 functions + +int EVP_PKEY_asn1_get_count(void) { + + return asn1_evp_pkey_methods_size; +} + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx) { + if(idx < 0 || idx >= (int)asn1_evp_pkey_methods_size) { + return NULL; + } + return asn1_evp_pkey_methods[idx]; +} + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **_pe, int type) { + for(size_t i = 0; i < asn1_evp_pkey_methods_size; i++) { + const EVP_PKEY_ASN1_METHOD* ameth = asn1_evp_pkey_methods[i]; + if(ameth->pkey_base_id == type) { + return ameth; + } + } + return NULL; +} + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe, const char *str, + int len) { + if(len < 0) { + return NULL; + } + // OPENSSL_strnlen returns an i, where str[i] == 0 + const size_t user_len = OPENSSL_strnlen(str, len); + + for (size_t i = 0; i < asn1_evp_pkey_methods_size; i++) { + const EVP_PKEY_ASN1_METHOD *ameth = asn1_evp_pkey_methods[i]; + + const size_t pem_str_len = OPENSSL_strnlen(ameth->pem_str, 16); + + // OPENSSL_strncasecmp(a, b, n) compares up to index n-1 + const size_t cmp_len = 1 + ((user_len < pem_str_len) ? user_len : pem_str_len); + if (0 == OPENSSL_strncasecmp(ameth->pem_str, str, cmp_len)) { + return ameth; + } + } + return NULL; +} + +int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *pkey_base_id, int *ppkey_flags, + const char **pinfo, const char **ppem_str, + const EVP_PKEY_ASN1_METHOD *ameth) { + if (!ameth) { + return 0; + } + if (ppkey_id) { + *ppkey_id = ameth->pkey_id; + } + if (pkey_base_id) { + *pkey_base_id = ameth->pkey_base_id; + } + // This value is not supported. + if (ppkey_flags) { + *ppkey_flags = 0; + } + if (pinfo) { + *pinfo = ameth->info; + } + if (ppem_str) { + *ppem_str = ameth->pem_str; + } + return 1; +} diff --git a/crypto/fipsmodule/evp/internal.h b/crypto/fipsmodule/evp/internal.h index 81915824312..b4c1618121f 100644 --- a/crypto/fipsmodule/evp/internal.h +++ b/crypto/fipsmodule/evp/internal.h @@ -61,6 +61,7 @@ #include #include +#include #if defined(__cplusplus) extern "C" { @@ -77,62 +78,8 @@ extern "C" { // This is an implementation detail of |EVP_PKEY_HMAC|. #define EVP_MD_CTX_HMAC 0x0800 -typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD; typedef struct evp_pkey_method_st EVP_PKEY_METHOD; -struct evp_pkey_asn1_method_st { - int pkey_id; - uint8_t oid[11]; - uint8_t oid_len; - - // pub_decode decodes |params| and |key| as a SubjectPublicKeyInfo - // and writes the result into |out|. It returns one on success and zero on - // error. |params| is the AlgorithmIdentifier after the OBJECT IDENTIFIER - // type field, and |key| is the contents of the subjectPublicKey with the - // leading padding byte checked and removed. Although X.509 uses BIT STRINGs - // to represent SubjectPublicKeyInfo, every key type defined encodes the key - // as a byte string with the same conversion to BIT STRING. - int (*pub_decode)(EVP_PKEY *out, CBS *params, CBS *key); - - // pub_encode encodes |key| as a SubjectPublicKeyInfo and appends the result - // to |out|. It returns one on success and zero on error. - int (*pub_encode)(CBB *out, const EVP_PKEY *key); - - int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b); - - // priv_decode decodes |params| and |key| as a PrivateKeyInfo and writes the - // result into |out|. It returns one on success and zero on error. |params| is - // the AlgorithmIdentifier after the OBJECT IDENTIFIER type field, and |key| - // is the contents of the OCTET STRING privateKey field. - int (*priv_decode)(EVP_PKEY *out, CBS *params, CBS *key, CBS *pubkey); - - // priv_encode encodes |key| as a PrivateKeyInfo and appends the result to - // |out|. It returns one on success and zero on error. - int (*priv_encode)(CBB *out, const EVP_PKEY *key); - - // priv_encode_v2 encodes |key| as a OneAsymmetricKey (RFC 5958) and appends - // the result to |out|. It returns one on success and zero on error. - int (*priv_encode_v2)(CBB *out, const EVP_PKEY *key); - - int (*set_priv_raw)(EVP_PKEY *pkey, const uint8_t *privkey, size_t privkey_len, const uint8_t *pubkey, size_t pubkey_len); - int (*set_pub_raw)(EVP_PKEY *pkey, const uint8_t *in, size_t len); - int (*get_priv_raw)(const EVP_PKEY *pkey, uint8_t *out, size_t *out_len); - int (*get_pub_raw)(const EVP_PKEY *pkey, uint8_t *out, size_t *out_len); - - // pkey_opaque returns 1 if the |pk| is opaque. Opaque keys are backed by - // custom implementations which do not expose key material and parameters. - int (*pkey_opaque)(const EVP_PKEY *pk); - - int (*pkey_size)(const EVP_PKEY *pk); - int (*pkey_bits)(const EVP_PKEY *pk); - - int (*param_missing)(const EVP_PKEY *pk); - int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from); - int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b); - - void (*pkey_free)(EVP_PKEY *pkey); -}; // EVP_PKEY_ASN1_METHOD - struct evp_pkey_st { CRYPTO_refcount_t references; diff --git a/include/openssl/evp.h b/include/openssl/evp.h index eea831786f9..f8fcfc3089c 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -928,6 +928,87 @@ OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_kem_new_raw_key(int nid, // to the secret key in |key|. OPENSSL_EXPORT int EVP_PKEY_kem_check_key(EVP_PKEY *key); +// ASN1 functions + +typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD; + +struct evp_pkey_asn1_method_st { + int pkey_id; + uint8_t oid[11]; + uint8_t oid_len; + + int pkey_base_id; + const char *pem_str; + const char *info; + + // pub_decode decodes |params| and |key| as a SubjectPublicKeyInfo + // and writes the result into |out|. It returns one on success and zero on + // error. |params| is the AlgorithmIdentifier after the OBJECT IDENTIFIER + // type field, and |key| is the contents of the subjectPublicKey with the + // leading padding byte checked and removed. Although X.509 uses BIT STRINGs + // to represent SubjectPublicKeyInfo, every key type defined encodes the key + // as a byte string with the same conversion to BIT STRING. + int (*pub_decode)(EVP_PKEY *out, CBS *params, CBS *key); + + // pub_encode encodes |key| as a SubjectPublicKeyInfo and appends the result + // to |out|. It returns one on success and zero on error. + int (*pub_encode)(CBB *out, const EVP_PKEY *key); + + int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b); + + // priv_decode decodes |params| and |key| as a PrivateKeyInfo and writes the + // result into |out|. It returns one on success and zero on error. |params| is + // the AlgorithmIdentifier after the OBJECT IDENTIFIER type field, and |key| + // is the contents of the OCTET STRING privateKey field. + int (*priv_decode)(EVP_PKEY *out, CBS *params, CBS *key, CBS *pubkey); + + // priv_encode encodes |key| as a PrivateKeyInfo and appends the result to + // |out|. It returns one on success and zero on error. + int (*priv_encode)(CBB *out, const EVP_PKEY *key); + + // priv_encode_v2 encodes |key| as a OneAsymmetricKey (RFC 5958) and appends + // the result to |out|. It returns one on success and zero on error. + int (*priv_encode_v2)(CBB *out, const EVP_PKEY *key); + + int (*set_priv_raw)(EVP_PKEY *pkey, const uint8_t *privkey, size_t privkey_len, const uint8_t *pubkey, size_t pubkey_len); + int (*set_pub_raw)(EVP_PKEY *pkey, const uint8_t *in, size_t len); + int (*get_priv_raw)(const EVP_PKEY *pkey, uint8_t *out, size_t *out_len); + int (*get_pub_raw)(const EVP_PKEY *pkey, uint8_t *out, size_t *out_len); + + // pkey_opaque returns 1 if the |pk| is opaque. Opaque keys are backed by + // custom implementations which do not expose key material and parameters. + int (*pkey_opaque)(const EVP_PKEY *pk); + + int (*pkey_size)(const EVP_PKEY *pk); + int (*pkey_bits)(const EVP_PKEY *pk); + + int (*param_missing)(const EVP_PKEY *pk); + int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from); + int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b); + + void (*pkey_free)(EVP_PKEY *pkey); +}; // EVP_PKEY_ASN1_METHOD + +// EVP_PKEY_asn1_get_count +int EVP_PKEY_asn1_get_count(void); + +// EVP_PKEY_asn1_get0 +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx); + +// EVP_PKEY_asn1_find +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type); + +// EVP_PKEY_asn1_find_str is a function. +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe, + const char *str, int len); + +// EVP_PKEY_asn1_get0_info is function. +int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *pkey_base_id, + int *ppkey_flags, const char **pinfo, + const char **ppem_str, + const EVP_PKEY_ASN1_METHOD *ameth); + + // Deprecated functions. // EVP_PKEY_RSA2 was historically an alternate form for RSA public keys (OID