@@ -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.
0 commit comments