From 97f1e44721ddc9416678f464e1451e5788c7e681 Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Mon, 6 Apr 2026 10:03:17 -0600 Subject: [PATCH 1/5] Add Ed25519/Ed448 cases to oid2nid() oidKeyType switch --- src/ssl.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/ssl.c b/src/ssl.c index 58cd6701c0..ede7863b2f 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -17765,6 +17765,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; @@ -18145,6 +18153,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; From 89dac98b95c86599d37709d0934572115ecde46b Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Mon, 6 Apr 2026 12:28:28 -0600 Subject: [PATCH 2/5] fix d2iTryAltDhKey short-circuiting the d2i probe chain When wc_DhKeyDecode() rejected the input, d2iTryAltDhKey() returned 0 after freeing the DH object. d2i_evp_pkey_try() treats any value >= 0 as success, so a non-DH input would stop the probe chain at the DH step and never reach the Falcon, Dilithium, Ed25519, or Ed448 probes that follow. d2i_PUBKEY()/d2i_PrivateKey() consequently returned NULL for any key type past DH in the chain. --- wolfcrypt/src/evp_pk.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/wolfcrypt/src/evp_pk.c b/wolfcrypt/src/evp_pk.c index bf0b3cf6af..51fffc6be8 100644 --- a/wolfcrypt/src/evp_pk.c +++ b/wolfcrypt/src/evp_pk.c @@ -404,24 +404,23 @@ static int d2iTryAltDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, key = (DhKey*)dhObj->internal; /* Try decoding data as a DH public key. */ if (wc_DhKeyDecode(mem, &keyIdx, key, (word32)memSz) != 0) { - ret = 0; + wolfSSL_DH_free(dhObj); + return WOLFSSL_FATAL_ERROR; } - if (ret == 1) { - /* DH key has data and is external to DH object. */ - elements = ELEMENT_P | ELEMENT_G | ELEMENT_Q | ELEMENT_PUB; - if (priv) { - elements |= ELEMENT_PRV; - } - if (SetDhExternal_ex(dhObj, elements) != WOLFSSL_SUCCESS ) { - ret = 0; - } + /* DH key has data and is external to DH object. */ + elements = ELEMENT_P | ELEMENT_G | ELEMENT_Q | ELEMENT_PUB; + if (priv) { + elements |= ELEMENT_PRV; + } + if (SetDhExternal_ex(dhObj, elements) != WOLFSSL_SUCCESS ) { + ret = 0; } if (ret == 1) { /* Create an EVP PKEY object. */ 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; } From d385ae9c296999d7c57fb4ce8a6d62672f847e4d Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Mon, 6 Apr 2026 12:32:25 -0600 Subject: [PATCH 3/5] add Ed25519 and Ed448 support to the EVP_PKEY layer - Add WC_EVP_PKEY_ED25519 / WC_EVP_PKEY_ED448 type constants and matching EVP_PKEY_ED25519 / EVP_PKEY_ED448 OpenSSL aliases. - Extend WOLFSSL_EVP_PKEY with ed25519/ed448 fields and ownership bits, and free them in wolfSSL_EVP_PKEY_free(). - Add d2i probe functions that accept both SubjectPublicKeyInfo / PKCS#8 PrivateKeyInfo encodings and raw 32/57-byte key material, and hook them into the d2i_evp_pkey_try() chain. - Map the Ed25519/Ed448 signature OIDs in the relevant lookups and teach the PEM key-format dispatch and SSL_CTX_use_PrivateKey switch about the new types. --- src/pk.c | 20 ++++ src/ssl.c | 16 +++ src/ssl_load.c | 12 ++ wolfcrypt/src/evp.c | 26 ++++ wolfcrypt/src/evp_pk.c | 262 ++++++++++++++++++++++++++++++++++++++++- wolfssl/openssl/evp.h | 6 + wolfssl/ssl.h | 12 ++ 7 files changed, 353 insertions(+), 1 deletion(-) diff --git a/src/pk.c b/src/pk.c index 1aaf40d065..4544baaf10 100644 --- a/src/pk.c +++ b/src/pk.c @@ -6262,6 +6262,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; @@ -6409,6 +6419,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; diff --git a/src/ssl.c b/src/ssl.c index ede7863b2f..47b13a8513 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -17747,6 +17747,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; @@ -18131,6 +18139,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; diff --git a/src/ssl_load.c b/src/ssl_load.c index 0a0fb9e467..d77ccb31d6 100644 --- a/src/ssl_load.c +++ b/src/ssl_load.c @@ -5256,6 +5256,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; diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index b802958a9e..f8f0a264b2 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -41,6 +41,12 @@ #include #include #include +#ifdef HAVE_ED25519 +#include +#endif +#ifdef HAVE_ED448 +#include +#endif static const struct s_ent { const enum wc_HashType macType; @@ -11679,6 +11685,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); diff --git a/wolfcrypt/src/evp_pk.c b/wolfcrypt/src/evp_pk.c index 51fffc6be8..1a2a14729a 100644 --- a/wolfcrypt/src/evp_pk.c +++ b/wolfcrypt/src/evp_pk.c @@ -231,6 +231,157 @@ 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 otherwise. + */ +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; + + edKey = (ed25519_key*)XMALLOC(sizeof(ed25519_key), NULL, + DYNAMIC_TYPE_ED25519); + if (edKey == NULL) { + return 0; + } + if (wc_ed25519_init(edKey) != 0) { + XFREE(edKey, NULL, DYNAMIC_TYPE_ED25519); + return 0; + } + + /* Try decoding data as an Ed25519 private/public key. The input may be + * either a DER-encoded SubjectPublicKeyInfo / PKCS#8 PrivateKeyInfo + * (the normal d2i_PUBKEY input) or a raw key (as passed from + * CopyDecodedToX509 where dCert->publicKey is the raw bytes from the + * SPKI BIT STRING). Try the structured form first, then fall back to + * the raw import. */ + if (priv) { + isEdKey = (wc_Ed25519PrivateKeyDecode(mem, &keyIdx, edKey, + (word32)memSz) == 0); + if (!isEdKey && memSz == ED25519_KEY_SIZE) { + keyIdx = (word32)memSz; + isEdKey = (wc_ed25519_import_private_only(mem, (word32)memSz, + edKey) == 0); + } + } + else { + isEdKey = (wc_Ed25519PublicKeyDecode(mem, &keyIdx, edKey, + (word32)memSz) == 0); + if (!isEdKey && memSz == ED25519_PUB_KEY_SIZE) { + keyIdx = (word32)memSz; + isEdKey = (wc_ed25519_import_public(mem, (word32)memSz, edKey) + == 0); + } + } + + if (!isEdKey) { + wc_ed25519_free(edKey); + XFREE(edKey, NULL, DYNAMIC_TYPE_ED25519); + return WOLFSSL_FATAL_ERROR; + } + + /* Create an EVP PKEY object holding the DER bytes. */ + ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_ED25519); + if (ret == 1) { + (*out)->ownEd25519 = 1; + (*out)->ed25519 = edKey; + } + else { + wc_ed25519_free(edKey); + XFREE(edKey, NULL, DYNAMIC_TYPE_ED25519); + } + + 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 otherwise. + */ +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; + + edKey = (ed448_key*)XMALLOC(sizeof(ed448_key), NULL, DYNAMIC_TYPE_ED448); + if (edKey == NULL) { + return 0; + } + if (wc_ed448_init(edKey) != 0) { + XFREE(edKey, NULL, DYNAMIC_TYPE_ED448); + return 0; + } + + /* Try decoding data as an Ed448 private/public key. The input may be + * either a DER-encoded SubjectPublicKeyInfo / PKCS#8 PrivateKeyInfo + * (the normal d2i_PUBKEY input) or a raw key (as passed from + * CopyDecodedToX509 where dCert->publicKey is the raw bytes from the + * SPKI BIT STRING). Try the structured form first, then fall back to + * the raw import. */ + if (priv) { + isEdKey = (wc_Ed448PrivateKeyDecode(mem, &keyIdx, edKey, + (word32)memSz) == 0); + if (!isEdKey && memSz == ED448_KEY_SIZE) { + keyIdx = (word32)memSz; + isEdKey = (wc_ed448_import_private_only(mem, (word32)memSz, + edKey) == 0); + } + } + else { + isEdKey = (wc_Ed448PublicKeyDecode(mem, &keyIdx, edKey, + (word32)memSz) == 0); + if (!isEdKey && memSz == ED448_PUB_KEY_SIZE) { + keyIdx = (word32)memSz; + isEdKey = (wc_ed448_import_public(mem, (word32)memSz, edKey) + == 0); + } + } + + if (!isEdKey) { + wc_ed448_free(edKey); + XFREE(edKey, NULL, DYNAMIC_TYPE_ED448); + return WOLFSSL_FATAL_ERROR; + } + + /* Create an EVP PKEY object holding the DER bytes. */ + ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_ED448); + if (ret == 1) { + (*out)->ownEd448 = 1; + (*out)->ed448 = edKey; + } + else { + wc_ed448_free(edKey); + XFREE(edKey, NULL, DYNAMIC_TYPE_ED448); + } + + return ret; +} +#endif /* HAVE_ED448 */ + #if !defined(NO_DSA) /** * Try to make a DSA EVP PKEY from data. @@ -686,6 +837,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) { ; @@ -917,7 +1080,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; } @@ -1022,6 +1192,96 @@ 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: + { + ed25519_key* edKey; + word32 keyIdx = 0; + int isEdKey; + + edKey = (ed25519_key*)XMALLOC(sizeof(ed25519_key), NULL, + DYNAMIC_TYPE_ED25519); + if (edKey == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + if (wc_ed25519_init(edKey) != 0) { + XFREE(edKey, NULL, DYNAMIC_TYPE_ED25519); + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + if (priv) { + isEdKey = (wc_Ed25519PrivateKeyDecode(p, &keyIdx, edKey, + (word32)local->pkey_sz) == 0); + if (!isEdKey && local->pkey_sz == ED25519_KEY_SIZE) { + isEdKey = (wc_ed25519_import_private_only(p, + (word32)local->pkey_sz, edKey) == 0); + } + } + else { + isEdKey = (wc_Ed25519PublicKeyDecode(p, &keyIdx, edKey, + (word32)local->pkey_sz) == 0); + if (!isEdKey && local->pkey_sz == ED25519_PUB_KEY_SIZE) { + isEdKey = (wc_ed25519_import_public(p, + (word32)local->pkey_sz, edKey) == 0); + } + } + if (!isEdKey) { + wc_ed25519_free(edKey); + XFREE(edKey, NULL, DYNAMIC_TYPE_ED25519); + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + local->ownEd25519 = 1; + local->ed25519 = edKey; + break; + } +#endif /* HAVE_ED25519 */ +#ifdef HAVE_ED448 + case WC_EVP_PKEY_ED448: + { + ed448_key* edKey; + word32 keyIdx = 0; + int isEdKey; + + edKey = (ed448_key*)XMALLOC(sizeof(ed448_key), NULL, + DYNAMIC_TYPE_ED448); + if (edKey == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + if (wc_ed448_init(edKey) != 0) { + XFREE(edKey, NULL, DYNAMIC_TYPE_ED448); + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + if (priv) { + isEdKey = (wc_Ed448PrivateKeyDecode(p, &keyIdx, edKey, + (word32)local->pkey_sz) == 0); + if (!isEdKey && local->pkey_sz == ED448_KEY_SIZE) { + isEdKey = (wc_ed448_import_private_only(p, + (word32)local->pkey_sz, edKey) == 0); + } + } + else { + isEdKey = (wc_Ed448PublicKeyDecode(p, &keyIdx, edKey, + (word32)local->pkey_sz) == 0); + if (!isEdKey && local->pkey_sz == ED448_PUB_KEY_SIZE) { + isEdKey = (wc_ed448_import_public(p, + (word32)local->pkey_sz, edKey) == 0); + } + } + if (!isEdKey) { + wc_ed448_free(edKey); + XFREE(edKey, NULL, DYNAMIC_TYPE_ED448); + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + local->ownEd448 = 1; + local->ed448 = edKey; + break; + } +#endif /* HAVE_ED448 */ default: WOLFSSL_MSG("Unsupported key type"); wolfSSL_EVP_PKEY_free(local); diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index f4ee44cd00..b8dfcb340c 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -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, diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index df5e272365..81160a57dc 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -602,6 +602,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; @@ -627,6 +633,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 }; From c01c43448d97be0af6023fc41e9f8f75250342b6 Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Mon, 6 Apr 2026 13:05:16 -0600 Subject: [PATCH 4/5] Add testing for the new ED paths in EVP_PKEY layer --- tests/api/test_evp_pkey.c | 132 ++++++++++++++++++++++++++++++++++++++ tests/api/test_evp_pkey.h | 8 ++- wolfssl/openssl/evp.h | 6 ++ 3 files changed, 145 insertions(+), 1 deletion(-) diff --git a/tests/api/test_evp_pkey.c b/tests/api/test_evp_pkey.c index 931f2b3804..81416c5c10 100644 --- a/tests/api/test_evp_pkey.c +++ b/tests/api/test_evp_pkey.c @@ -2357,3 +2357,135 @@ 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; + + static const unsigned char rawPub[32] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f + }; + + static const unsigned char spkiPub[] = { + 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f + }; + + /* 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 d2iTryEd25519Key's raw fallback where the caller passes + * the raw bytes from the SPKI BIT STRING rather than a wrapped SPKI. */ + p = rawPub; + ExpectNotNull(pkey = wolfSSL_d2i_PUBKEY(NULL, &p, (long)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; + /* 57 arbitrary bytes used as a "raw Ed448 public key". */ + static const unsigned char rawPub[57] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38 + }; + + static const unsigned char spkiPub[] = { + 0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x71, 0x03, 0x3a, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38 + }; + + /* 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; + + /* Raw 57-byte fallback path. */ + p = rawPub; + ExpectNotNull(pkey = wolfSSL_d2i_PUBKEY(NULL, &p, (long)sizeof(rawPub))); + ExpectIntEQ(wolfSSL_EVP_PKEY_id(pkey), EVP_PKEY_ED448); + wolfSSL_EVP_PKEY_free(pkey); + pkey = NULL; +#endif + return EXPECT_RESULT(); +} + diff --git a/tests/api/test_evp_pkey.h b/tests/api/test_evp_pkey.h index e11d5b9c8c..2f60056d3e 100644 --- a/tests/api/test_evp_pkey.h +++ b/tests/api/test_evp_pkey.h @@ -60,6 +60,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), \ @@ -97,6 +100,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 */ diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index b8dfcb340c..dc41bd11a4 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -523,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 From 8e263292ebd34ecaaf8c0d8b816404f3b34beb3c Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Mon, 6 Apr 2026 14:03:24 -0600 Subject: [PATCH 5/5] Address Copilot feedback --- tests/api/test_evp_pkey.c | 61 +++++++++++++++++++++++---------------- wolfcrypt/src/evp_pk.c | 60 ++++++++++++++++++++++++-------------- 2 files changed, 74 insertions(+), 47 deletions(-) diff --git a/tests/api/test_evp_pkey.c b/tests/api/test_evp_pkey.c index 81416c5c10..eee753125e 100644 --- a/tests/api/test_evp_pkey.c +++ b/tests/api/test_evp_pkey.c @@ -2364,19 +2364,25 @@ int test_wolfSSL_EVP_PKEY_ed25519(void) 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] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f + 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, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f + 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() @@ -2448,28 +2454,33 @@ int test_wolfSSL_EVP_PKEY_ed448(void) #if defined(OPENSSL_EXTRA) && defined(HAVE_ED448) WOLFSSL_EVP_PKEY* pkey = NULL; const unsigned char* p; - /* 57 arbitrary bytes used as a "raw Ed448 public key". */ + + /* 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] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38 + 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, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38 + 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. */ diff --git a/wolfcrypt/src/evp_pk.c b/wolfcrypt/src/evp_pk.c index 1a2a14729a..e0dff16cf8 100644 --- a/wolfcrypt/src/evp_pk.c +++ b/wolfcrypt/src/evp_pk.c @@ -241,7 +241,8 @@ static int d2iTryEccKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, * @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 otherwise. + * @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) @@ -250,14 +251,19 @@ static int d2iTryEd25519Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, word32 keyIdx = 0; int isEdKey; int ret = 1; + void* heap = NULL; + + if (*out != NULL) { + heap = (*out)->heap; + } - edKey = (ed25519_key*)XMALLOC(sizeof(ed25519_key), NULL, + edKey = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap, DYNAMIC_TYPE_ED25519); if (edKey == NULL) { return 0; } - if (wc_ed25519_init(edKey) != 0) { - XFREE(edKey, NULL, DYNAMIC_TYPE_ED25519); + if (wc_ed25519_init_ex(edKey, heap, INVALID_DEVID) != 0) { + XFREE(edKey, heap, DYNAMIC_TYPE_ED25519); return 0; } @@ -288,11 +294,13 @@ static int d2iTryEd25519Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, if (!isEdKey) { wc_ed25519_free(edKey); - XFREE(edKey, NULL, DYNAMIC_TYPE_ED25519); + XFREE(edKey, heap, DYNAMIC_TYPE_ED25519); return WOLFSSL_FATAL_ERROR; } - /* Create an EVP PKEY object holding the DER bytes. */ + /* Create an EVP PKEY object holding the input bytes. These are the + * SPKI / PKCS#8 DER on the structured path, or the raw 32-byte key + * on the raw fallback path. */ ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_ED25519); if (ret == 1) { (*out)->ownEd25519 = 1; @@ -300,7 +308,7 @@ static int d2iTryEd25519Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, } else { wc_ed25519_free(edKey); - XFREE(edKey, NULL, DYNAMIC_TYPE_ED25519); + XFREE(edKey, heap, DYNAMIC_TYPE_ED25519); } return ret; @@ -317,7 +325,8 @@ static int d2iTryEd25519Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, * @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 otherwise. + * @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) @@ -326,13 +335,18 @@ static int d2iTryEd448Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, word32 keyIdx = 0; int isEdKey; int ret = 1; + void* heap = NULL; + + if (*out != NULL) { + heap = (*out)->heap; + } - edKey = (ed448_key*)XMALLOC(sizeof(ed448_key), NULL, DYNAMIC_TYPE_ED448); + edKey = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448); if (edKey == NULL) { return 0; } - if (wc_ed448_init(edKey) != 0) { - XFREE(edKey, NULL, DYNAMIC_TYPE_ED448); + if (wc_ed448_init_ex(edKey, heap, INVALID_DEVID) != 0) { + XFREE(edKey, heap, DYNAMIC_TYPE_ED448); return 0; } @@ -363,11 +377,13 @@ static int d2iTryEd448Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, if (!isEdKey) { wc_ed448_free(edKey); - XFREE(edKey, NULL, DYNAMIC_TYPE_ED448); + XFREE(edKey, heap, DYNAMIC_TYPE_ED448); return WOLFSSL_FATAL_ERROR; } - /* Create an EVP PKEY object holding the DER bytes. */ + /* Create an EVP PKEY object holding the input bytes. These are the + * SPKI / PKCS#8 DER on the structured path, or the raw 57-byte key + * on the raw fallback path. */ ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_ED448); if (ret == 1) { (*out)->ownEd448 = 1; @@ -375,7 +391,7 @@ static int d2iTryEd448Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, } else { wc_ed448_free(edKey); - XFREE(edKey, NULL, DYNAMIC_TYPE_ED448); + XFREE(edKey, heap, DYNAMIC_TYPE_ED448); } return ret; @@ -1199,14 +1215,14 @@ static WOLFSSL_EVP_PKEY* d2i_evp_pkey(int type, WOLFSSL_EVP_PKEY** out, word32 keyIdx = 0; int isEdKey; - edKey = (ed25519_key*)XMALLOC(sizeof(ed25519_key), NULL, + edKey = (ed25519_key*)XMALLOC(sizeof(ed25519_key), local->heap, DYNAMIC_TYPE_ED25519); if (edKey == NULL) { wolfSSL_EVP_PKEY_free(local); return NULL; } - if (wc_ed25519_init(edKey) != 0) { - XFREE(edKey, NULL, DYNAMIC_TYPE_ED25519); + if (wc_ed25519_init_ex(edKey, local->heap, INVALID_DEVID) != 0) { + XFREE(edKey, local->heap, DYNAMIC_TYPE_ED25519); wolfSSL_EVP_PKEY_free(local); return NULL; } @@ -1228,7 +1244,7 @@ static WOLFSSL_EVP_PKEY* d2i_evp_pkey(int type, WOLFSSL_EVP_PKEY** out, } if (!isEdKey) { wc_ed25519_free(edKey); - XFREE(edKey, NULL, DYNAMIC_TYPE_ED25519); + XFREE(edKey, local->heap, DYNAMIC_TYPE_ED25519); wolfSSL_EVP_PKEY_free(local); return NULL; } @@ -1244,14 +1260,14 @@ static WOLFSSL_EVP_PKEY* d2i_evp_pkey(int type, WOLFSSL_EVP_PKEY** out, word32 keyIdx = 0; int isEdKey; - edKey = (ed448_key*)XMALLOC(sizeof(ed448_key), NULL, + edKey = (ed448_key*)XMALLOC(sizeof(ed448_key), local->heap, DYNAMIC_TYPE_ED448); if (edKey == NULL) { wolfSSL_EVP_PKEY_free(local); return NULL; } - if (wc_ed448_init(edKey) != 0) { - XFREE(edKey, NULL, DYNAMIC_TYPE_ED448); + if (wc_ed448_init_ex(edKey, local->heap, INVALID_DEVID) != 0) { + XFREE(edKey, local->heap, DYNAMIC_TYPE_ED448); wolfSSL_EVP_PKEY_free(local); return NULL; } @@ -1273,7 +1289,7 @@ static WOLFSSL_EVP_PKEY* d2i_evp_pkey(int type, WOLFSSL_EVP_PKEY** out, } if (!isEdKey) { wc_ed448_free(edKey); - XFREE(edKey, NULL, DYNAMIC_TYPE_ED448); + XFREE(edKey, local->heap, DYNAMIC_TYPE_ED448); wolfSSL_EVP_PKEY_free(local); return NULL; }