From dcf943965a22de687a4f86c4c8e383172fd95d05 Mon Sep 17 00:00:00 2001 From: jackctj117 Date: Tue, 13 Jan 2026 14:22:30 -0700 Subject: [PATCH 1/4] Add PKCS7 ECC raw sign callback support --- tests/api/test_pkcs7.c | 64 +++++++++++++++++++++++++++++++++++++++ wolfcrypt/src/pkcs7.c | 38 +++++++++++++++++++++++ wolfssl/wolfcrypt/pkcs7.h | 17 +++++++++++ 3 files changed, 119 insertions(+) diff --git a/tests/api/test_pkcs7.c b/tests/api/test_pkcs7.c index d60e3abb67f..72d73fddd66 100644 --- a/tests/api/test_pkcs7.c +++ b/tests/api/test_pkcs7.c @@ -451,6 +451,46 @@ static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz, } #endif +#if defined(HAVE_PKCS7) && defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && \ + defined(HAVE_ECC) && !defined(NO_SHA256) +/* ECC sign raw digest callback */ +static int eccSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz, + byte* out, word32 outSz, byte* privateKey, + word32 privateKeySz, int devid, int hashOID) +{ + int ret; + word32 idx = 0; + word32 sigSz = outSz; + ecc_key ecc; + + if (pkcs7 == NULL || digest == NULL || out == NULL) { + return -1; + } + + (void)hashOID; + + /* set up ECC key */ + ret = wc_ecc_init_ex(&ecc, pkcs7->heap, devid); + if (ret != 0) { + return ret; + } + + ret = wc_EccPrivateKeyDecode(privateKey, &idx, &ecc, privateKeySz); + + /* sign digest */ + if (ret == 0) { + ret = wc_ecc_sign_hash(digest, digestSz, out, &sigSz, pkcs7->rng, &ecc); + if (ret == 0) { + ret = (int)sigSz; + } + } + + wc_ecc_free(&ecc); + + return ret; +} +#endif + #if defined(HAVE_PKCS7) && defined(ASN_BER_TO_DER) typedef struct encodeSignedDataStream { byte out[FOURK_BUF*3]; @@ -769,6 +809,30 @@ int test_wc_PKCS7_EncodeSignedData(void) ExpectIntGT(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), 0); #endif +#if defined(HAVE_PKCS7) && defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && \ + defined(HAVE_ECC) && defined(NO_RSA) && !defined(NO_SHA256) + /* test ECC sign raw digest callback, if using ECC and compiled in. + * Example callback assumes SHA-256, so only run test if compiled in. */ + wc_PKCS7_Free(pkcs7); + pkcs7 = NULL; + ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); + ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); + + if (pkcs7 != NULL) { + pkcs7->content = data; + pkcs7->contentSz = (word32)sizeof(data); + pkcs7->privateKey = key; + pkcs7->privateKeySz = (word32)keySz; + pkcs7->encryptOID = ECDSAk; + pkcs7->hashOID = SHA256h; + pkcs7->rng = &rng; + } + + ExpectIntEQ(wc_PKCS7_SetEccSignRawDigestCb(pkcs7, eccSignRawDigestCb), 0); + + ExpectIntGT(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), 0); +#endif + wc_PKCS7_Free(pkcs7); DoExpectIntEQ(wc_FreeRng(&rng), 0); diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 677441e426e..428662a868f 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -2398,6 +2398,20 @@ static int wc_PKCS7_SignedDataBuildSignature(wc_PKCS7* pkcs7, #ifdef HAVE_ECC case ECDSAk: + #ifdef HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK + if (pkcs7->eccSignRawDigestCb != NULL) { + /* get hash OID */ + int eccHashOID = wc_HashGetOID(esd->hashType); + + /* user signing plain digest */ + ret = pkcs7->eccSignRawDigestCb(pkcs7, + esd->contentAttribsDigest, hashSz, + esd->encContentDigest, sizeof(esd->encContentDigest), + pkcs7->privateKey, pkcs7->privateKeySz, pkcs7->devId, + eccHashOID); + break; + } + #endif /* CMS with ECDSA does not sign DigestInfo structure * like PKCS#7 with RSA does */ ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest, @@ -3986,6 +4000,30 @@ int wc_PKCS7_SetRsaSignRawDigestCb(wc_PKCS7* pkcs7, CallbackRsaSignRawDigest cb) } #endif +#endif /* NO_RSA */ + + +#ifdef HAVE_ECC + +#ifdef HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK +/* register raw ECC sign digest callback */ +int wc_PKCS7_SetEccSignRawDigestCb(wc_PKCS7* pkcs7, CallbackEccSignRawDigest cb) +{ + if (pkcs7 == NULL || cb == NULL) { + return BAD_FUNC_ARG; + } + + pkcs7->eccSignRawDigestCb = cb; + + return 0; +} +#endif + +#endif /* HAVE_ECC */ + + +#ifndef NO_RSA + /* returns size of signature put into out, negative on error */ static int wc_PKCS7_RsaVerify(wc_PKCS7* pkcs7, byte* sig, int sigSz, byte* hash, word32 hashSz) diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 834d17fa5cc..f4e626cd415 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -229,6 +229,14 @@ typedef int (*CallbackRsaSignRawDigest)(wc_PKCS7* pkcs7, byte* digest, int devId, int hashOID); #endif +#if defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && defined(HAVE_ECC) +/* ECC sign raw digest callback, user signs hash directly */ +typedef int (*CallbackEccSignRawDigest)(wc_PKCS7* pkcs7, byte* digest, + word32 digestSz, byte* out, word32 outSz, + byte* privateKey, word32 privateKeySz, + int devId, int hashOID); +#endif + /* Public Structure Warning: * Existing members must not be changed to maintain backwards compatibility! @@ -346,6 +354,10 @@ struct wc_PKCS7 { CallbackRsaSignRawDigest rsaSignRawDigestCb; #endif +#if defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && defined(HAVE_ECC) + CallbackEccSignRawDigest eccSignRawDigestCb; +#endif + /* used by DecodeEnvelopedData with multiple encrypted contents */ byte* cachedEncryptedContent; word32 cachedEncryptedContentSz; @@ -511,6 +523,11 @@ WOLFSSL_API int wc_PKCS7_SetRsaSignRawDigestCb(wc_PKCS7* pkcs7, CallbackRsaSignRawDigest cb); #endif +#if defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && defined(HAVE_ECC) +WOLFSSL_API int wc_PKCS7_SetEccSignRawDigestCb(wc_PKCS7* pkcs7, + CallbackEccSignRawDigest cb); +#endif + /* CMS/PKCS#7 EnvelopedData */ WOLFSSL_API int wc_PKCS7_EncodeEnvelopedData(wc_PKCS7* pkcs7, byte* output, word32 outputSz); From f2f959f693946c6d6949f4ba5be61d35d668b0cc Mon Sep 17 00:00:00 2001 From: jackctj117 Date: Wed, 14 Jan 2026 11:07:41 -0700 Subject: [PATCH 2/4] Added new macro to source tree --- .wolfssl_known_macro_extras | 1 + 1 file changed, 1 insertion(+) diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 56eb6a0dfda..ad3350d28ec 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -280,6 +280,7 @@ HAVE_INTEL_QAT_SYNC HAVE_INTEL_SPEEDUP HAVE_MDK_RTX HAVE_NETX_BSD +HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK HAVE_POCO_LIB HAVE_RTP_SYS From 8e2e6d15aaf623a9d6ab9e376e868c3098a0c24f Mon Sep 17 00:00:00 2001 From: jackctj117 Date: Wed, 14 Jan 2026 17:02:16 -0700 Subject: [PATCH 3/4] removed NO_RSA check --- tests/api/test_pkcs7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/api/test_pkcs7.c b/tests/api/test_pkcs7.c index 72d73fddd66..6833938e892 100644 --- a/tests/api/test_pkcs7.c +++ b/tests/api/test_pkcs7.c @@ -810,7 +810,7 @@ int test_wc_PKCS7_EncodeSignedData(void) #endif #if defined(HAVE_PKCS7) && defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && \ - defined(HAVE_ECC) && defined(NO_RSA) && !defined(NO_SHA256) + defined(HAVE_ECC) && !defined(NO_SHA256) /* test ECC sign raw digest callback, if using ECC and compiled in. * Example callback assumes SHA-256, so only run test if compiled in. */ wc_PKCS7_Free(pkcs7); From 23f4659105791313ca8912c9e0cb13fa36f73a6b Mon Sep 17 00:00:00 2001 From: jackctj117 Date: Thu, 15 Jan 2026 17:17:00 -0700 Subject: [PATCH 4/4] Fix ABI break: move PKCS7 raw sign callbacks to end of struct --- .wolfssl_known_macro_extras | 10 +----- tests/api/test_pkcs7.c | 64 ------------------------------------- wolfcrypt/src/pkcs7.c | 43 ------------------------- wolfssl/wolfcrypt/pkcs7.h | 29 +++++------------ 4 files changed, 9 insertions(+), 137 deletions(-) diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index ad3350d28ec..b703f4db39b 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -280,7 +280,6 @@ HAVE_INTEL_QAT_SYNC HAVE_INTEL_SPEEDUP HAVE_MDK_RTX HAVE_NETX_BSD -HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK HAVE_POCO_LIB HAVE_RTP_SYS @@ -479,7 +478,6 @@ REDIRECTION_OUT2_KEYELMID REDIRECTION_OUT2_KEYID RENESAS_T4_USE RHEL_MAJOR -RHEL_RELEASE_CODE RTC_ALARMSUBSECONDMASK_ALL RTE_CMSIS_RTOS_RTX RTOS_MODULE_NET_AVAIL @@ -624,7 +622,6 @@ WC_LMS_FULL_HASH WC_NO_ASYNC_SLEEP WC_NO_RNG_SIMPLE WC_NO_STATIC_ASSERT -WC_NO_VERBOSE_RNG WC_PKCS11_FIND_WITH_ID_ONLY WC_PROTECT_ENCRYPTED_MEM WC_RNG_BLOCKING @@ -656,7 +653,6 @@ WOLFSSL_AESNI_BY6 WOLFSSL_AES_CTR_EXAMPLE WOLFSSL_AFTER_DATE_CLOCK_SKEW WOLFSSL_ALGO_HW_MUTEX -WOLFSSL_ALLOW_AKID_SKID_MATCH WOLFSSL_ALLOW_BAD_TLS_LEGACY_VERSION WOLFSSL_ALLOW_CRIT_AIA WOLFSSL_ALLOW_CRIT_AKID @@ -791,7 +787,6 @@ WOLFSSL_MONT_RED_CT WOLFSSL_MP_COND_COPY WOLFSSL_MP_INVMOD_CONSTANT_TIME WOLFSSL_MULTICIRCULATE_ALTNAMELIST -WOLFSSL_NEW_PRIME_CHECK WOLFSSL_NONBLOCK_OCSP WOLFSSL_NOSHA3_384 WOLFSSL_NOT_WINDOWS_API @@ -863,7 +858,6 @@ WOLFSSL_RENESAS_RZN2L WOLFSSL_RENESAS_TLS WOLFSSL_RENESAS_TSIP_IAREWRX WOLFSSL_REQUIRE_TCA -WOLFSSL_RNG_USE_FULL_SEED WOLFSSL_RSA_CHECK_D_ON_DECRYPT WOLFSSL_RSA_DECRYPT_TO_0_LEN WOLFSSL_RW_THREADED @@ -891,6 +885,7 @@ WOLFSSL_SP_INT_SQR_VOLATILE WOLFSSL_STACK_CHECK WOLFSSL_STM32F427_RNG WOLFSSL_STM32U5_DHUK +WOLFSSL_STM32_RNG_NOLIB WOLFSSL_STRONGEST_HASH_SIG WOLFSSL_STSAFE_TAKES_SLOT WOLFSSL_TELIT_M2MB @@ -907,7 +902,6 @@ WOLFSSL_TICKET_ENC_HMAC_SHA512 WOLFSSL_TI_CURRTIME WOLFSSL_TLS13_DRAFT WOLFSSL_TLS13_IGNORE_AEAD_LIMITS -WOLFSSL_TLS13_IGNORE_PT_ALERT_ON_ENC WOLFSSL_TLS13_SHA512 WOLFSSL_TLS13_TICKET_BEFORE_FINISHED WOLFSSL_TLSX_PQC_MLKEM_STORE_PRIV_KEY @@ -1034,7 +1028,6 @@ __MWERKS__ __NT__ __OS2__ __OpenBSD__ -__PIC__ __PIE__ __POWERPC__ __PPC__ @@ -1075,7 +1068,6 @@ __WATCOMC__ __WATCOM_INT64__ __XC32 __XTENSA__ -__ZEPHYR__ __aarch64__ __alpha__ __arch64__ diff --git a/tests/api/test_pkcs7.c b/tests/api/test_pkcs7.c index 6833938e892..d60e3abb67f 100644 --- a/tests/api/test_pkcs7.c +++ b/tests/api/test_pkcs7.c @@ -451,46 +451,6 @@ static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz, } #endif -#if defined(HAVE_PKCS7) && defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && \ - defined(HAVE_ECC) && !defined(NO_SHA256) -/* ECC sign raw digest callback */ -static int eccSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz, - byte* out, word32 outSz, byte* privateKey, - word32 privateKeySz, int devid, int hashOID) -{ - int ret; - word32 idx = 0; - word32 sigSz = outSz; - ecc_key ecc; - - if (pkcs7 == NULL || digest == NULL || out == NULL) { - return -1; - } - - (void)hashOID; - - /* set up ECC key */ - ret = wc_ecc_init_ex(&ecc, pkcs7->heap, devid); - if (ret != 0) { - return ret; - } - - ret = wc_EccPrivateKeyDecode(privateKey, &idx, &ecc, privateKeySz); - - /* sign digest */ - if (ret == 0) { - ret = wc_ecc_sign_hash(digest, digestSz, out, &sigSz, pkcs7->rng, &ecc); - if (ret == 0) { - ret = (int)sigSz; - } - } - - wc_ecc_free(&ecc); - - return ret; -} -#endif - #if defined(HAVE_PKCS7) && defined(ASN_BER_TO_DER) typedef struct encodeSignedDataStream { byte out[FOURK_BUF*3]; @@ -809,30 +769,6 @@ int test_wc_PKCS7_EncodeSignedData(void) ExpectIntGT(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), 0); #endif -#if defined(HAVE_PKCS7) && defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && \ - defined(HAVE_ECC) && !defined(NO_SHA256) - /* test ECC sign raw digest callback, if using ECC and compiled in. - * Example callback assumes SHA-256, so only run test if compiled in. */ - wc_PKCS7_Free(pkcs7); - pkcs7 = NULL; - ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); - ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); - - if (pkcs7 != NULL) { - pkcs7->content = data; - pkcs7->contentSz = (word32)sizeof(data); - pkcs7->privateKey = key; - pkcs7->privateKeySz = (word32)keySz; - pkcs7->encryptOID = ECDSAk; - pkcs7->hashOID = SHA256h; - pkcs7->rng = &rng; - } - - ExpectIntEQ(wc_PKCS7_SetEccSignRawDigestCb(pkcs7, eccSignRawDigestCb), 0); - - ExpectIntGT(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), 0); -#endif - wc_PKCS7_Free(pkcs7); DoExpectIntEQ(wc_FreeRng(&rng), 0); diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 428662a868f..9c99f8cf5b6 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -2074,11 +2074,6 @@ static int wc_PKCS7_BuildSignedAttributes(wc_PKCS7* pkcs7, ESD* esd, /* add custom signed attributes if set */ if (pkcs7->signedAttribsSz > 0 && pkcs7->signedAttribs != NULL) { - word32 availableSpace = MAX_SIGNED_ATTRIBS_SZ - atrIdx; - - if (pkcs7->signedAttribsSz > availableSpace) - return BUFFER_E; - esd->signedAttribsCount += pkcs7->signedAttribsSz; esd->signedAttribsSz += (word32)EncodeAttributes( &esd->signedAttribs[atrIdx], (int)esd->signedAttribsCount, @@ -2398,20 +2393,6 @@ static int wc_PKCS7_SignedDataBuildSignature(wc_PKCS7* pkcs7, #ifdef HAVE_ECC case ECDSAk: - #ifdef HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK - if (pkcs7->eccSignRawDigestCb != NULL) { - /* get hash OID */ - int eccHashOID = wc_HashGetOID(esd->hashType); - - /* user signing plain digest */ - ret = pkcs7->eccSignRawDigestCb(pkcs7, - esd->contentAttribsDigest, hashSz, - esd->encContentDigest, sizeof(esd->encContentDigest), - pkcs7->privateKey, pkcs7->privateKeySz, pkcs7->devId, - eccHashOID); - break; - } - #endif /* CMS with ECDSA does not sign DigestInfo structure * like PKCS#7 with RSA does */ ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest, @@ -4000,30 +3981,6 @@ int wc_PKCS7_SetRsaSignRawDigestCb(wc_PKCS7* pkcs7, CallbackRsaSignRawDigest cb) } #endif -#endif /* NO_RSA */ - - -#ifdef HAVE_ECC - -#ifdef HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK -/* register raw ECC sign digest callback */ -int wc_PKCS7_SetEccSignRawDigestCb(wc_PKCS7* pkcs7, CallbackEccSignRawDigest cb) -{ - if (pkcs7 == NULL || cb == NULL) { - return BAD_FUNC_ARG; - } - - pkcs7->eccSignRawDigestCb = cb; - - return 0; -} -#endif - -#endif /* HAVE_ECC */ - - -#ifndef NO_RSA - /* returns size of signature put into out, negative on error */ static int wc_PKCS7_RsaVerify(wc_PKCS7* pkcs7, byte* sig, int sigSz, byte* hash, word32 hashSz) diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index f4e626cd415..75a92393b6d 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -229,14 +229,6 @@ typedef int (*CallbackRsaSignRawDigest)(wc_PKCS7* pkcs7, byte* digest, int devId, int hashOID); #endif -#if defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && defined(HAVE_ECC) -/* ECC sign raw digest callback, user signs hash directly */ -typedef int (*CallbackEccSignRawDigest)(wc_PKCS7* pkcs7, byte* digest, - word32 digestSz, byte* out, word32 outSz, - byte* privateKey, word32 privateKeySz, - int devId, int hashOID); -#endif - /* Public Structure Warning: * Existing members must not be changed to maintain backwards compatibility! @@ -350,14 +342,6 @@ struct wc_PKCS7 { wc_UnknownExtCallback unknownExtCallback; #endif -#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA) - CallbackRsaSignRawDigest rsaSignRawDigestCb; -#endif - -#if defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && defined(HAVE_ECC) - CallbackEccSignRawDigest eccSignRawDigestCb; -#endif - /* used by DecodeEnvelopedData with multiple encrypted contents */ byte* cachedEncryptedContent; word32 cachedEncryptedContentSz; @@ -388,6 +372,14 @@ struct wc_PKCS7 { CallbackAESKeyWrapUnwrap aesKeyWrapUnwrapCb; +#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA) + CallbackRsaSignRawDigest rsaSignRawDigestCb; +#endif + +#if defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && defined(HAVE_ECC) + CallbackEccSignRawDigest eccSignRawDigestCb; +#endif + /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ }; @@ -523,11 +515,6 @@ WOLFSSL_API int wc_PKCS7_SetRsaSignRawDigestCb(wc_PKCS7* pkcs7, CallbackRsaSignRawDigest cb); #endif -#if defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && defined(HAVE_ECC) -WOLFSSL_API int wc_PKCS7_SetEccSignRawDigestCb(wc_PKCS7* pkcs7, - CallbackEccSignRawDigest cb); -#endif - /* CMS/PKCS#7 EnvelopedData */ WOLFSSL_API int wc_PKCS7_EncodeEnvelopedData(wc_PKCS7* pkcs7, byte* output, word32 outputSz);