mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-08 02:50:47 +02:00
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.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -41,6 +41,12 @@
|
||||
#include <wolfssl/openssl/evp.h>
|
||||
#include <wolfssl/openssl/kdf.h>
|
||||
#include <wolfssl/wolfcrypt/wolfmath.h>
|
||||
#ifdef HAVE_ED25519
|
||||
#include <wolfssl/wolfcrypt/ed25519.h>
|
||||
#endif
|
||||
#ifdef HAVE_ED448
|
||||
#include <wolfssl/wolfcrypt/ed448.h>
|
||||
#endif
|
||||
|
||||
static const struct s_ent {
|
||||
const enum wc_HashType macType;
|
||||
@@ -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);
|
||||
|
||||
+261
-1
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user