Merge pull request #10135 from lealem47/nid_ED

Add Ed25519/Ed448 support to EVP layer
This commit is contained in:
JacobBarthelmeh
2026-04-30 14:16:05 -06:00
committed by GitHub
14 changed files with 832 additions and 14 deletions
+24 -3
View File
@@ -13957,9 +13957,30 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
}
wolfSSL_EVP_PKEY_free(x509->key.pkey);
if (!(x509->key.pkey = wolfSSL_d2i_PUBKEY(NULL,
&dCert->publicKey,
dCert->pubKeySize))) {
x509->key.pkey = NULL;
switch (dCert->keyOID) {
#ifdef HAVE_ED25519
case ED25519k:
x509->key.pkey = wolfSSL_EVP_PKEY_new_raw_public_key(
WC_EVP_PKEY_ED25519, NULL, dCert->publicKey,
dCert->pubKeySize);
break;
#endif
#ifdef HAVE_ED448
case ED448k:
x509->key.pkey = wolfSSL_EVP_PKEY_new_raw_public_key(
WC_EVP_PKEY_ED448, NULL, dCert->publicKey,
dCert->pubKeySize);
break;
#endif
default:
x509->key.pkey = wolfSSL_d2i_PUBKEY(NULL,
&dCert->publicKey, dCert->pubKeySize);
break;
}
if (x509->key.pkey == NULL) {
ret = PUBLIC_KEY_E;
WOLFSSL_ERROR_VERBOSE(ret);
}
+129
View File
@@ -5511,6 +5511,60 @@ int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz,
#endif /* OPENSSL_EXTRA && HAVE_ED25519 */
#if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) && \
defined(HAVE_ED25519)
/* Allocate and initialize a new ed25519_key.
*
* @param [in] heap Heap hint for memory allocation.
* @param [in] devId Device identifier for crypto callbacks.
* @return Allocated and initialized ed25519_key on success.
* @return NULL on failure.
*/
ed25519_key* wolfSSL_ED25519_new(void* heap, int devId)
{
ed25519_key* key;
WOLFSSL_ENTER("wolfSSL_ED25519_new");
#ifndef WC_NO_CONSTRUCTORS
key = wc_ed25519_new(heap, devId, NULL);
#else
key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap,
DYNAMIC_TYPE_ED25519);
if (key == NULL) {
WOLFSSL_ERROR_MSG("wolfSSL_ED25519_new malloc failure");
}
else if (wc_ed25519_init_ex(key, heap, devId) != 0) {
WOLFSSL_ERROR_MSG("wolfSSL_ED25519_new init failure");
XFREE(key, heap, DYNAMIC_TYPE_ED25519);
key = NULL;
}
#endif
return key;
}
/* Free an ed25519_key allocated with wolfSSL_ED25519_new.
*
* @param [in] key ed25519_key to free. May be NULL.
*/
void wolfSSL_ED25519_free(ed25519_key* key)
{
if (key != NULL) {
WOLFSSL_ENTER("wolfSSL_ED25519_free");
#ifndef WC_NO_CONSTRUCTORS
wc_ed25519_delete(key, NULL);
#else
{
void* heap = key->heap;
wc_ed25519_free(key);
XFREE(key, heap, DYNAMIC_TYPE_ED25519);
}
#endif
}
}
#endif /* (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) && HAVE_ED25519 */
/*******************************************************************************
* END OF ED25519 API
******************************************************************************/
@@ -5964,6 +6018,61 @@ int wolfSSL_ED448_verify(const unsigned char *msg, unsigned int msgSz,
}
#endif /* OPENSSL_EXTRA && HAVE_ED448 */
#if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) && \
defined(HAVE_ED448)
/* Allocate and initialize a new ed448_key.
*
* @param [in] heap Heap hint for memory allocation.
* @param [in] devId Device identifier for crypto callbacks.
* @return Allocated and initialized ed448_key on success.
* @return NULL on failure.
*/
ed448_key* wolfSSL_ED448_new(void* heap, int devId)
{
ed448_key* key;
WOLFSSL_ENTER("wolfSSL_ED448_new");
#if !defined(WC_NO_CONSTRUCTORS) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(7, 0))
key = wc_ed448_new(heap, devId, NULL);
#else
key = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448);
if (key == NULL) {
WOLFSSL_ERROR_MSG("wolfSSL_ED448_new malloc failure");
}
else if (wc_ed448_init_ex(key, heap, devId) != 0) {
WOLFSSL_ERROR_MSG("wolfSSL_ED448_new init failure");
XFREE(key, heap, DYNAMIC_TYPE_ED448);
key = NULL;
}
#endif
return key;
}
/* Free an ed448_key allocated with wolfSSL_ED448_new.
*
* @param [in] key ed448_key to free. May be NULL.
*/
void wolfSSL_ED448_free(ed448_key* key)
{
if (key != NULL) {
WOLFSSL_ENTER("wolfSSL_ED448_free");
#if !defined(WC_NO_CONSTRUCTORS) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(7, 0))
wc_ed448_delete(key, NULL);
#else
{
void* heap = key->heap;
wc_ed448_free(key);
XFREE(key, heap, DYNAMIC_TYPE_ED448);
}
#endif
}
}
#endif /* (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) && HAVE_ED448 */
/*******************************************************************************
* END OF ED448 API
******************************************************************************/
@@ -6272,6 +6381,16 @@ WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio,
case DHk:
type = WC_EVP_PKEY_DH;
break;
#ifdef HAVE_ED25519
case ED25519k:
type = WC_EVP_PKEY_ED25519;
break;
#endif
#ifdef HAVE_ED448
case ED448k:
type = WC_EVP_PKEY_ED448;
break;
#endif
default:
type = WOLFSSL_FATAL_ERROR;
break;
@@ -6419,6 +6538,16 @@ WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_PrivateKey(XFILE fp, WOLFSSL_EVP_PKEY **key,
case DHk:
type = WC_EVP_PKEY_DH;
break;
#ifdef HAVE_ED25519
case ED25519k:
type = WC_EVP_PKEY_ED25519;
break;
#endif
#ifdef HAVE_ED448
case ED448k:
type = WC_EVP_PKEY_ED448;
break;
#endif
default:
type = WOLFSSL_FATAL_ERROR;
break;
+32
View File
@@ -17724,6 +17724,14 @@ word32 nid2oid(int nid, int grp)
return CTC_SHA3_512wECDSA;
#endif
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
case WC_NID_ED25519:
return CTC_ED25519;
#endif /* HAVE_ED25519 */
#ifdef HAVE_ED448
case WC_NID_ED448:
return CTC_ED448;
#endif /* HAVE_ED448 */
}
break;
@@ -17742,6 +17750,14 @@ word32 nid2oid(int nid, int grp)
case WC_NID_X9_62_id_ecPublicKey:
return ECDSAk;
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
case WC_NID_ED25519:
return ED25519k;
#endif /* HAVE_ED25519 */
#ifdef HAVE_ED448
case WC_NID_ED448:
return ED448k;
#endif /* HAVE_ED448 */
}
break;
@@ -18100,6 +18116,14 @@ int oid2nid(word32 oid, int grp)
return WC_NID_ecdsa_with_SHA3_512;
#endif
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
case CTC_ED25519:
return WC_NID_ED25519;
#endif /* HAVE_ED25519 */
#ifdef HAVE_ED448
case CTC_ED448:
return WC_NID_ED448;
#endif /* HAVE_ED448 */
}
break;
@@ -18122,6 +18146,14 @@ int oid2nid(word32 oid, int grp)
case ECDSAk:
return WC_NID_X9_62_id_ecPublicKey;
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
case ED25519k:
return WC_NID_ED25519;
#endif /* HAVE_ED25519 */
#ifdef HAVE_ED448
case ED448k:
return WC_NID_ED448;
#endif /* HAVE_ED448 */
}
break;
+12
View File
@@ -5306,6 +5306,18 @@ int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey)
WOLFSSL_MSG("populating ECC key");
ret = ECC_populate_EVP_PKEY(pkey, pkey->ecc);
break;
#endif
#ifdef HAVE_ED25519
case WC_EVP_PKEY_ED25519:
/* DER is already stored in pkey->pkey.ptr by d2i_evp_pkey. */
WOLFSSL_MSG("populating Ed25519 key");
break;
#endif
#ifdef HAVE_ED448
case WC_EVP_PKEY_ED448:
/* DER is already stored in pkey->pkey.ptr by d2i_evp_pkey. */
WOLFSSL_MSG("populating Ed448 key");
break;
#endif
default:
ret = 0;
+142
View File
@@ -2429,3 +2429,145 @@ int test_wolfSSL_EVP_PKEY_print_public(void)
return EXPECT_RESULT();
}
int test_wolfSSL_EVP_PKEY_ed25519(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA) && defined(HAVE_ED25519)
WOLFSSL_EVP_PKEY* pkey = NULL;
const unsigned char* p;
/* Known-valid Ed25519 public key matching server_ed25519_key. The bytes
* are the raw 32-byte BIT STRING contents from
* ./certs/ed25519/server-ed25519-key.der so the import succeeds even
* under strict point-validation. */
static const unsigned char rawPub[32] = {
0x23, 0xaa, 0x4d, 0x60, 0x50, 0xe0, 0x13, 0xd3,
0x3a, 0xed, 0xab, 0xf6, 0xa9, 0xcc, 0x4a, 0xfe,
0xd7, 0x4d, 0x2f, 0xd2, 0x5b, 0x1a, 0x10, 0x05,
0xef, 0x5a, 0x41, 0x25, 0xce, 0x1b, 0x53, 0x78
};
/* SPKI wrapper around the same known-valid public key (the full
* contents of ./certs/ed25519/server-ed25519-key.der). */
static const unsigned char spkiPub[] = {
0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
0x23, 0xaa, 0x4d, 0x60, 0x50, 0xe0, 0x13, 0xd3,
0x3a, 0xed, 0xab, 0xf6, 0xa9, 0xcc, 0x4a, 0xfe,
0xd7, 0x4d, 0x2f, 0xd2, 0x5b, 0x1a, 0x10, 0x05,
0xef, 0x5a, 0x41, 0x25, 0xce, 0x1b, 0x53, 0x78
};
/* Exercise the WC_EVP_PKEY_ED25519 case in d2i_evp_pkey()
* including the algId match for the PKCS#8 wrapper. */
p = server_ed25519_key;
ExpectNotNull(pkey = wolfSSL_d2i_PrivateKey(EVP_PKEY_ED25519, NULL,
&p, (long)sizeof_server_ed25519_key));
ExpectIntEQ(wolfSSL_EVP_PKEY_id(pkey), EVP_PKEY_ED25519);
wolfSSL_EVP_PKEY_free(pkey);
pkey = NULL;
p = spkiPub;
ExpectNotNull(pkey = wolfSSL_d2i_PUBKEY(NULL, &p, (long)sizeof(spkiPub)));
ExpectIntEQ(wolfSSL_EVP_PKEY_id(pkey), EVP_PKEY_ED25519);
wolfSSL_EVP_PKEY_free(pkey);
pkey = NULL;
/* Exercise EVP_PKEY_new_raw_public_key to parse 32 raw BIT STRING bytes */
ExpectNotNull(pkey = wolfSSL_EVP_PKEY_new_raw_public_key(
WC_EVP_PKEY_ED25519, NULL, rawPub, sizeof(rawPub)));
ExpectIntEQ(wolfSSL_EVP_PKEY_id(pkey), EVP_PKEY_ED25519);
wolfSSL_EVP_PKEY_free(pkey);
pkey = NULL;
{
static const unsigned char junk[16] = { 0 };
const unsigned char* jp = junk;
ExpectNull(wolfSSL_d2i_PUBKEY(NULL, &jp, (long)sizeof(junk)));
}
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_CTX_use_PrivateKey_ed25519(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA) && defined(HAVE_ED25519) && \
!defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS)
WOLFSSL_CTX* ctx = NULL;
WOLFSSL_EVP_PKEY* pkey = NULL;
const unsigned char* p;
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
/* Load the matching Ed25519 server cert */
ExpectIntEQ(wolfSSL_CTX_use_certificate_buffer(ctx, server_ed25519_cert,
(long)sizeof_server_ed25519_cert, WOLFSSL_FILETYPE_ASN1),
WOLFSSL_SUCCESS);
/* Decode the Ed25519 private key as a WOLFSSL_EVP_PKEY */
p = server_ed25519_key;
ExpectNotNull(pkey = wolfSSL_d2i_PrivateKey(EVP_PKEY_ED25519, NULL,
&p, (long)sizeof_server_ed25519_key));
ExpectIntEQ(wolfSSL_EVP_PKEY_id(pkey), EVP_PKEY_ED25519);
/* Load the pkey and check for success */
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey(ctx, pkey), WOLFSSL_SUCCESS);
wolfSSL_EVP_PKEY_free(pkey);
wolfSSL_CTX_free(ctx);
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_EVP_PKEY_ed448(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA) && defined(HAVE_ED448)
WOLFSSL_EVP_PKEY* pkey = NULL;
const unsigned char* p;
/* Known-valid Ed448 public key: the raw 57-byte BIT STRING contents
* from ./certs/ed448/server-ed448-key.der so the import succeeds even
* under strict point-validation. */
static const unsigned char rawPub[57] = {
0x54, 0x81, 0x39, 0x01, 0xeb, 0x37, 0xd9, 0xa9,
0x07, 0xcd, 0x01, 0xbc, 0x9d, 0x70, 0x16, 0xc2,
0x2c, 0x2b, 0x75, 0x5b, 0x63, 0xdb, 0xee, 0x3a,
0x2d, 0x44, 0x92, 0x46, 0xb4, 0x7b, 0x07, 0x03,
0x4f, 0xa2, 0xae, 0x86, 0x86, 0xdc, 0x8b, 0x4b,
0x2c, 0x7f, 0xe8, 0x6b, 0x14, 0x8d, 0x58, 0xdd,
0x6d, 0xe7, 0x6f, 0x3a, 0x05, 0x95, 0xa8, 0xef,
0x00
};
/* SPKI wrapper around the same known-valid public key (the full
* contents of ./certs/ed448/server-ed448-key.der). */
static const unsigned char spkiPub[] = {
0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x71, 0x03, 0x3a, 0x00,
0x54, 0x81, 0x39, 0x01, 0xeb, 0x37, 0xd9, 0xa9,
0x07, 0xcd, 0x01, 0xbc, 0x9d, 0x70, 0x16, 0xc2,
0x2c, 0x2b, 0x75, 0x5b, 0x63, 0xdb, 0xee, 0x3a,
0x2d, 0x44, 0x92, 0x46, 0xb4, 0x7b, 0x07, 0x03,
0x4f, 0xa2, 0xae, 0x86, 0x86, 0xdc, 0x8b, 0x4b,
0x2c, 0x7f, 0xe8, 0x6b, 0x14, 0x8d, 0x58, 0xdd,
0x6d, 0xe7, 0x6f, 0x3a, 0x05, 0x95, 0xa8, 0xef,
0x00
};
/* SPKI path. */
p = spkiPub;
ExpectNotNull(pkey = wolfSSL_d2i_PUBKEY(NULL, &p, (long)sizeof(spkiPub)));
ExpectIntEQ(wolfSSL_EVP_PKEY_id(pkey), EVP_PKEY_ED448);
wolfSSL_EVP_PKEY_free(pkey);
pkey = NULL;
/* Parse raw bytes */
ExpectNotNull(pkey = wolfSSL_EVP_PKEY_new_raw_public_key(
WC_EVP_PKEY_ED448, NULL, rawPub, sizeof(rawPub)));
ExpectIntEQ(wolfSSL_EVP_PKEY_id(pkey), EVP_PKEY_ED448);
wolfSSL_EVP_PKEY_free(pkey);
pkey = NULL;
#endif
return EXPECT_RESULT();
}
+7 -1
View File
@@ -61,6 +61,9 @@ int test_wolfSSL_EVP_MD_ecc_signing(void);
int test_wolfSSL_EVP_PKEY_encrypt(void);
int test_wolfSSL_EVP_PKEY_derive(void);
int test_wolfSSL_EVP_PKEY_print_public(void);
int test_wolfSSL_EVP_PKEY_ed25519(void);
int test_wolfSSL_CTX_use_PrivateKey_ed25519(void);
int test_wolfSSL_EVP_PKEY_ed448(void);
#define TEST_EVP_PKEY_DECLS \
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_CTX_new_id), \
@@ -100,6 +103,9 @@ int test_wolfSSL_EVP_PKEY_print_public(void);
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_MD_ecc_signing), \
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_encrypt), \
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_derive), \
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_print_public)
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_print_public), \
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_ed25519), \
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_CTX_use_PrivateKey_ed25519), \
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_ed448)
#endif /* WOLFCRYPT_TEST_EVP_PKEY_H */
+35
View File
@@ -1001,6 +1001,41 @@ void wc_ed448_free(ed448_key* key)
}
}
#ifndef WC_NO_CONSTRUCTORS
ed448_key* wc_ed448_new(void* heap, int devId, int *result_code)
{
int ret;
ed448_key* key = (ed448_key*)XMALLOC(sizeof(ed448_key), heap,
DYNAMIC_TYPE_ED448);
if (key == NULL) {
ret = MEMORY_E;
}
else {
ret = wc_ed448_init_ex(key, heap, devId);
if (ret != 0) {
XFREE(key, heap, DYNAMIC_TYPE_ED448);
key = NULL;
}
}
if (result_code != NULL)
*result_code = ret;
return key;
}
int wc_ed448_delete(ed448_key* key, ed448_key** key_p) {
void* heap;
if (key == NULL)
return BAD_FUNC_ARG;
heap = key->heap;
wc_ed448_free(key);
XFREE(key, heap, DYNAMIC_TYPE_ED448);
if (key_p != NULL)
*key_p = NULL;
return 0;
}
#endif /* !WC_NO_CONSTRUCTORS */
#ifdef HAVE_ED448_KEY_EXPORT
+26
View File
@@ -41,6 +41,12 @@
#include <wolfssl/openssl/evp.h>
#include <wolfssl/openssl/kdf.h>
#include <wolfssl/wolfcrypt/wolfmath.h>
#ifdef HAVE_ED25519
#include <wolfssl/wolfcrypt/ed25519.h>
#endif
#ifdef HAVE_ED448
#include <wolfssl/wolfcrypt/ed448.h>
#endif
static const struct s_ent {
const enum wc_HashType macType;
@@ -11744,6 +11750,26 @@ void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key)
break;
#endif /* ! NO_DH ... */
#ifdef HAVE_ED25519
case WC_EVP_PKEY_ED25519:
if (key->ed25519 != NULL && key->ownEd25519 == 1) {
wc_ed25519_free(key->ed25519);
XFREE(key->ed25519, key->heap, DYNAMIC_TYPE_ED25519);
key->ed25519 = NULL;
}
break;
#endif /* HAVE_ED25519 */
#ifdef HAVE_ED448
case WC_EVP_PKEY_ED448:
if (key->ed448 != NULL && key->ownEd448 == 1) {
wc_ed448_free(key->ed448);
XFREE(key->ed448, key->heap, DYNAMIC_TYPE_ED448);
key->ed448 = NULL;
}
break;
#endif /* HAVE_ED448 */
#ifdef HAVE_HKDF
case WC_EVP_PKEY_HKDF:
XFREE(key->hkdfSalt, NULL, DYNAMIC_TYPE_SALT);
+361 -10
View File
@@ -231,6 +231,316 @@ static int d2iTryEccKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
}
#endif /* HAVE_ECC && OPENSSL_EXTRA */
#ifdef HAVE_ED25519
/**
* Try to make an Ed25519 EVP PKEY from data.
*
* @param [in, out] out On in, an EVP PKEY or NULL.
* On out, an EVP PKEY or NULL.
* @param [in] mem Memory containing key data.
* @param [in] memSz Size of key data in bytes.
* @param [in] priv 1 means private key, 0 means public key.
* @return 1 on success.
* @return 0 on allocation/initialization failure
* @return WOLFSSL_FATAL_ERROR if the input is not an Ed25519 key.
*/
static int d2iTryEd25519Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
long memSz, int priv)
{
ed25519_key* edKey = NULL;
word32 keyIdx = 0;
int isEdKey;
int ret = 1;
void* heap = NULL;
if (*out != NULL) {
heap = (*out)->heap;
}
edKey = wolfSSL_ED25519_new(heap, INVALID_DEVID);
if (edKey == NULL) {
return 0;
}
/* Decode data as an Ed25519 key in DER form (SubjectPublicKeyInfo for
* public keys, PKCS#8 PrivateKeyInfo for private keys). */
if (priv) {
isEdKey = (wc_Ed25519PrivateKeyDecode(mem, &keyIdx, edKey,
(word32)memSz) == 0);
}
else {
isEdKey = (wc_Ed25519PublicKeyDecode(mem, &keyIdx, edKey,
(word32)memSz) == 0);
}
if (!isEdKey) {
wolfSSL_ED25519_free(edKey);
return WOLFSSL_FATAL_ERROR;
}
/* Create an EVP PKEY object holding the input DER bytes. If the caller
* already populated the EVP PKEY with the input bytes (pkey.ptr set),
* skip the allocate/copy. */
if (*out == NULL || (*out)->pkey.ptr == NULL) {
ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_ED25519);
}
if (ret == 1) {
(*out)->ownEd25519 = 1;
(*out)->ed25519 = edKey;
}
else {
wolfSSL_ED25519_free(edKey);
}
return ret;
}
#endif /* HAVE_ED25519 */
#ifdef HAVE_ED448
/**
* Try to make an Ed448 EVP PKEY from data.
*
* @param [in, out] out On in, an EVP PKEY or NULL.
* On out, an EVP PKEY or NULL.
* @param [in] mem Memory containing key data.
* @param [in] memSz Size of key data in bytes.
* @param [in] priv 1 means private key, 0 means public key.
* @return 1 on success.
* @return 0 on allocation/initialization failure.
* @return WOLFSSL_FATAL_ERROR if the input is not an Ed448 key.
*/
static int d2iTryEd448Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
long memSz, int priv)
{
ed448_key* edKey = NULL;
word32 keyIdx = 0;
int isEdKey;
int ret = 1;
void* heap = NULL;
if (*out != NULL) {
heap = (*out)->heap;
}
edKey = wolfSSL_ED448_new(heap, INVALID_DEVID);
if (edKey == NULL) {
return 0;
}
/* Decode data as an Ed448 key in DER form (SubjectPublicKeyInfo for
* public keys, PKCS#8 PrivateKeyInfo for private keys). */
if (priv) {
isEdKey = (wc_Ed448PrivateKeyDecode(mem, &keyIdx, edKey,
(word32)memSz) == 0);
}
else {
isEdKey = (wc_Ed448PublicKeyDecode(mem, &keyIdx, edKey,
(word32)memSz) == 0);
}
if (!isEdKey) {
wolfSSL_ED448_free(edKey);
return WOLFSSL_FATAL_ERROR;
}
/* Create an EVP PKEY object holding the input DER bytes. If the caller
* already populated the EVP PKEY with the input bytes (pkey.ptr set),
* skip the allocate/copy. */
if (*out == NULL || (*out)->pkey.ptr == NULL) {
ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_ED448);
}
if (ret == 1) {
(*out)->ownEd448 = 1;
(*out)->ed448 = edKey;
}
else {
wolfSSL_ED448_free(edKey);
}
return ret;
}
#endif /* HAVE_ED448 */
/* Create a new EVP_PKEY from raw Ed25519 or Ed448 key material.
*
* Used for for callers who already have the raw key bytes and shouldn't need
* to rewrap them in an SPKI just to decode.
*
* @param [in] type WC_EVP_PKEY_ED25519 or WC_EVP_PKEY_ED448.
* @param [in] e Engine. Ignored; accepted for OpenSSL API parity.
* @param [in] pub Raw public key bytes.
* @param [in] len Length of pub. Must match the curve's public key size
* (ED25519_PUB_KEY_SIZE or ED448_PUB_KEY_SIZE).
* @return WOLFSSL_EVP_PKEY on success, NULL on failure.
*/
WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_raw_public_key(int type,
WOLFSSL_ENGINE* e, const unsigned char* pub, size_t len)
{
WOLFSSL_EVP_PKEY* pkey;
int ok = 0;
(void)e;
WOLFSSL_ENTER("wolfSSL_EVP_PKEY_new_raw_public_key");
if (pub == NULL || len == 0) {
return NULL;
}
pkey = wolfSSL_EVP_PKEY_new();
if (pkey == NULL) {
return NULL;
}
switch (type) {
#ifdef HAVE_ED25519
case WC_EVP_PKEY_ED25519: {
ed25519_key* edKey;
if (len != ED25519_PUB_KEY_SIZE) {
break;
}
edKey = wolfSSL_ED25519_new(pkey->heap, INVALID_DEVID);
if (edKey == NULL) {
break;
}
if (wc_ed25519_import_public(pub, (word32)len, edKey) != 0) {
wolfSSL_ED25519_free(edKey);
break;
}
pkey->type = WC_EVP_PKEY_ED25519;
pkey->ed25519 = edKey;
pkey->ownEd25519 = 1;
ok = 1;
break;
}
#endif
#ifdef HAVE_ED448
case WC_EVP_PKEY_ED448: {
ed448_key* edKey;
if (len != ED448_PUB_KEY_SIZE) {
break;
}
edKey = wolfSSL_ED448_new(pkey->heap, INVALID_DEVID);
if (edKey == NULL) {
break;
}
if (wc_ed448_import_public(pub, (word32)len, edKey) != 0) {
wolfSSL_ED448_free(edKey);
break;
}
pkey->type = WC_EVP_PKEY_ED448;
pkey->ed448 = edKey;
pkey->ownEd448 = 1;
ok = 1;
break;
}
#endif
default:
break;
}
if (!ok) {
wolfSSL_EVP_PKEY_free(pkey);
return NULL;
}
/* Stash the raw bytes so callers that later serialize the EVP_PKEY see
* consistent state. */
pkey->pkey.ptr = (char*)XMALLOC(len, pkey->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if (pkey->pkey.ptr == NULL) {
wolfSSL_EVP_PKEY_free(pkey);
return NULL;
}
XMEMCPY(pkey->pkey.ptr, pub, len);
pkey->pkey_sz = (int)len;
return pkey;
}
/* Private-key counterpart to wolfSSL_EVP_PKEY_new_raw_public_key. The raw
* input is the 32-byte seed (Ed25519) or 57-byte seed (Ed448).
*/
WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_raw_private_key(int type,
WOLFSSL_ENGINE* e, const unsigned char* priv, size_t len)
{
WOLFSSL_EVP_PKEY* pkey;
int ok = 0;
(void)e;
WOLFSSL_ENTER("wolfSSL_EVP_PKEY_new_raw_private_key");
if (priv == NULL || len == 0) {
return NULL;
}
pkey = wolfSSL_EVP_PKEY_new();
if (pkey == NULL) {
return NULL;
}
switch (type) {
#ifdef HAVE_ED25519
case WC_EVP_PKEY_ED25519: {
ed25519_key* edKey;
if (len != ED25519_KEY_SIZE) {
break;
}
edKey = wolfSSL_ED25519_new(pkey->heap, INVALID_DEVID);
if (edKey == NULL) {
break;
}
if (wc_ed25519_import_private_only(priv, (word32)len, edKey)
!= 0) {
wolfSSL_ED25519_free(edKey);
break;
}
pkey->type = WC_EVP_PKEY_ED25519;
pkey->ed25519 = edKey;
pkey->ownEd25519 = 1;
ok = 1;
break;
}
#endif
#ifdef HAVE_ED448
case WC_EVP_PKEY_ED448: {
ed448_key* edKey;
if (len != ED448_KEY_SIZE) {
break;
}
edKey = wolfSSL_ED448_new(pkey->heap, INVALID_DEVID);
if (edKey == NULL) {
break;
}
if (wc_ed448_import_private_only(priv, (word32)len, edKey) != 0) {
wolfSSL_ED448_free(edKey);
break;
}
pkey->type = WC_EVP_PKEY_ED448;
pkey->ed448 = edKey;
pkey->ownEd448 = 1;
ok = 1;
break;
}
#endif
default:
break;
}
if (!ok) {
wolfSSL_EVP_PKEY_free(pkey);
return NULL;
}
pkey->pkey.ptr = (char*)XMALLOC(len, pkey->heap, DYNAMIC_TYPE_PRIVATE_KEY);
if (pkey->pkey.ptr == NULL) {
wolfSSL_EVP_PKEY_free(pkey);
return NULL;
}
XMEMCPY(pkey->pkey.ptr, priv, len);
pkey->pkey_sz = (int)len;
return pkey;
}
#if !defined(NO_DSA)
/**
* Try to make a DSA EVP PKEY from data.
@@ -389,7 +699,7 @@ static int d2iTryDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
static int d2iTryAltDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
long memSz, int priv)
{
WOLFSSL_DH* dhObj;
WOLFSSL_DH* dhObj = NULL;
word32 keyIdx = 0;
DhKey* key = NULL;
int elements;
@@ -398,13 +708,15 @@ static int d2iTryAltDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
/* Create DH key object from data. */
dhObj = wolfSSL_DH_new();
if (dhObj == NULL) {
return 0;
ret = 0;
}
key = (DhKey*)dhObj->internal;
/* Try decoding data as a DH public key. */
if (wc_DhKeyDecode(mem, &keyIdx, key, (word32)memSz) != 0) {
ret = 0;
if (ret == 1) {
key = (DhKey*)dhObj->internal;
/* Try decoding data as a DH public key. */
if (wc_DhKeyDecode(mem, &keyIdx, key, (word32)memSz) != 0) {
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
/* DH key has data and is external to DH object. */
@@ -412,7 +724,7 @@ static int d2iTryAltDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
if (priv) {
elements |= ELEMENT_PRV;
}
if (SetDhExternal_ex(dhObj, elements) != WOLFSSL_SUCCESS ) {
if (SetDhExternal_ex(dhObj, elements) != WOLFSSL_SUCCESS) {
ret = 0;
}
}
@@ -421,11 +733,11 @@ static int d2iTryAltDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_DH);
}
if (ret == 1) {
/* Put RSA key object into EVP PKEY object. */
/* Put DH key object into EVP PKEY object. */
(*out)->ownDh = 1;
(*out)->dh = dhObj;
}
if (ret == 0) {
else if (dhObj != NULL) {
wolfSSL_DH_free(dhObj);
}
@@ -694,6 +1006,18 @@ static WOLFSSL_EVP_PKEY* d2i_evp_pkey_try(WOLFSSL_EVP_PKEY** out,
#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
#endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */
#ifdef HAVE_ED25519
if (d2iTryEd25519Key(&pkey, *in, inSz, priv) >= 0) {
;
}
else
#endif /* HAVE_ED25519 */
#ifdef HAVE_ED448
if (d2iTryEd448Key(&pkey, *in, inSz, priv) >= 0) {
;
}
else
#endif /* HAVE_ED448 */
#ifdef HAVE_FALCON
if (d2iTryFalconKey(&pkey, *in, inSz, priv) >= 0) {
;
@@ -925,7 +1249,14 @@ static WOLFSSL_EVP_PKEY* d2i_evp_pkey(int type, WOLFSSL_EVP_PKEY** out,
) ||
(type == WC_EVP_PKEY_EC && algId != ECDSAk) ||
(type == WC_EVP_PKEY_DSA && algId != DSAk) ||
(type == WC_EVP_PKEY_DH && algId != DHk)) {
(type == WC_EVP_PKEY_DH && algId != DHk)
#ifdef HAVE_ED25519
|| (type == WC_EVP_PKEY_ED25519 && algId != ED25519k)
#endif
#ifdef HAVE_ED448
|| (type == WC_EVP_PKEY_ED448 && algId != ED448k)
#endif
) {
WOLFSSL_MSG("PKCS8 does not match EVP key type");
return NULL;
}
@@ -1030,6 +1361,26 @@ static WOLFSSL_EVP_PKEY* d2i_evp_pkey(int type, WOLFSSL_EVP_PKEY** out,
#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
#endif /* HAVE_DH */
#endif /* WOLFSSL_QT || OPENSSL_ALL || WOLFSSL_OPENSSH */
#ifdef HAVE_ED25519
case WC_EVP_PKEY_ED25519:
/* local->pkey.ptr already holds the input bytes, so
* d2iTryEd25519Key will skip the d2i_make_pkey allocate/copy
* and just decode into local->ed25519. */
if (d2iTryEd25519Key(&local, p, local->pkey_sz, priv) != 1) {
wolfSSL_EVP_PKEY_free(local);
return NULL;
}
break;
#endif /* HAVE_ED25519 */
#ifdef HAVE_ED448
case WC_EVP_PKEY_ED448:
/* See WC_EVP_PKEY_ED25519 case above. */
if (d2iTryEd448Key(&local, p, local->pkey_sz, priv) != 1) {
wolfSSL_EVP_PKEY_free(local);
return NULL;
}
break;
#endif /* HAVE_ED448 */
default:
WOLFSSL_MSG("Unsupported key type");
wolfSSL_EVP_PKEY_free(local);
+14
View File
@@ -42,6 +42,20 @@ int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz,
const unsigned char *pub, unsigned int pubSz,
const unsigned char *sig, unsigned int sigSz);
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
#ifndef WC_ED25519KEY_TYPE_DEFINED
typedef struct ed25519_key ed25519_key;
#define WC_ED25519KEY_TYPE_DEFINED
#endif
/* Not OpenSSL API's, but these two constructors are leveraged within
* wolfSSL's compat layer for Ed25519 object creation/deletion simplicity */
WOLFSSL_API
ed25519_key* wolfSSL_ED25519_new(void* heap, int devId);
WOLFSSL_API
void wolfSSL_ED25519_free(ed25519_key* key);
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
+14
View File
@@ -42,6 +42,20 @@ int wolfSSL_ED448_verify(const unsigned char *msg, unsigned int msgSz,
const unsigned char *pub, unsigned int pubSz,
const unsigned char *sig, unsigned int sigSz);
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
#ifndef WC_ED448KEY_TYPE_DEFINED
typedef struct ed448_key ed448_key;
#define WC_ED448KEY_TYPE_DEFINED
#endif
/* Not OpenSSL API's, but these two constructors are leveraged within
* wolfSSL's compat layer for Ed448 object creation/deletion simplicity */
WOLFSSL_API
ed448_key* wolfSSL_ED448_new(void* heap, int devId);
WOLFSSL_API
void wolfSSL_ED448_free(ed448_key* key);
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
+18
View File
@@ -450,6 +450,12 @@ enum {
WC_EVP_PKEY_HKDF = WC_NID_hkdf,
WC_EVP_PKEY_FALCON = 300, /* Randomly picked value. */
WC_EVP_PKEY_DILITHIUM = 301, /* Randomly picked value. */
#ifdef HAVE_ED25519
WC_EVP_PKEY_ED25519 = WC_NID_ED25519,
#endif
#ifdef HAVE_ED448
WC_EVP_PKEY_ED448 = WC_NID_ED448,
#endif
WC_AES_128_CFB1_TYPE = 24,
WC_AES_192_CFB1_TYPE = 25,
WC_AES_256_CFB1_TYPE = 26,
@@ -517,6 +523,12 @@ enum {
#define EVP_PKEY_HKDF WC_EVP_PKEY_HKDF
#define EVP_PKEY_FALCON WC_EVP_PKEY_FALCON
#define EVP_PKEY_DILITHIUM WC_EVP_PKEY_DILITHIUM
#ifdef HAVE_ED25519
#define EVP_PKEY_ED25519 WC_EVP_PKEY_ED25519
#endif
#ifdef HAVE_ED448
#define EVP_PKEY_ED448 WC_EVP_PKEY_ED448
#endif
#define AES_128_CFB1_TYPE WC_AES_128_CFB1_TYPE
#define AES_192_CFB1_TYPE WC_AES_192_CFB1_TYPE
#define AES_256_CFB1_TYPE WC_AES_256_CFB1_TYPE
@@ -979,6 +991,10 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_encrypt(WOLFSSL_EVP_PKEY_CTX *ctx,
WOLFSSL_API int wolfSSL_EVP_PKEY_encrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx);
WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_EVP_PKEY_new(void);
WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_ex(void* heap);
WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_raw_public_key(int type,
WOLFSSL_ENGINE* e, const unsigned char* pub, size_t len);
WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_raw_private_key(int type,
WOLFSSL_ENGINE* e, const unsigned char* priv, size_t len);
WOLFSSL_API void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key);
WOLFSSL_API int wolfSSL_EVP_PKEY_size(WOLFSSL_EVP_PKEY *pkey);
WOLFSSL_API int wolfSSL_EVP_PKEY_copy_parameters(WOLFSSL_EVP_PKEY *to, const WOLFSSL_EVP_PKEY *from);
@@ -1388,6 +1404,8 @@ WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx,
#define EVP_PKEY_encrypt wolfSSL_EVP_PKEY_encrypt
#define EVP_PKEY_encrypt_init wolfSSL_EVP_PKEY_encrypt_init
#define EVP_PKEY_new wolfSSL_EVP_PKEY_new
#define EVP_PKEY_new_raw_public_key wolfSSL_EVP_PKEY_new_raw_public_key
#define EVP_PKEY_new_raw_private_key wolfSSL_EVP_PKEY_new_raw_private_key
#define EVP_PKEY_free wolfSSL_EVP_PKEY_free
#define EVP_PKEY_up_ref wolfSSL_EVP_PKEY_up_ref
#define EVP_PKEY_size wolfSSL_EVP_PKEY_size
+12
View File
@@ -603,6 +603,12 @@ struct WOLFSSL_EVP_PKEY {
#ifndef NO_DH
WOLFSSL_DH* dh;
#endif
#ifdef HAVE_ED25519
struct ed25519_key* ed25519;
#endif
#ifdef HAVE_ED448
struct ed448_key* ed448;
#endif
WC_RNG rng;
#ifdef HAVE_HKDF
const WOLFSSL_EVP_MD* hkdfMd;
@@ -628,6 +634,12 @@ struct WOLFSSL_EVP_PKEY {
WC_BITFIELD ownEcc:1; /* if struct owns ECC and should free it */
WC_BITFIELD ownDsa:1; /* if struct owns DSA and should free it */
WC_BITFIELD ownRsa:1; /* if struct owns RSA and should free it */
#ifdef HAVE_ED25519
WC_BITFIELD ownEd25519:1; /* if struct owns Ed25519 and should free it */
#endif
#ifdef HAVE_ED448
WC_BITFIELD ownEd448:1; /* if struct owns Ed448 and should free it */
#endif
};
+6
View File
@@ -163,6 +163,12 @@ WOLFSSL_API
int wc_ed448_init(ed448_key* key);
WOLFSSL_API
void wc_ed448_free(ed448_key* key);
#ifndef WC_NO_CONSTRUCTORS
WOLFSSL_API
ed448_key* wc_ed448_new(void* heap, int devId, int *result_code);
WOLFSSL_API
int wc_ed448_delete(ed448_key* key, ed448_key** key_p);
#endif
#ifdef HAVE_ED448_KEY_IMPORT
WOLFSSL_API