Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EVP_PKEY_asn1_* functions #1751

Merged
merged 3 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions crypto/dilithium/p_dilithium3_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ 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,

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

dilithium3_pub_decode,
dilithium3_pub_encode,
dilithium3_pub_cmp,
Expand Down
70 changes: 70 additions & 0 deletions crypto/evp_extra/evp_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -575,3 +575,73 @@ 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_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 longest_pem_str_len = 10; // "DILITHIUM3"

const size_t pem_str_len =
OPENSSL_strnlen(ameth->pem_str, longest_pem_str_len);

// 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_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 @@ -1404,3 +1406,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
3 changes: 3 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,9 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
// 1.2.840.10040.4.1
{0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01}, 7,

"DSA",
"OpenSSL DSA method",

dsa_pub_decode,
dsa_pub_encode,
dsa_pub_cmp,
Expand Down
3 changes: 3 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,9 @@ const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
// 1.2.840.10045.2.1
{0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01}, 7,

"EC",
"OpenSSL EC algorithm",

eckey_pub_decode,
eckey_pub_encode,
eckey_pub_cmp,
Expand Down
2 changes: 2 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,8 @@ const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
EVP_PKEY_ED25519,
{0x2b, 0x65, 0x70},
3,
"ED25519",
"OpenSSL ED25519 algorithm",
ed25519_pub_decode,
ed25519_pub_encode,
ed25519_pub_cmp,
Expand Down
4 changes: 4 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,10 @@ const EVP_PKEY_ASN1_METHOD hmac_asn1_meth = {
EVP_PKEY_HMAC,
{0xff} /* placeholder oid */,
0 /* oid_len */,

"HMAC",
"OpenSSL HMAC method",

NULL /* pub_decode */,
NULL /* pub_encode */,
NULL /* pub_cmp */,
Expand Down
4 changes: 4 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,10 @@ 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,

"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
6 changes: 6 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,9 @@ 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,

"RSA",
"OpenSSL RSA method",

rsa_pub_decode,
rsa_pub_encode,
rsa_pub_cmp,
Expand Down Expand Up @@ -252,6 +255,9 @@ 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,

"RSA-PSS",
"OpenSSL RSA-PSS method",

rsa_pss_pub_decode,
NULL /* pub_encode */,
rsa_pub_cmp,
Expand Down
4 changes: 4 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,10 @@ const EVP_PKEY_ASN1_METHOD x25519_asn1_meth = {
EVP_PKEY_X25519,
{0x2b, 0x65, 0x6e},
3,

"X25519",
"OpenSSL X25519 algorithm",

x25519_pub_decode,
x25519_pub_encode,
x25519_pub_cmp,
Expand Down
5 changes: 4 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,16 @@ 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;

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
1 change: 1 addition & 0 deletions include/openssl/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ typedef struct evp_hpke_key_st EVP_HPKE_KEY;
typedef struct evp_kem_st EVP_KEM;
typedef struct kem_key_st KEM_KEY;
typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD;
typedef struct evp_pkey_st EVP_PKEY;
typedef struct hmac_ctx_st HMAC_CTX;
typedef struct md4_state_st MD4_CTX;
Expand Down
37 changes: 37 additions & 0 deletions include/openssl/evp.h
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,43 @@ 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

// 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. Value will be the same
// as |ppkey_id|.
// |ppkey_flags| is not supported. Value is set to 0 if 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
Loading