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 12, 2024
1 parent 94f021b commit bcbd1f9
Show file tree
Hide file tree
Showing 14 changed files with 216 additions and 3 deletions.
5 changes: 5 additions & 0 deletions crypto/dilithium/p_dilithium3_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,11 @@ const EVP_PKEY_ASN1_METHOD dilithium3_asn1_meth = {
// as we await NIST to release OIDs.
{0x2B, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0B, 0x07, 0x06, 0x05},
11,

EVP_PKEY_DILITHIUM3,
"DILITHIUM3",
"AWS-LC DILITHIUM3 method",

dilithium3_pub_decode,
dilithium3_pub_encode,
dilithium3_pub_cmp,
Expand Down
67 changes: 67 additions & 0 deletions crypto/evp_extra/evp_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -575,3 +575,70 @@ int i2d_EC_PUBKEY(const EC_KEY *ec_key, uint8_t **outp) {
EVP_PKEY_free(pkey);
return ret;
}

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 >= EVP_PKEY_asn1_get_count()) {
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 < (size_t)EVP_PKEY_asn1_get_count(); i++) {
const EVP_PKEY_ASN1_METHOD *ameth = EVP_PKEY_asn1_get0(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 *name, int len) {
if (len < 0) {
return NULL;
}
// OPENSSL_strnlen returns an i, where str[i] == 0
const size_t name_len = OPENSSL_strnlen(name, len);

for (size_t i = 0; i < (size_t)EVP_PKEY_asn1_get_count(); i++) {
const EVP_PKEY_ASN1_METHOD *ameth = EVP_PKEY_asn1_get0(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 + ((name_len < pem_str_len) ? name_len : pem_str_len);
if (0 == OPENSSL_strncasecmp(ameth->pem_str, name, 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;
}
64 changes: 63 additions & 1 deletion crypto/evp_extra/evp_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,13 @@
#include <openssl/ec_key.h>
#include <openssl/evp.h>

#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../fipsmodule/evp/internal.h"

OPENSSL_MSVC_PRAGMA(warning(push))
OPENSSL_MSVC_PRAGMA(warning(disable: 4702))

Expand Down Expand Up @@ -1394,3 +1396,63 @@ TEST(EVPTest, ECTLSEncodedPoint) {
ERR_GET_REASON(ERR_peek_last_error()));
ERR_clear_error();
}

TEST(EVPTest, PKEY_asn1_find) {
int pkey_id, pkey_base_id, pkey_flags;
const char *pinfo, *pem_str;

/* Test case 1: Find RSA algorithm */
const EVP_PKEY_ASN1_METHOD* ameth = EVP_PKEY_asn1_find(NULL, EVP_PKEY_RSA);
ASSERT_TRUE(ameth);
ASSERT_TRUE(EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags, &pinfo, &pem_str, ameth));
ASSERT_EQ(pkey_id, EVP_PKEY_RSA);
ASSERT_EQ(pkey_base_id, EVP_PKEY_RSA);
ASSERT_EQ(0, pkey_flags);
ASSERT_STREQ("RSA", pem_str);
ASSERT_STREQ("OpenSSL RSA method", pinfo);

/* Test case 2: Find EC algorithm */
ameth = EVP_PKEY_asn1_find(NULL, EVP_PKEY_EC);
ASSERT_TRUE(ameth);
ASSERT_TRUE(EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags, &pinfo, &pem_str, ameth));
ASSERT_EQ(pkey_id, EVP_PKEY_EC);
ASSERT_EQ(pkey_base_id, EVP_PKEY_EC);
ASSERT_EQ(0, pkey_flags);
ASSERT_STREQ("EC", pem_str);
ASSERT_STREQ("OpenSSL EC algorithm", pinfo);

/* Test case 3: Find non-existent algorithm */
ameth = EVP_PKEY_asn1_find(NULL, EVP_PKEY_NONE);
ASSERT_FALSE(ameth);
ASSERT_FALSE(EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags, &pinfo, &pem_str, ameth));
}

TEST(EVPTest, PKEY_asn1_find_str) {
int pkey_id, pkey_base_id, pkey_flags;
const char *pinfo, *pem_str;

/* Test case 1: Find RSA algorithm */
const EVP_PKEY_ASN1_METHOD* ameth = EVP_PKEY_asn1_find_str(NULL, "RSA", 3);
ASSERT_TRUE(ameth);
ASSERT_TRUE(EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags, &pinfo, &pem_str, ameth));
ASSERT_EQ(pkey_id, EVP_PKEY_RSA);
ASSERT_EQ(pkey_base_id, EVP_PKEY_RSA);
ASSERT_EQ(0, pkey_flags);
ASSERT_STREQ("RSA", pem_str);
ASSERT_STREQ("OpenSSL RSA method", pinfo);

/* Test case 2: Find EC algorithm */
ameth = EVP_PKEY_asn1_find_str(NULL, "EC", 2);
ASSERT_TRUE(ameth);
ASSERT_TRUE(EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags, &pinfo, &pem_str, ameth));
ASSERT_EQ(pkey_id, EVP_PKEY_EC);
ASSERT_EQ(pkey_base_id, EVP_PKEY_EC);
ASSERT_EQ(0, pkey_flags);
ASSERT_STREQ("EC", pem_str);
ASSERT_STREQ("OpenSSL EC algorithm", pinfo);

/* Test case 3: Find non-existent algorithm */
ameth = EVP_PKEY_asn1_find_str(NULL, "Nonsense", 8);
ASSERT_FALSE(ameth);
ASSERT_FALSE(EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags, &pinfo, &pem_str, ameth));
}
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
6 changes: 5 additions & 1 deletion 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,14 +78,17 @@ 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;

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
Expand Down
38 changes: 38 additions & 0 deletions include/openssl/evp.h
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,44 @@ 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;

// EVP_PKEY_asn1_get_count returns the number of available
// |EVP_PKEY_ASN1_METHOD| structures.
OPENSSL_EXPORT int EVP_PKEY_asn1_get_count(void);

// EVP_PKEY_asn1_get0
// Returns a pointer to an EVP_PKEY_ASN1_METHOD structure. |idx| is the index
// value, which must be a non-negative value smaller than the return value of
// |EVP_PKEY_asn1_get_count|.
OPENSSL_EXPORT const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx);

// EVP_PKEY_asn1_find finds an |EVP_PKEY_ASN1_METHOD| structure for the given
// key |type|, e.g. |EVP_PKEY_EC| or |EVP_PKEY_RSA|. |pe| is ignored.
OPENSSL_EXPORT const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **_pe,
int type);

// EVP_PKEY_asn1_find_str finds an |EVP_PKEY_ASN1_METHOD| structure by name.
// |pe| is ignored.
// |name| is the name of the key type to find, e.g, "RSA" or "EC".
// |len| is the length of the name.
OPENSSL_EXPORT const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(
ENGINE **_pe, const char *name, int len);

// EVP_PKEY_asn1_get0_info retrieves information about an |EVP_PKEY_ASN1_METHOD|
// structure. |ppkey_id| is a pointer to get the key type identifier.
// |pkey_base_id| is a pointer to get the base key type.
// |ppkey_flags| is not supported. Value is set to 0 is pointer is not |NULL|.
// |pinfo| is a pointer to get a text description.
// |ppem_str| is a pointer to get the PEM string name.
// |ameth| is a pointer to the EVP_PKEY_ASN1_METHOD structure.
OPENSSL_EXPORT 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 bcbd1f9

Please sign in to comment.