@@ -388,12 +388,15 @@ int test_wc_PKCS7_EncodeData(void)
388388
389389#if defined(HAVE_PKCS7 ) && defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK ) && \
390390 !defined(NO_RSA ) && !defined(NO_SHA256 )
391- /* RSA sign raw digest callback */
391+ /* RSA sign raw digest callback
392+ * This callback demonstrates HSM/secure element use case where the private
393+ * key is not passed through PKCS7 structure but obtained independently.
394+ */
392395static int rsaSignRawDigestCb (PKCS7 * pkcs7 , byte * digest , word32 digestSz ,
393396 byte * out , word32 outSz , byte * privateKey ,
394397 word32 privateKeySz , int devid , int hashOID )
395398{
396- /* specific DigestInfo ASN.1 encoding prefix for a SHA2565 digest */
399+ /* specific DigestInfo ASN.1 encoding prefix for a SHA256 digest */
397400 byte digInfoEncoding [] = {
398401 0x30 , 0x31 , 0x30 , 0x0d , 0x06 , 0x09 , 0x60 , 0x86 ,
399402 0x48 , 0x01 , 0x65 , 0x03 , 0x04 , 0x02 , 0x01 , 0x05 ,
@@ -407,6 +410,11 @@ static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz,
407410 word32 idx = 0 ;
408411 RsaKey rsa ;
409412
413+ /* privateKey may be NULL in HSM/secure element use case - we load it
414+ * independently in this callback to simulate that scenario */
415+ (void )privateKey ;
416+ (void )privateKeySz ;
417+
410418 /* SHA-256 required only for this example callback due to above
411419 * digInfoEncoding[] */
412420 if (pkcs7 == NULL || digest == NULL || out == NULL ||
@@ -427,7 +435,33 @@ static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz,
427435 return ret ;
428436 }
429437
430- ret = wc_RsaPrivateKeyDecode (privateKey , & idx , & rsa , privateKeySz );
438+ /* Load key from test buffer - simulates HSM/secure element access */
439+ #if defined(USE_CERT_BUFFERS_2048 )
440+ ret = wc_RsaPrivateKeyDecode (client_key_der_2048 , & idx , & rsa ,
441+ sizeof_client_key_der_2048 );
442+ #elif defined(USE_CERT_BUFFERS_1024 )
443+ ret = wc_RsaPrivateKeyDecode (client_key_der_1024 , & idx , & rsa ,
444+ sizeof_client_key_der_1024 );
445+ #else
446+ {
447+ XFILE fp ;
448+ byte keyBuf [ONEK_BUF ];
449+ int keySz ;
450+
451+ fp = XFOPEN ("./certs/client-key.der" , "rb" );
452+ if (fp == XBADFILE ) {
453+ wc_FreeRsaKey (& rsa );
454+ return -1 ;
455+ }
456+ keySz = (int )XFREAD (keyBuf , 1 , sizeof (keyBuf ), fp );
457+ XFCLOSE (fp );
458+ if (keySz <= 0 ) {
459+ wc_FreeRsaKey (& rsa );
460+ return -1 ;
461+ }
462+ ret = wc_RsaPrivateKeyDecode (keyBuf , & idx , & rsa , (word32 )keySz );
463+ }
464+ #endif
431465
432466 /* sign DigestInfo */
433467 if (ret == 0 ) {
@@ -451,6 +485,102 @@ static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz,
451485}
452486#endif
453487
488+ #if defined(HAVE_PKCS7 ) && defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK ) && \
489+ defined(HAVE_ECC ) && !defined(NO_SHA256 )
490+ /* ECC sign raw digest callback
491+ * This callback demonstrates HSM/secure element use case where the private
492+ * key is not passed through PKCS7 structure but obtained independently.
493+ * Note: This example callback is hash-agnostic and will work with any
494+ * hash algorithm. The hashOID parameter can be used to validate or select
495+ * different signing behavior if needed.
496+ */
497+ static int eccSignRawDigestCb (PKCS7 * pkcs7 , byte * digest , word32 digestSz ,
498+ byte * out , word32 outSz , byte * privateKey ,
499+ word32 privateKeySz , int devid , int hashOID )
500+ {
501+ int ret ;
502+ word32 idx = 0 ;
503+ word32 sigSz = outSz ;
504+ #ifdef WOLFSSL_SMALL_STACK
505+ ecc_key * ecc = NULL ;
506+ #else
507+ ecc_key ecc [1 ];
508+ #endif
509+
510+ /* privateKey may be NULL in HSM/secure element use case - we load it
511+ * independently in this callback to simulate that scenario */
512+ (void )privateKey ;
513+ (void )privateKeySz ;
514+ (void )hashOID ;
515+
516+ if (pkcs7 == NULL || digest == NULL || out == NULL ) {
517+ return -1 ;
518+ }
519+
520+ #ifdef WOLFSSL_SMALL_STACK
521+ ecc = (ecc_key * )XMALLOC (sizeof (ecc_key ), pkcs7 -> heap , DYNAMIC_TYPE_ECC );
522+ if (ecc == NULL ) {
523+ return MEMORY_E ;
524+ }
525+ #endif
526+
527+ /* set up ECC key */
528+ ret = wc_ecc_init_ex (ecc , pkcs7 -> heap , devid );
529+ if (ret != 0 ) {
530+ #ifdef WOLFSSL_SMALL_STACK
531+ XFREE (ecc , pkcs7 -> heap , DYNAMIC_TYPE_ECC );
532+ #endif
533+ return ret ;
534+ }
535+
536+ /* Load key from test buffer - simulates HSM/secure element access */
537+ #if defined(USE_CERT_BUFFERS_256 )
538+ ret = wc_EccPrivateKeyDecode (ecc_clikey_der_256 , & idx , ecc ,
539+ sizeof_ecc_clikey_der_256 );
540+ #else
541+ {
542+ XFILE fp ;
543+ byte keyBuf [ONEK_BUF ];
544+ int keySz ;
545+
546+ fp = XFOPEN ("./certs/client-ecc-key.der" , "rb" );
547+ if (fp == XBADFILE ) {
548+ wc_ecc_free (ecc );
549+ #ifdef WOLFSSL_SMALL_STACK
550+ XFREE (ecc , pkcs7 -> heap , DYNAMIC_TYPE_ECC );
551+ #endif
552+ return -1 ;
553+ }
554+ keySz = (int )XFREAD (keyBuf , 1 , sizeof (keyBuf ), fp );
555+ XFCLOSE (fp );
556+ if (keySz <= 0 ) {
557+ wc_ecc_free (ecc );
558+ #ifdef WOLFSSL_SMALL_STACK
559+ XFREE (ecc , pkcs7 -> heap , DYNAMIC_TYPE_ECC );
560+ #endif
561+ return -1 ;
562+ }
563+ ret = wc_EccPrivateKeyDecode (keyBuf , & idx , ecc , (word32 )keySz );
564+ }
565+ #endif
566+
567+ /* sign digest */
568+ if (ret == 0 ) {
569+ ret = wc_ecc_sign_hash (digest , digestSz , out , & sigSz , pkcs7 -> rng , ecc );
570+ if (ret == 0 ) {
571+ ret = (int )sigSz ;
572+ }
573+ }
574+
575+ wc_ecc_free (ecc );
576+ #ifdef WOLFSSL_SMALL_STACK
577+ XFREE (ecc , pkcs7 -> heap , DYNAMIC_TYPE_ECC );
578+ #endif
579+
580+ return ret ;
581+ }
582+ #endif
583+
454584#if defined(HAVE_PKCS7 ) && defined(ASN_BER_TO_DER )
455585typedef struct encodeSignedDataStream {
456586 byte out [FOURK_BUF * 3 ];
@@ -757,8 +887,7 @@ int test_wc_PKCS7_EncodeSignedData(void)
757887 if (pkcs7 != NULL ) {
758888 pkcs7 -> content = data ;
759889 pkcs7 -> contentSz = (word32 )sizeof (data );
760- pkcs7 -> privateKey = key ;
761- pkcs7 -> privateKeySz = (word32 )sizeof (key );
890+ /* privateKey not set - callback simulates HSM/secure element access */
762891 pkcs7 -> encryptOID = RSAk ;
763892 pkcs7 -> hashOID = SHA256h ;
764893 pkcs7 -> rng = & rng ;
@@ -769,6 +898,47 @@ int test_wc_PKCS7_EncodeSignedData(void)
769898 ExpectIntGT (wc_PKCS7_EncodeSignedData (pkcs7 , output , outputSz ), 0 );
770899#endif
771900
901+ #if defined(HAVE_PKCS7 ) && defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK ) && \
902+ defined(HAVE_ECC ) && !defined(NO_SHA256 )
903+ /* test ECC sign raw digest callback, if using ECC and compiled in.
904+ * Example callback assumes SHA-256, so only run test if compiled in. */
905+ {
906+ #if defined(USE_CERT_BUFFERS_256 )
907+ byte eccCert [sizeof (cliecc_cert_der_256 )];
908+ word32 eccCertSz = (word32 )sizeof (eccCert );
909+ XMEMCPY (eccCert , cliecc_cert_der_256 , eccCertSz );
910+ #else
911+ byte eccCert [ONEK_BUF ];
912+ int eccCertSz ;
913+ XFILE eccFp = XBADFILE ;
914+
915+ ExpectTrue ((eccFp = XFOPEN ("./certs/client-ecc-cert.der" , "rb" )) !=
916+ XBADFILE );
917+ ExpectIntGT (eccCertSz = (int )XFREAD (eccCert , 1 , ONEK_BUF , eccFp ), 0 );
918+ if (eccFp != XBADFILE )
919+ XFCLOSE (eccFp );
920+ #endif
921+
922+ wc_PKCS7_Free (pkcs7 );
923+ pkcs7 = NULL ;
924+ ExpectNotNull (pkcs7 = wc_PKCS7_New (HEAP_HINT , testDevId ));
925+ ExpectIntEQ (wc_PKCS7_InitWithCert (pkcs7 , eccCert , (word32 )eccCertSz ), 0 );
926+
927+ if (pkcs7 != NULL ) {
928+ pkcs7 -> content = data ;
929+ pkcs7 -> contentSz = (word32 )sizeof (data );
930+ /* privateKey not set - callback simulates HSM/secure element access */
931+ pkcs7 -> encryptOID = ECDSAk ;
932+ pkcs7 -> hashOID = SHA256h ;
933+ pkcs7 -> rng = & rng ;
934+ }
935+
936+ ExpectIntEQ (wc_PKCS7_SetEccSignRawDigestCb (pkcs7 , eccSignRawDigestCb ), 0 );
937+
938+ ExpectIntGT (wc_PKCS7_EncodeSignedData (pkcs7 , output , outputSz ), 0 );
939+ }
940+ #endif
941+
772942 wc_PKCS7_Free (pkcs7 );
773943 DoExpectIntEQ (wc_FreeRng (& rng ), 0 );
774944
0 commit comments