Skip to content

Commit 8b76230

Browse files
committed
Add EVP_PKEY_new_raw_public_key and EVP_PKEY_new_raw_private_key
1 parent 56b2017 commit 8b76230

4 files changed

Lines changed: 226 additions & 42 deletions

File tree

src/internal.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13894,9 +13894,30 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
1389413894
}
1389513895

1389613896
wolfSSL_EVP_PKEY_free(x509->key.pkey);
13897-
if (!(x509->key.pkey = wolfSSL_d2i_PUBKEY(NULL,
13898-
&dCert->publicKey,
13899-
dCert->pubKeySize))) {
13897+
x509->key.pkey = NULL;
13898+
13899+
switch (dCert->keyOID) {
13900+
#ifdef HAVE_ED25519
13901+
case ED25519k:
13902+
x509->key.pkey = wolfSSL_EVP_PKEY_new_raw_public_key(
13903+
WC_EVP_PKEY_ED25519, NULL, dCert->publicKey,
13904+
dCert->pubKeySize);
13905+
break;
13906+
#endif
13907+
#ifdef HAVE_ED448
13908+
case ED448k:
13909+
x509->key.pkey = wolfSSL_EVP_PKEY_new_raw_public_key(
13910+
WC_EVP_PKEY_ED448, NULL, dCert->publicKey,
13911+
dCert->pubKeySize);
13912+
break;
13913+
#endif
13914+
default:
13915+
x509->key.pkey = wolfSSL_d2i_PUBKEY(NULL,
13916+
&dCert->publicKey, dCert->pubKeySize);
13917+
break;
13918+
}
13919+
13920+
if (x509->key.pkey == NULL) {
1390013921
ret = PUBLIC_KEY_E;
1390113922
WOLFSSL_ERROR_VERBOSE(ret);
1390213923
}

tests/api/test_evp_pkey.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2400,10 +2400,9 @@ int test_wolfSSL_EVP_PKEY_ed25519(void)
24002400
wolfSSL_EVP_PKEY_free(pkey);
24012401
pkey = NULL;
24022402

2403-
/* Exercise d2iTryEd25519Key's raw fallback where the caller passes
2404-
* the raw bytes from the SPKI BIT STRING rather than a wrapped SPKI. */
2405-
p = rawPub;
2406-
ExpectNotNull(pkey = wolfSSL_d2i_PUBKEY(NULL, &p, (long)sizeof(rawPub)));
2403+
/* Exercise EVP_PKEY_new_raw_public_key to parse 32 raw BIT STRING bytes */
2404+
ExpectNotNull(pkey = wolfSSL_EVP_PKEY_new_raw_public_key(
2405+
WC_EVP_PKEY_ED25519, NULL, rawPub, sizeof(rawPub)));
24072406
ExpectIntEQ(wolfSSL_EVP_PKEY_id(pkey), EVP_PKEY_ED25519);
24082407
wolfSSL_EVP_PKEY_free(pkey);
24092408
pkey = NULL;
@@ -2490,9 +2489,9 @@ int test_wolfSSL_EVP_PKEY_ed448(void)
24902489
wolfSSL_EVP_PKEY_free(pkey);
24912490
pkey = NULL;
24922491

2493-
/* Raw 57-byte fallback path. */
2494-
p = rawPub;
2495-
ExpectNotNull(pkey = wolfSSL_d2i_PUBKEY(NULL, &p, (long)sizeof(rawPub)));
2492+
/* Parse raw bytes */
2493+
ExpectNotNull(pkey = wolfSSL_EVP_PKEY_new_raw_public_key(
2494+
WC_EVP_PKEY_ED448, NULL, rawPub, sizeof(rawPub)));
24962495
ExpectIntEQ(wolfSSL_EVP_PKEY_id(pkey), EVP_PKEY_ED448);
24972496
wolfSSL_EVP_PKEY_free(pkey);
24982497
pkey = NULL;

wolfcrypt/src/evp_pk.c

Lines changed: 190 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -262,36 +262,25 @@ static int d2iTryEd25519Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
262262
return 0;
263263
}
264264

265-
/* Try decoding data as an Ed25519 private/public key. Private keys must
266-
* be PKCS#8 PrivateKeyInfo DER (matching OpenSSL d2i_PrivateKey
267-
* semantics). Public keys may be DER-encoded SubjectPublicKeyInfo (the
268-
* normal d2i_PUBKEY input) or raw 32-byte key material (as passed from
269-
* CopyDecodedToX509 where dCert->publicKey is the raw bytes from the
270-
* SPKI BIT STRING); the structured form is tried first, then the raw
271-
* import as fallback. */
265+
/* Decode data as an Ed25519 key in DER form (SubjectPublicKeyInfo for
266+
* public keys, PKCS#8 PrivateKeyInfo for private keys). */
272267
if (priv) {
273268
isEdKey = (wc_Ed25519PrivateKeyDecode(mem, &keyIdx, edKey,
274269
(word32)memSz) == 0);
275270
}
276271
else {
277272
isEdKey = (wc_Ed25519PublicKeyDecode(mem, &keyIdx, edKey,
278273
(word32)memSz) == 0);
279-
if (!isEdKey && memSz == ED25519_PUB_KEY_SIZE) {
280-
keyIdx = (word32)memSz;
281-
isEdKey = (wc_ed25519_import_public(mem, (word32)memSz, edKey)
282-
== 0);
283-
}
284274
}
285275

286276
if (!isEdKey) {
287277
wolfSSL_ED25519_free(edKey);
288278
return WOLFSSL_FATAL_ERROR;
289279
}
290280

291-
/* Create an EVP PKEY object holding the input bytes. These are the
292-
* SPKI / PKCS#8 DER on the structured path, or the raw 32-byte key
293-
* on the raw fallback path. If the caller already populated the EVP
294-
* PKEY with the input bytes (pkey.ptr set), skip the allocate/copy. */
281+
/* Create an EVP PKEY object holding the input DER bytes. If the caller
282+
* already populated the EVP PKEY with the input bytes (pkey.ptr set),
283+
* skip the allocate/copy. */
295284
if (*out == NULL || (*out)->pkey.ptr == NULL) {
296285
ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_ED25519);
297286
}
@@ -338,36 +327,25 @@ static int d2iTryEd448Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
338327
return 0;
339328
}
340329

341-
/* Try decoding data as an Ed448 private/public key. Private keys must
342-
* be PKCS#8 PrivateKeyInfo DER (matching OpenSSL d2i_PrivateKey
343-
* semantics). Public keys may be DER-encoded SubjectPublicKeyInfo (the
344-
* normal d2i_PUBKEY input) or raw 57-byte key material (as passed from
345-
* CopyDecodedToX509 where dCert->publicKey is the raw bytes from the
346-
* SPKI BIT STRING); the structured form is tried first, then the raw
347-
* import as fallback. */
330+
/* Decode data as an Ed448 key in DER form (SubjectPublicKeyInfo for
331+
* public keys, PKCS#8 PrivateKeyInfo for private keys). */
348332
if (priv) {
349333
isEdKey = (wc_Ed448PrivateKeyDecode(mem, &keyIdx, edKey,
350334
(word32)memSz) == 0);
351335
}
352336
else {
353337
isEdKey = (wc_Ed448PublicKeyDecode(mem, &keyIdx, edKey,
354338
(word32)memSz) == 0);
355-
if (!isEdKey && memSz == ED448_PUB_KEY_SIZE) {
356-
keyIdx = (word32)memSz;
357-
isEdKey = (wc_ed448_import_public(mem, (word32)memSz, edKey)
358-
== 0);
359-
}
360339
}
361340

362341
if (!isEdKey) {
363342
wolfSSL_ED448_free(edKey);
364343
return WOLFSSL_FATAL_ERROR;
365344
}
366345

367-
/* Create an EVP PKEY object holding the input bytes. These are the
368-
* SPKI / PKCS#8 DER on the structured path, or the raw 57-byte key
369-
* on the raw fallback path. If the caller already populated the EVP
370-
* PKEY with the input bytes (pkey.ptr set), skip the allocate/copy. */
346+
/* Create an EVP PKEY object holding the input DER bytes. If the caller
347+
* already populated the EVP PKEY with the input bytes (pkey.ptr set),
348+
* skip the allocate/copy. */
371349
if (*out == NULL || (*out)->pkey.ptr == NULL) {
372350
ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_ED448);
373351
}
@@ -383,6 +361,186 @@ static int d2iTryEd448Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
383361
}
384362
#endif /* HAVE_ED448 */
385363

364+
/* Create a new EVP_PKEY from raw Ed25519 or Ed448 key material.
365+
*
366+
* Used for for callers who already have the raw key bytes and shouldn't need
367+
* to rewrap them in an SPKI just to decode.
368+
*
369+
* @param [in] type WC_EVP_PKEY_ED25519 or WC_EVP_PKEY_ED448.
370+
* @param [in] e Engine. Ignored; accepted for OpenSSL API parity.
371+
* @param [in] pub Raw public key bytes.
372+
* @param [in] len Length of pub. Must match the curve's public key size
373+
* (ED25519_PUB_KEY_SIZE or ED448_PUB_KEY_SIZE).
374+
* @return WOLFSSL_EVP_PKEY on success, NULL on failure.
375+
*/
376+
WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_raw_public_key(int type,
377+
WOLFSSL_ENGINE* e, const unsigned char* pub, size_t len)
378+
{
379+
WOLFSSL_EVP_PKEY* pkey;
380+
int ok = 0;
381+
382+
(void)e;
383+
WOLFSSL_ENTER("wolfSSL_EVP_PKEY_new_raw_public_key");
384+
385+
if (pub == NULL || len == 0) {
386+
return NULL;
387+
}
388+
389+
pkey = wolfSSL_EVP_PKEY_new();
390+
if (pkey == NULL) {
391+
return NULL;
392+
}
393+
394+
switch (type) {
395+
#ifdef HAVE_ED25519
396+
case WC_EVP_PKEY_ED25519: {
397+
ed25519_key* edKey;
398+
if (len != ED25519_PUB_KEY_SIZE) {
399+
break;
400+
}
401+
edKey = wolfSSL_ED25519_new(pkey->heap, INVALID_DEVID);
402+
if (edKey == NULL) {
403+
break;
404+
}
405+
if (wc_ed25519_import_public(pub, (word32)len, edKey) != 0) {
406+
wolfSSL_ED25519_free(edKey);
407+
break;
408+
}
409+
pkey->type = WC_EVP_PKEY_ED25519;
410+
pkey->ed25519 = edKey;
411+
pkey->ownEd25519 = 1;
412+
ok = 1;
413+
break;
414+
}
415+
#endif
416+
#ifdef HAVE_ED448
417+
case WC_EVP_PKEY_ED448: {
418+
ed448_key* edKey;
419+
if (len != ED448_PUB_KEY_SIZE) {
420+
break;
421+
}
422+
edKey = wolfSSL_ED448_new(pkey->heap, INVALID_DEVID);
423+
if (edKey == NULL) {
424+
break;
425+
}
426+
if (wc_ed448_import_public(pub, (word32)len, edKey) != 0) {
427+
wolfSSL_ED448_free(edKey);
428+
break;
429+
}
430+
pkey->type = WC_EVP_PKEY_ED448;
431+
pkey->ed448 = edKey;
432+
pkey->ownEd448 = 1;
433+
ok = 1;
434+
break;
435+
}
436+
#endif
437+
default:
438+
break;
439+
}
440+
441+
if (!ok) {
442+
wolfSSL_EVP_PKEY_free(pkey);
443+
return NULL;
444+
}
445+
446+
/* Stash the raw bytes so callers that later serialize the EVP_PKEY see
447+
* consistent state. */
448+
pkey->pkey.ptr = (char*)XMALLOC(len, pkey->heap, DYNAMIC_TYPE_PUBLIC_KEY);
449+
if (pkey->pkey.ptr == NULL) {
450+
wolfSSL_EVP_PKEY_free(pkey);
451+
return NULL;
452+
}
453+
XMEMCPY(pkey->pkey.ptr, pub, len);
454+
pkey->pkey_sz = (int)len;
455+
456+
return pkey;
457+
}
458+
459+
/* Private-key counterpart to wolfSSL_EVP_PKEY_new_raw_public_key. The raw
460+
* input is the 32-byte seed (Ed25519) or 57-byte seed (Ed448).
461+
*/
462+
WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_raw_private_key(int type,
463+
WOLFSSL_ENGINE* e, const unsigned char* priv, size_t len)
464+
{
465+
WOLFSSL_EVP_PKEY* pkey;
466+
int ok = 0;
467+
468+
(void)e;
469+
WOLFSSL_ENTER("wolfSSL_EVP_PKEY_new_raw_private_key");
470+
471+
if (priv == NULL || len == 0) {
472+
return NULL;
473+
}
474+
475+
pkey = wolfSSL_EVP_PKEY_new();
476+
if (pkey == NULL) {
477+
return NULL;
478+
}
479+
480+
switch (type) {
481+
#ifdef HAVE_ED25519
482+
case WC_EVP_PKEY_ED25519: {
483+
ed25519_key* edKey;
484+
if (len != ED25519_KEY_SIZE) {
485+
break;
486+
}
487+
edKey = wolfSSL_ED25519_new(pkey->heap, INVALID_DEVID);
488+
if (edKey == NULL) {
489+
break;
490+
}
491+
if (wc_ed25519_import_private_only(priv, (word32)len, edKey)
492+
!= 0) {
493+
wolfSSL_ED25519_free(edKey);
494+
break;
495+
}
496+
pkey->type = WC_EVP_PKEY_ED25519;
497+
pkey->ed25519 = edKey;
498+
pkey->ownEd25519 = 1;
499+
ok = 1;
500+
break;
501+
}
502+
#endif
503+
#ifdef HAVE_ED448
504+
case WC_EVP_PKEY_ED448: {
505+
ed448_key* edKey;
506+
if (len != ED448_KEY_SIZE) {
507+
break;
508+
}
509+
edKey = wolfSSL_ED448_new(pkey->heap, INVALID_DEVID);
510+
if (edKey == NULL) {
511+
break;
512+
}
513+
if (wc_ed448_import_private_only(priv, (word32)len, edKey) != 0) {
514+
wolfSSL_ED448_free(edKey);
515+
break;
516+
}
517+
pkey->type = WC_EVP_PKEY_ED448;
518+
pkey->ed448 = edKey;
519+
pkey->ownEd448 = 1;
520+
ok = 1;
521+
break;
522+
}
523+
#endif
524+
default:
525+
break;
526+
}
527+
528+
if (!ok) {
529+
wolfSSL_EVP_PKEY_free(pkey);
530+
return NULL;
531+
}
532+
533+
pkey->pkey.ptr = (char*)XMALLOC(len, pkey->heap, DYNAMIC_TYPE_PRIVATE_KEY);
534+
if (pkey->pkey.ptr == NULL) {
535+
wolfSSL_EVP_PKEY_free(pkey);
536+
return NULL;
537+
}
538+
XMEMCPY(pkey->pkey.ptr, priv, len);
539+
pkey->pkey_sz = (int)len;
540+
541+
return pkey;
542+
}
543+
386544
#if !defined(NO_DSA)
387545
/**
388546
* Try to make a DSA EVP PKEY from data.

wolfssl/openssl/evp.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,10 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_encrypt(WOLFSSL_EVP_PKEY_CTX *ctx,
991991
WOLFSSL_API int wolfSSL_EVP_PKEY_encrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx);
992992
WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_EVP_PKEY_new(void);
993993
WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_ex(void* heap);
994+
WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_raw_public_key(int type,
995+
WOLFSSL_ENGINE* e, const unsigned char* pub, size_t len);
996+
WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_raw_private_key(int type,
997+
WOLFSSL_ENGINE* e, const unsigned char* priv, size_t len);
994998
WOLFSSL_API void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key);
995999
WOLFSSL_API int wolfSSL_EVP_PKEY_size(WOLFSSL_EVP_PKEY *pkey);
9961000
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,
14001404
#define EVP_PKEY_encrypt wolfSSL_EVP_PKEY_encrypt
14011405
#define EVP_PKEY_encrypt_init wolfSSL_EVP_PKEY_encrypt_init
14021406
#define EVP_PKEY_new wolfSSL_EVP_PKEY_new
1407+
#define EVP_PKEY_new_raw_public_key wolfSSL_EVP_PKEY_new_raw_public_key
1408+
#define EVP_PKEY_new_raw_private_key wolfSSL_EVP_PKEY_new_raw_private_key
14031409
#define EVP_PKEY_free wolfSSL_EVP_PKEY_free
14041410
#define EVP_PKEY_up_ref wolfSSL_EVP_PKEY_up_ref
14051411
#define EVP_PKEY_size wolfSSL_EVP_PKEY_size

0 commit comments

Comments
 (0)