Skip to content

Commit

Permalink
Add EVP_PKEY_asn1_* functions
Browse files Browse the repository at this point in the history
  • Loading branch information
justsmth committed Aug 7, 2024
1 parent bf1556b commit 443fd8a
Show file tree
Hide file tree
Showing 12 changed files with 191 additions and 55 deletions.
2 changes: 2 additions & 0 deletions crypto/evp_extra/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions crypto/evp_extra/p_dsa_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions crypto/evp_extra/p_ec_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 3 additions & 0 deletions crypto/evp_extra/p_ed25519_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions crypto/evp_extra/p_hmac_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */,
Expand Down
5 changes: 5 additions & 0 deletions crypto/evp_extra/p_kem_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion crypto/evp_extra/p_methods.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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),
Expand Down
8 changes: 8 additions & 0 deletions crypto/evp_extra/p_rsa_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions crypto/evp_extra/p_x25519_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
71 changes: 71 additions & 0 deletions crypto/fipsmodule/evp/evp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
55 changes: 1 addition & 54 deletions crypto/fipsmodule/evp/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@

#include <openssl/rsa.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>

#if defined(__cplusplus)
extern "C" {
Expand All @@ -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;

Expand Down
81 changes: 81 additions & 0 deletions include/openssl/evp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 443fd8a

Please sign in to comment.