Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .wolfssl_known_macro_extras
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
154 changes: 149 additions & 5 deletions tests/api/test_pkcs7.c
Original file line number Diff line number Diff line change
Expand Up @@ -388,12 +388,15 @@ int test_wc_PKCS7_EncodeData(void)

#if defined(HAVE_PKCS7) && defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && \
!defined(NO_RSA) && !defined(NO_SHA256)
/* RSA sign raw digest callback */
/* RSA sign raw digest callback
* This callback demonstrates HSM/secure element use case where the private
* key is not passed through PKCS7 structure but obtained independently.
*/
static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz,
byte* out, word32 outSz, byte* privateKey,
word32 privateKeySz, int devid, int hashOID)
{
/* specific DigestInfo ASN.1 encoding prefix for a SHA2565 digest */
/* specific DigestInfo ASN.1 encoding prefix for a SHA256 digest */
byte digInfoEncoding[] = {
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
Expand All @@ -407,6 +410,11 @@ static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz,
word32 idx = 0;
RsaKey rsa;

/* privateKey may be NULL in HSM/secure element use case - we load it
* independently in this callback to simulate that scenario */
(void)privateKey;
(void)privateKeySz;

/* SHA-256 required only for this example callback due to above
* digInfoEncoding[] */
if (pkcs7 == NULL || digest == NULL || out == NULL ||
Expand All @@ -427,7 +435,33 @@ static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz,
return ret;
}

ret = wc_RsaPrivateKeyDecode(privateKey, &idx, &rsa, privateKeySz);
/* Load key from test buffer - simulates HSM/secure element access */
#if defined(USE_CERT_BUFFERS_2048)
ret = wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &rsa,
sizeof_client_key_der_2048);
#elif defined(USE_CERT_BUFFERS_1024)
ret = wc_RsaPrivateKeyDecode(client_key_der_1024, &idx, &rsa,
sizeof_client_key_der_1024);
#else
{
XFILE fp;
byte keyBuf[ONEK_BUF];
int keySz;

fp = XFOPEN("./certs/client-key.der", "rb");
if (fp == XBADFILE) {
wc_FreeRsaKey(&rsa);
return -1;
}
keySz = (int)XFREAD(keyBuf, 1, sizeof(keyBuf), fp);
XFCLOSE(fp);
if (keySz <= 0) {
wc_FreeRsaKey(&rsa);
return -1;
}
ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &rsa, (word32)keySz);
}
#endif

/* sign DigestInfo */
if (ret == 0) {
Expand All @@ -451,6 +485,76 @@ 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
* This callback demonstrates HSM/secure element use case where the private
* key is not passed through PKCS7 structure but obtained independently.
*/
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;

/* privateKey may be NULL in HSM/secure element use case - we load it
* independently in this callback to simulate that scenario */
(void)privateKey;
(void)privateKeySz;
(void)hashOID;

if (pkcs7 == NULL || digest == NULL || out == NULL) {
return -1;
}

/* set up ECC key */
ret = wc_ecc_init_ex(&ecc, pkcs7->heap, devid);
if (ret != 0) {
return ret;
}

/* Load key from test buffer - simulates HSM/secure element access */
#if defined(USE_CERT_BUFFERS_256)
ret = wc_EccPrivateKeyDecode(ecc_clikey_der_256, &idx, &ecc,
sizeof_ecc_clikey_der_256);
#else
{
XFILE fp;
byte keyBuf[ONEK_BUF];
int keySz;

fp = XFOPEN("./certs/client-ecc-key.der", "rb");
if (fp == XBADFILE) {
wc_ecc_free(&ecc);
return -1;
}
keySz = (int)XFREAD(keyBuf, 1, sizeof(keyBuf), fp);
XFCLOSE(fp);
if (keySz <= 0) {
wc_ecc_free(&ecc);
return -1;
}
ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &ecc, (word32)keySz);
}
#endif

/* 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];
Expand Down Expand Up @@ -757,8 +861,7 @@ int test_wc_PKCS7_EncodeSignedData(void)
if (pkcs7 != NULL) {
pkcs7->content = data;
pkcs7->contentSz = (word32)sizeof(data);
pkcs7->privateKey = key;
pkcs7->privateKeySz = (word32)sizeof(key);
/* privateKey not set - callback simulates HSM/secure element access */
pkcs7->encryptOID = RSAk;
pkcs7->hashOID = SHA256h;
pkcs7->rng = &rng;
Expand All @@ -769,6 +872,47 @@ 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. */
{
#if defined(USE_CERT_BUFFERS_256)
byte eccCert[sizeof(cliecc_cert_der_256)];
word32 eccCertSz = (word32)sizeof(eccCert);
XMEMCPY(eccCert, cliecc_cert_der_256, eccCertSz);
#else
byte eccCert[ONEK_BUF];
int eccCertSz;
XFILE eccFp = XBADFILE;

ExpectTrue((eccFp = XFOPEN("./certs/client-ecc-cert.der", "rb")) !=
XBADFILE);
ExpectIntGT(eccCertSz = (int)XFREAD(eccCert, 1, ONEK_BUF, eccFp), 0);
if (eccFp != XBADFILE)
XFCLOSE(eccFp);
#endif

wc_PKCS7_Free(pkcs7);
pkcs7 = NULL;
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, eccCert, (word32)eccCertSz), 0);

if (pkcs7 != NULL) {
pkcs7->content = data;
pkcs7->contentSz = (word32)sizeof(data);
/* privateKey not set - callback simulates HSM/secure element access */
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);

Expand Down
58 changes: 58 additions & 0 deletions wolfcrypt/src/pkcs7.c
Original file line number Diff line number Diff line change
Expand Up @@ -1794,6 +1794,16 @@ static int wc_PKCS7_ImportRSA(wc_PKCS7* pkcs7, RsaKey* privKey)
}
#endif
}
#ifdef HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK
else if (pkcs7->rsaSignRawDigestCb != NULL && pkcs7->publicKeySz > 0) {
/* When using raw sign callback (e.g., HSM/secure element), private
* key may not be available. Use public key from signer certificate
* for signature size calculation. */
idx = 0;
ret = wc_RsaPublicKeyDecode(pkcs7->publicKey, &idx, privKey,
pkcs7->publicKeySz);
}
#endif
else if (pkcs7->devId == INVALID_DEVID) {
ret = BAD_FUNC_ARG;
}
Expand Down Expand Up @@ -1874,6 +1884,16 @@ static int wc_PKCS7_ImportECC(wc_PKCS7* pkcs7, ecc_key* privKey)
}
#endif
}
#ifdef HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK
else if (pkcs7->eccSignRawDigestCb != NULL && pkcs7->publicKeySz > 0) {
/* When using raw sign callback (e.g., HSM/secure element), private
* key may not be available. Use public key from signer certificate
* for signature size calculation. */
idx = 0;
ret = wc_EccPublicKeyDecode(pkcs7->publicKey, &idx, privKey,
pkcs7->publicKeySz);
}
#endif
else if (pkcs7->devId == INVALID_DEVID) {
ret = BAD_FUNC_ARG;
}
Expand Down Expand Up @@ -2398,6 +2418,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,
Expand Down Expand Up @@ -3986,6 +4020,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)
Expand Down
17 changes: 17 additions & 0 deletions wolfssl/wolfcrypt/pkcs7.h
Original file line number Diff line number Diff line change
Expand Up @@ -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!
Expand Down Expand Up @@ -376,6 +384,10 @@ struct wc_PKCS7 {

CallbackAESKeyWrapUnwrap aesKeyWrapUnwrapCb;

#if defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && defined(HAVE_ECC)
CallbackEccSignRawDigest eccSignRawDigestCb;
#endif

/* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */
};

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