From 97f1e44721ddc9416678f464e1451e5788c7e681 Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Mon, 6 Apr 2026 10:03:17 -0600 Subject: [PATCH 01/10] 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 02/10] 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 03/10] 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 04/10] 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 05/10] 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; } From 86c56de33fb2d54e2baf1e16e2636b6c9fc636a6 Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Mon, 13 Apr 2026 21:32:54 -0600 Subject: [PATCH 06/10] Address peer review comments --- src/pk.c | 87 +++++++++++++++++ wolfcrypt/src/evp_pk.c | 186 ++++++++++-------------------------- wolfssl/wolfcrypt/ed25519.h | 7 ++ wolfssl/wolfcrypt/ed448.h | 7 ++ 4 files changed, 153 insertions(+), 134 deletions(-) diff --git a/src/pk.c b/src/pk.c index 4544baaf10..292c3a2d81 100644 --- a/src/pk.c +++ b/src/pk.c @@ -5501,6 +5501,50 @@ 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"); + + 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; + } + + 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) { + void* heap = key->heap; + WOLFSSL_ENTER("wolfSSL_ED25519_free"); + wc_ed25519_free(key); + XFREE(key, heap, DYNAMIC_TYPE_ED25519); + } +} +#endif /* (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) && HAVE_ED25519 */ + /******************************************************************************* * END OF ED25519 API ******************************************************************************/ @@ -5954,6 +5998,49 @@ 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"); + + 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; + } + + 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) { + void* heap = key->heap; + WOLFSSL_ENTER("wolfSSL_ED448_free"); + wc_ed448_free(key); + XFREE(key, heap, DYNAMIC_TYPE_ED448); + } +} +#endif /* (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) && HAVE_ED448 */ + /******************************************************************************* * END OF ED448 API ******************************************************************************/ diff --git a/wolfcrypt/src/evp_pk.c b/wolfcrypt/src/evp_pk.c index e0dff16cf8..4a82d4931f 100644 --- a/wolfcrypt/src/evp_pk.c +++ b/wolfcrypt/src/evp_pk.c @@ -257,30 +257,21 @@ static int d2iTryEd25519Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, heap = (*out)->heap; } - edKey = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap, - DYNAMIC_TYPE_ED25519); + edKey = wolfSSL_ED25519_new(heap, INVALID_DEVID); if (edKey == NULL) { return 0; } - if (wc_ed25519_init_ex(edKey, heap, INVALID_DEVID) != 0) { - XFREE(edKey, heap, 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 + /* Try decoding data as an Ed25519 private/public key. Private keys must + * be PKCS#8 PrivateKeyInfo DER (matching OpenSSL d2i_PrivateKey + * semantics). Public keys may be DER-encoded SubjectPublicKeyInfo (the + * normal d2i_PUBKEY input) or raw 32-byte key material (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. */ + * SPKI BIT STRING); the structured form is tried first, then the raw + * import as fallback. */ 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, @@ -293,22 +284,23 @@ static int d2iTryEd25519Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, } if (!isEdKey) { - wc_ed25519_free(edKey); - XFREE(edKey, heap, DYNAMIC_TYPE_ED25519); + wolfSSL_ED25519_free(edKey); return WOLFSSL_FATAL_ERROR; } /* 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); + * on the raw fallback path. 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 { - wc_ed25519_free(edKey); - XFREE(edKey, heap, DYNAMIC_TYPE_ED25519); + wolfSSL_ED25519_free(edKey); } return ret; @@ -341,29 +333,21 @@ static int d2iTryEd448Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, heap = (*out)->heap; } - edKey = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448); + edKey = wolfSSL_ED448_new(heap, INVALID_DEVID); if (edKey == NULL) { return 0; } - if (wc_ed448_init_ex(edKey, heap, INVALID_DEVID) != 0) { - XFREE(edKey, heap, 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 + /* Try decoding data as an Ed448 private/public key. Private keys must + * be PKCS#8 PrivateKeyInfo DER (matching OpenSSL d2i_PrivateKey + * semantics). Public keys may be DER-encoded SubjectPublicKeyInfo (the + * normal d2i_PUBKEY input) or raw 57-byte key material (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. */ + * SPKI BIT STRING); the structured form is tried first, then the raw + * import as fallback. */ 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, @@ -376,22 +360,23 @@ static int d2iTryEd448Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, } if (!isEdKey) { - wc_ed448_free(edKey); - XFREE(edKey, heap, DYNAMIC_TYPE_ED448); + wolfSSL_ED448_free(edKey); return WOLFSSL_FATAL_ERROR; } /* 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); + * on the raw fallback path. 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 { - wc_ed448_free(edKey); - XFREE(edKey, heap, DYNAMIC_TYPE_ED448); + wolfSSL_ED448_free(edKey); } return ret; @@ -556,7 +541,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; @@ -565,22 +550,25 @@ 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) { - wolfSSL_DH_free(dhObj); - return WOLFSSL_FATAL_ERROR; - } - /* 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 (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 (SetDhExternal_ex(dhObj, elements) != WOLFSSL_SUCCESS ) { - ret = 0; + 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; + } } if (ret == 1) { /* Create an EVP PKEY object. */ @@ -591,7 +579,7 @@ static int d2iTryAltDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, (*out)->ownDh = 1; (*out)->dh = dhObj; } - if (ret == 0) { + else if (dhObj != NULL) { wolfSSL_DH_free(dhObj); } @@ -1210,93 +1198,23 @@ static WOLFSSL_EVP_PKEY* d2i_evp_pkey(int type, WOLFSSL_EVP_PKEY** out, #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), local->heap, - DYNAMIC_TYPE_ED25519); - if (edKey == NULL) { - wolfSSL_EVP_PKEY_free(local); - return NULL; - } - 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; - } - 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, local->heap, DYNAMIC_TYPE_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; } - 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), local->heap, - DYNAMIC_TYPE_ED448); - if (edKey == NULL) { - wolfSSL_EVP_PKEY_free(local); - return NULL; - } - if (wc_ed448_init_ex(edKey, local->heap, INVALID_DEVID) != 0) { - XFREE(edKey, local->heap, DYNAMIC_TYPE_ED448); + /* See WC_EVP_PKEY_ED25519 case above. */ + if (d2iTryEd448Key(&local, p, local->pkey_sz, priv) != 1) { 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, local->heap, 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"); diff --git a/wolfssl/wolfcrypt/ed25519.h b/wolfssl/wolfcrypt/ed25519.h index 120c210a92..02858cc227 100644 --- a/wolfssl/wolfcrypt/ed25519.h +++ b/wolfssl/wolfcrypt/ed25519.h @@ -188,6 +188,13 @@ WOLFSSL_API int wc_ed25519_delete(ed25519_key* key, ed25519_key** key_p); #endif +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +WOLFSSL_API +ed25519_key* wolfSSL_ED25519_new(void* heap, int devId); +WOLFSSL_API +void wolfSSL_ED25519_free(ed25519_key* key); +#endif + #ifdef HAVE_ED25519_KEY_IMPORT WOLFSSL_API int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key); diff --git a/wolfssl/wolfcrypt/ed448.h b/wolfssl/wolfcrypt/ed448.h index e255fdacae..a72d8c0daf 100644 --- a/wolfssl/wolfcrypt/ed448.h +++ b/wolfssl/wolfcrypt/ed448.h @@ -164,6 +164,13 @@ int wc_ed448_init(ed448_key* key); WOLFSSL_API void wc_ed448_free(ed448_key* key); +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +WOLFSSL_API +ed448_key* wolfSSL_ED448_new(void* heap, int devId); +WOLFSSL_API +void wolfSSL_ED448_free(ed448_key* key); +#endif + #ifdef HAVE_ED448_KEY_IMPORT WOLFSSL_API int wc_ed448_import_public(const byte* in, word32 inLen, ed448_key* key); From e0be9777f6bcba61786d4fff807177a88d3ce308 Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Thu, 16 Apr 2026 18:39:32 -0600 Subject: [PATCH 07/10] Leverage wc constructors for ED* --- src/pk.c | 34 ++++++++++++++++++++++++++++------ wolfcrypt/src/ed448.c | 35 +++++++++++++++++++++++++++++++++++ wolfssl/wolfcrypt/ed448.h | 6 ++++++ 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/src/pk.c b/src/pk.c index 292c3a2d81..ec80cb6958 100644 --- a/src/pk.c +++ b/src/pk.c @@ -5516,6 +5516,9 @@ ed25519_key* wolfSSL_ED25519_new(void* heap, int devId) 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) { @@ -5526,6 +5529,7 @@ ed25519_key* wolfSSL_ED25519_new(void* heap, int devId) XFREE(key, heap, DYNAMIC_TYPE_ED25519); key = NULL; } +#endif return key; } @@ -5537,10 +5541,16 @@ ed25519_key* wolfSSL_ED25519_new(void* heap, int devId) void wolfSSL_ED25519_free(ed25519_key* key) { if (key != NULL) { - void* heap = key->heap; WOLFSSL_ENTER("wolfSSL_ED25519_free"); - wc_ed25519_free(key); - XFREE(key, heap, DYNAMIC_TYPE_ED25519); + #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 */ @@ -6013,6 +6023,10 @@ ed448_key* wolfSSL_ED448_new(void* heap, int devId) 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"); @@ -6022,6 +6036,7 @@ ed448_key* wolfSSL_ED448_new(void* heap, int devId) XFREE(key, heap, DYNAMIC_TYPE_ED448); key = NULL; } +#endif return key; } @@ -6033,10 +6048,17 @@ ed448_key* wolfSSL_ED448_new(void* heap, int devId) void wolfSSL_ED448_free(ed448_key* key) { if (key != NULL) { - void* heap = key->heap; WOLFSSL_ENTER("wolfSSL_ED448_free"); - wc_ed448_free(key); - XFREE(key, heap, DYNAMIC_TYPE_ED448); + #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 */ diff --git a/wolfcrypt/src/ed448.c b/wolfcrypt/src/ed448.c index 37674cad51..c371eb7df6 100644 --- a/wolfcrypt/src/ed448.c +++ b/wolfcrypt/src/ed448.c @@ -959,6 +959,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 diff --git a/wolfssl/wolfcrypt/ed448.h b/wolfssl/wolfcrypt/ed448.h index a72d8c0daf..44397b70e3 100644 --- a/wolfssl/wolfcrypt/ed448.h +++ b/wolfssl/wolfcrypt/ed448.h @@ -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 #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) WOLFSSL_API From 56b2017405ed67e9f59e3927708a1f6799697b8f Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Thu, 16 Apr 2026 18:42:19 -0600 Subject: [PATCH 08/10] Save heap before *_free in *_delete to avoid XFREE with zeroed memory after ForceZero --- wolfcrypt/src/aes.c | 4 +++- wolfcrypt/src/curve25519.c | 4 +++- wolfcrypt/src/dilithium.c | 4 +++- wolfcrypt/src/ed25519.c | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index cb4258e634..67887bba10 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -13581,10 +13581,12 @@ Aes* wc_AesNew(void* heap, int devId, int *result_code) int wc_AesDelete(Aes *aes, Aes** aes_p) { + void* heap; if (aes == NULL) return BAD_FUNC_ARG; + heap = aes->heap; wc_AesFree(aes); - XFREE(aes, aes->heap, DYNAMIC_TYPE_AES); + XFREE(aes, heap, DYNAMIC_TYPE_AES); if (aes_p != NULL) *aes_p = NULL; return 0; diff --git a/wolfcrypt/src/curve25519.c b/wolfcrypt/src/curve25519.c index bc2961aca4..f8ca74255c 100644 --- a/wolfcrypt/src/curve25519.c +++ b/wolfcrypt/src/curve25519.c @@ -1113,10 +1113,12 @@ curve25519_key* wc_curve25519_new(void* heap, int devId, int *result_code) } int wc_curve25519_delete(curve25519_key* key, curve25519_key** key_p) { + void* heap; if (key == NULL) return BAD_FUNC_ARG; + heap = key->heap; wc_curve25519_free(key); - XFREE(key, key->heap, DYNAMIC_TYPE_CURVE25519); + XFREE(key, heap, DYNAMIC_TYPE_CURVE25519); if (key_p != NULL) *key_p = NULL; return 0; diff --git a/wolfcrypt/src/dilithium.c b/wolfcrypt/src/dilithium.c index fc66b43065..e94460e01d 100644 --- a/wolfcrypt/src/dilithium.c +++ b/wolfcrypt/src/dilithium.c @@ -10730,10 +10730,12 @@ dilithium_key* wc_dilithium_new(void* heap, int devId) int wc_dilithium_delete(dilithium_key* key, dilithium_key** key_p) { + void* heap; if (key == NULL) return BAD_FUNC_ARG; + heap = key->heap; wc_dilithium_free(key); - XFREE(key, key->heap, DYNAMIC_TYPE_DILITHIUM); + XFREE(key, heap, DYNAMIC_TYPE_DILITHIUM); if (key_p != NULL) *key_p = NULL; diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index 425531575b..bf64f45909 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -1035,10 +1035,12 @@ ed25519_key* wc_ed25519_new(void* heap, int devId, int *result_code) } int wc_ed25519_delete(ed25519_key* key, ed25519_key** key_p) { + void* heap; if (key == NULL) return BAD_FUNC_ARG; + heap = key->heap; wc_ed25519_free(key); - XFREE(key, key->heap, DYNAMIC_TYPE_ED25519); + XFREE(key, heap, DYNAMIC_TYPE_ED25519); if (key_p != NULL) *key_p = NULL; return 0; From 8b762301ef22bd78bad30a9d303043d5837b3d56 Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Mon, 20 Apr 2026 09:31:42 -0600 Subject: [PATCH 09/10] Add EVP_PKEY_new_raw_public_key and EVP_PKEY_new_raw_private_key --- src/internal.c | 27 ++++- tests/api/test_evp_pkey.c | 13 ++- wolfcrypt/src/evp_pk.c | 222 ++++++++++++++++++++++++++++++++------ wolfssl/openssl/evp.h | 6 ++ 4 files changed, 226 insertions(+), 42 deletions(-) diff --git a/src/internal.c b/src/internal.c index 067b7a6c08..8662a9bbaf 100644 --- a/src/internal.c +++ b/src/internal.c @@ -13894,9 +13894,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); } diff --git a/tests/api/test_evp_pkey.c b/tests/api/test_evp_pkey.c index eee753125e..ec46779a71 100644 --- a/tests/api/test_evp_pkey.c +++ b/tests/api/test_evp_pkey.c @@ -2400,10 +2400,9 @@ int test_wolfSSL_EVP_PKEY_ed25519(void) 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))); + /* 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; @@ -2490,9 +2489,9 @@ int test_wolfSSL_EVP_PKEY_ed448(void) wolfSSL_EVP_PKEY_free(pkey); pkey = NULL; - /* Raw 57-byte fallback path. */ - p = rawPub; - ExpectNotNull(pkey = wolfSSL_d2i_PUBKEY(NULL, &p, (long)sizeof(rawPub))); + /* 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; diff --git a/wolfcrypt/src/evp_pk.c b/wolfcrypt/src/evp_pk.c index 4a82d4931f..68fecb8fda 100644 --- a/wolfcrypt/src/evp_pk.c +++ b/wolfcrypt/src/evp_pk.c @@ -262,13 +262,8 @@ static int d2iTryEd25519Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, return 0; } - /* Try decoding data as an Ed25519 private/public key. Private keys must - * be PKCS#8 PrivateKeyInfo DER (matching OpenSSL d2i_PrivateKey - * semantics). Public keys may be DER-encoded SubjectPublicKeyInfo (the - * normal d2i_PUBKEY input) or raw 32-byte key material (as passed from - * CopyDecodedToX509 where dCert->publicKey is the raw bytes from the - * SPKI BIT STRING); the structured form is tried first, then the raw - * import as fallback. */ + /* 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); @@ -276,11 +271,6 @@ static int d2iTryEd25519Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, 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) { @@ -288,10 +278,9 @@ static int d2iTryEd25519Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, return WOLFSSL_FATAL_ERROR; } - /* 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. If the caller already populated the EVP - * PKEY with the input bytes (pkey.ptr set), skip the allocate/copy. */ + /* 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); } @@ -338,13 +327,8 @@ static int d2iTryEd448Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, return 0; } - /* Try decoding data as an Ed448 private/public key. Private keys must - * be PKCS#8 PrivateKeyInfo DER (matching OpenSSL d2i_PrivateKey - * semantics). Public keys may be DER-encoded SubjectPublicKeyInfo (the - * normal d2i_PUBKEY input) or raw 57-byte key material (as passed from - * CopyDecodedToX509 where dCert->publicKey is the raw bytes from the - * SPKI BIT STRING); the structured form is tried first, then the raw - * import as fallback. */ + /* 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); @@ -352,11 +336,6 @@ static int d2iTryEd448Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, 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) { @@ -364,10 +343,9 @@ static int d2iTryEd448Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, return WOLFSSL_FATAL_ERROR; } - /* 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. If the caller already populated the EVP - * PKEY with the input bytes (pkey.ptr set), skip the allocate/copy. */ + /* 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); } @@ -383,6 +361,186 @@ static int d2iTryEd448Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, } #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. diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index dc41bd11a4..05cd80f314 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -991,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); @@ -1400,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 From 5da71f4c98dd0f2f9e0399f1d2807c7c08b024eb Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Tue, 28 Apr 2026 08:21:55 -0600 Subject: [PATCH 10/10] Move new wolfSSL_ED* API's to openssl/ed*.h headers --- wolfssl/openssl/ed25519.h | 14 ++++++++++++++ wolfssl/openssl/ed448.h | 14 ++++++++++++++ wolfssl/wolfcrypt/ed25519.h | 7 ------- wolfssl/wolfcrypt/ed448.h | 7 ------- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/wolfssl/openssl/ed25519.h b/wolfssl/openssl/ed25519.h index d38248fbaf..1c95e71eec 100644 --- a/wolfssl/openssl/ed25519.h +++ b/wolfssl/openssl/ed25519.h @@ -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 diff --git a/wolfssl/openssl/ed448.h b/wolfssl/openssl/ed448.h index cc2ece4206..99a57d6a0b 100644 --- a/wolfssl/openssl/ed448.h +++ b/wolfssl/openssl/ed448.h @@ -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 diff --git a/wolfssl/wolfcrypt/ed25519.h b/wolfssl/wolfcrypt/ed25519.h index 02858cc227..120c210a92 100644 --- a/wolfssl/wolfcrypt/ed25519.h +++ b/wolfssl/wolfcrypt/ed25519.h @@ -188,13 +188,6 @@ WOLFSSL_API int wc_ed25519_delete(ed25519_key* key, ed25519_key** key_p); #endif -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) -WOLFSSL_API -ed25519_key* wolfSSL_ED25519_new(void* heap, int devId); -WOLFSSL_API -void wolfSSL_ED25519_free(ed25519_key* key); -#endif - #ifdef HAVE_ED25519_KEY_IMPORT WOLFSSL_API int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key); diff --git a/wolfssl/wolfcrypt/ed448.h b/wolfssl/wolfcrypt/ed448.h index 44397b70e3..0890198874 100644 --- a/wolfssl/wolfcrypt/ed448.h +++ b/wolfssl/wolfcrypt/ed448.h @@ -170,13 +170,6 @@ WOLFSSL_API int wc_ed448_delete(ed448_key* key, ed448_key** key_p); #endif -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) -WOLFSSL_API -ed448_key* wolfSSL_ED448_new(void* heap, int devId); -WOLFSSL_API -void wolfSSL_ED448_free(ed448_key* key); -#endif - #ifdef HAVE_ED448_KEY_IMPORT WOLFSSL_API int wc_ed448_import_public(const byte* in, word32 inLen, ed448_key* key);