Skip to content
129 changes: 129 additions & 0 deletions src/pk.c
Original file line number Diff line number Diff line change
Expand Up @@ -5501,6 +5501,60 @@ int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz,

#endif /* OPENSSL_EXTRA && HAVE_ED25519 */

#if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) && \
defined(HAVE_ED25519)
/* Allocate and initialize a new ed25519_key.
*
* @param [in] heap Heap hint for memory allocation.
* @param [in] devId Device identifier for crypto callbacks.
* @return Allocated and initialized ed25519_key on success.
* @return NULL on failure.
*/
ed25519_key* wolfSSL_ED25519_new(void* heap, int devId)
{
ed25519_key* key;

WOLFSSL_ENTER("wolfSSL_ED25519_new");

#ifndef WC_NO_CONSTRUCTORS
key = wc_ed25519_new(heap, devId, NULL);
#else
key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap,
DYNAMIC_TYPE_ED25519);
if (key == NULL) {
WOLFSSL_ERROR_MSG("wolfSSL_ED25519_new malloc failure");
}
else if (wc_ed25519_init_ex(key, heap, devId) != 0) {
WOLFSSL_ERROR_MSG("wolfSSL_ED25519_new init failure");
XFREE(key, heap, DYNAMIC_TYPE_ED25519);
key = NULL;
}
#endif

return key;
Comment thread
julek-wolfssl marked this conversation as resolved.
}

/* Free an ed25519_key allocated with wolfSSL_ED25519_new.
*
* @param [in] key ed25519_key to free. May be NULL.
*/
void wolfSSL_ED25519_free(ed25519_key* key)
{
if (key != NULL) {
WOLFSSL_ENTER("wolfSSL_ED25519_free");
#ifndef WC_NO_CONSTRUCTORS
wc_ed25519_delete(key, NULL);
#else
{
void* heap = key->heap;
wc_ed25519_free(key);
XFREE(key, heap, DYNAMIC_TYPE_ED25519);
}
#endif
}
Comment thread
julek-wolfssl marked this conversation as resolved.
}
#endif /* (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) && HAVE_ED25519 */

/*******************************************************************************
* END OF ED25519 API
******************************************************************************/
Expand Down Expand Up @@ -5954,6 +6008,61 @@ int wolfSSL_ED448_verify(const unsigned char *msg, unsigned int msgSz,
}
#endif /* OPENSSL_EXTRA && HAVE_ED448 */

#if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) && \
defined(HAVE_ED448)
/* Allocate and initialize a new ed448_key.
*
* @param [in] heap Heap hint for memory allocation.
* @param [in] devId Device identifier for crypto callbacks.
* @return Allocated and initialized ed448_key on success.
* @return NULL on failure.
*/
ed448_key* wolfSSL_ED448_new(void* heap, int devId)
{
ed448_key* key;

WOLFSSL_ENTER("wolfSSL_ED448_new");

#if !defined(WC_NO_CONSTRUCTORS) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(7, 0))
key = wc_ed448_new(heap, devId, NULL);
#else
key = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448);
if (key == NULL) {
WOLFSSL_ERROR_MSG("wolfSSL_ED448_new malloc failure");
}
else if (wc_ed448_init_ex(key, heap, devId) != 0) {
WOLFSSL_ERROR_MSG("wolfSSL_ED448_new init failure");
XFREE(key, heap, DYNAMIC_TYPE_ED448);
key = NULL;
}
#endif

return key;
}

/* Free an ed448_key allocated with wolfSSL_ED448_new.
*
* @param [in] key ed448_key to free. May be NULL.
*/
void wolfSSL_ED448_free(ed448_key* key)
{
if (key != NULL) {
WOLFSSL_ENTER("wolfSSL_ED448_free");
#if !defined(WC_NO_CONSTRUCTORS) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(7, 0))
wc_ed448_delete(key, NULL);
#else
{
void* heap = key->heap;
wc_ed448_free(key);
XFREE(key, heap, DYNAMIC_TYPE_ED448);
}
#endif
}
}
#endif /* (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) && HAVE_ED448 */

Comment thread
julek-wolfssl marked this conversation as resolved.
/*******************************************************************************
* END OF ED448 API
******************************************************************************/
Expand Down Expand Up @@ -6262,6 +6371,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;
Expand Down Expand Up @@ -6409,6 +6528,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;
Expand Down
32 changes: 32 additions & 0 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -17765,6 +17773,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;

Expand Down Expand Up @@ -18123,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;

Expand All @@ -18145,6 +18169,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;

Expand Down
12 changes: 12 additions & 0 deletions src/ssl_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
143 changes: 143 additions & 0 deletions tests/api/test_evp_pkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -2357,3 +2357,146 @@ int test_wolfSSL_EVP_PKEY_print_public(void)
return EXPECT_RESULT();
}

int test_wolfSSL_EVP_PKEY_ed25519(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA) && defined(HAVE_ED25519)
WOLFSSL_EVP_PKEY* pkey = NULL;
const unsigned char* p;

/* Known-valid Ed25519 public key matching server_ed25519_key. The bytes
* are the raw 32-byte BIT STRING contents from
* ./certs/ed25519/server-ed25519-key.der so the import succeeds even
* under strict point-validation. */
static const unsigned char rawPub[32] = {
0x23, 0xaa, 0x4d, 0x60, 0x50, 0xe0, 0x13, 0xd3,
0x3a, 0xed, 0xab, 0xf6, 0xa9, 0xcc, 0x4a, 0xfe,
0xd7, 0x4d, 0x2f, 0xd2, 0x5b, 0x1a, 0x10, 0x05,
0xef, 0x5a, 0x41, 0x25, 0xce, 0x1b, 0x53, 0x78
};
Comment thread
lealem47 marked this conversation as resolved.

/* SPKI wrapper around the same known-valid public key (the full
* contents of ./certs/ed25519/server-ed25519-key.der). */
static const unsigned char spkiPub[] = {
0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
0x23, 0xaa, 0x4d, 0x60, 0x50, 0xe0, 0x13, 0xd3,
0x3a, 0xed, 0xab, 0xf6, 0xa9, 0xcc, 0x4a, 0xfe,
0xd7, 0x4d, 0x2f, 0xd2, 0x5b, 0x1a, 0x10, 0x05,
0xef, 0x5a, 0x41, 0x25, 0xce, 0x1b, 0x53, 0x78
};

/* Exercise the WC_EVP_PKEY_ED25519 case in d2i_evp_pkey()
* including the algId match for the PKCS#8 wrapper. */
p = server_ed25519_key;
ExpectNotNull(pkey = wolfSSL_d2i_PrivateKey(EVP_PKEY_ED25519, NULL,
&p, (long)sizeof_server_ed25519_key));
ExpectIntEQ(wolfSSL_EVP_PKEY_id(pkey), EVP_PKEY_ED25519);
wolfSSL_EVP_PKEY_free(pkey);
pkey = NULL;

p = spkiPub;
ExpectNotNull(pkey = wolfSSL_d2i_PUBKEY(NULL, &p, (long)sizeof(spkiPub)));
ExpectIntEQ(wolfSSL_EVP_PKEY_id(pkey), EVP_PKEY_ED25519);
wolfSSL_EVP_PKEY_free(pkey);
pkey = NULL;

/* Exercise 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;

/* Known-valid Ed448 public key: the raw 57-byte BIT STRING contents
* from ./certs/ed448/server-ed448-key.der so the import succeeds even
* under strict point-validation. */
static const unsigned char rawPub[57] = {
0x54, 0x81, 0x39, 0x01, 0xeb, 0x37, 0xd9, 0xa9,
0x07, 0xcd, 0x01, 0xbc, 0x9d, 0x70, 0x16, 0xc2,
0x2c, 0x2b, 0x75, 0x5b, 0x63, 0xdb, 0xee, 0x3a,
0x2d, 0x44, 0x92, 0x46, 0xb4, 0x7b, 0x07, 0x03,
0x4f, 0xa2, 0xae, 0x86, 0x86, 0xdc, 0x8b, 0x4b,
0x2c, 0x7f, 0xe8, 0x6b, 0x14, 0x8d, 0x58, 0xdd,
0x6d, 0xe7, 0x6f, 0x3a, 0x05, 0x95, 0xa8, 0xef,
0x00
};

/* SPKI wrapper around the same known-valid public key (the full
* contents of ./certs/ed448/server-ed448-key.der). */
static const unsigned char spkiPub[] = {
0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x71, 0x03, 0x3a, 0x00,
0x54, 0x81, 0x39, 0x01, 0xeb, 0x37, 0xd9, 0xa9,
0x07, 0xcd, 0x01, 0xbc, 0x9d, 0x70, 0x16, 0xc2,
0x2c, 0x2b, 0x75, 0x5b, 0x63, 0xdb, 0xee, 0x3a,
0x2d, 0x44, 0x92, 0x46, 0xb4, 0x7b, 0x07, 0x03,
0x4f, 0xa2, 0xae, 0x86, 0x86, 0xdc, 0x8b, 0x4b,
0x2c, 0x7f, 0xe8, 0x6b, 0x14, 0x8d, 0x58, 0xdd,
0x6d, 0xe7, 0x6f, 0x3a, 0x05, 0x95, 0xa8, 0xef,
0x00
};

/* SPKI path. */
p = spkiPub;
ExpectNotNull(pkey = wolfSSL_d2i_PUBKEY(NULL, &p, (long)sizeof(spkiPub)));
ExpectIntEQ(wolfSSL_EVP_PKEY_id(pkey), EVP_PKEY_ED448);
wolfSSL_EVP_PKEY_free(pkey);
pkey = NULL;

/* 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
Comment thread
lealem47 marked this conversation as resolved.
return EXPECT_RESULT();
}

Loading
Loading