From 2044d6b7dd481929dd4aaa80d6edc8d7a3065fa9 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Thu, 8 Feb 2024 02:44:18 +0700 Subject: [PATCH 1/9] add callbacks for PKCS7 streaming input and output --- tests/api.c | 50 +- wolfcrypt/src/asn.c | 4 +- wolfcrypt/src/pkcs7.c | 1103 +++++++++++++++++++++++++++++-------- wolfssl/wolfcrypt/pkcs7.h | 13 +- 4 files changed, 922 insertions(+), 248 deletions(-) diff --git a/tests/api.c b/tests/api.c index 1d7c55d41..1af455a75 100644 --- a/tests/api.c +++ b/tests/api.c @@ -27019,8 +27019,8 @@ static int test_wc_PKCS7_EncodeSignedData(void) pkcs7->rng = &rng; } ExpectIntEQ(wc_PKCS7_GetStreamMode(pkcs7), 0); - ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1), 0); - ExpectIntEQ(wc_PKCS7_SetStreamMode(NULL, 1), BAD_FUNC_ARG); + ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1, NULL, NULL), 0); + ExpectIntEQ(wc_PKCS7_SetStreamMode(NULL, 1, NULL, NULL), BAD_FUNC_ARG); ExpectIntEQ(wc_PKCS7_GetStreamMode(pkcs7), 1); ExpectIntGT(signedSz = wc_PKCS7_EncodeSignedData(pkcs7, output, @@ -28287,16 +28287,46 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void) pkcs7->privateKey = (testVectors + i)->privateKey; pkcs7->privateKeySz = (testVectors + i)->privateKeySz; } - ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1), 0); + ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1, NULL, NULL), 0); - ExpectIntGE(encodedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, output, - (word32)sizeof(output)), 0); + encodedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, output, + (word32)sizeof(output)); - decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, output, - (word32)encodedSz, decoded, (word32)sizeof(decoded)); - ExpectIntGE(decodedSz, 0); - /* Verify the size of each buffer. */ - ExpectIntEQ((word32)sizeof(input)/sizeof(char), decodedSz); + switch ((testVectors + i)->encryptOID) { + #ifndef NO_DES3 + case DES3b: + case DESb: + ExpectIntEQ(encodedSz, BAD_FUNC_ARG); + break; + #endif + #ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + ExpectIntEQ(encodedSz, BAD_FUNC_ARG); + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + ExpectIntEQ(encodedSz, BAD_FUNC_ARG); + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + ExpectIntEQ(encodedSz, BAD_FUNC_ARG); + break; + #endif + #endif + default: + ExpectIntGE(encodedSz, 0); + } + + if (encodedSz > 0) { + decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, output, + (word32)encodedSz, decoded, (word32)sizeof(decoded)); + ExpectIntGE(decodedSz, 0); + /* Verify the size of each buffer. */ + ExpectIntEQ((word32)sizeof(input)/sizeof(char), decodedSz); + } wc_PKCS7_Free(pkcs7); pkcs7 = NULL; ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 099dc059b..110a62453 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -3465,7 +3465,9 @@ word32 SetBitString(word32 len, byte unusedBits, byte* output) #ifdef ASN_BER_TO_DER -#define BER_OCTET_LENGTH 4096 +#ifndef BER_OCTET_LENGTH + #define BER_OCTET_LENGTH 4096 +#endif /* sets the terminating 0x00 0x00 at the end of an indefinite length * returns the number of bytes written */ diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 4f7bbc4b1..55b56fda0 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -1487,6 +1487,7 @@ typedef struct ESD { wc_HashAlg hash; enum wc_HashType hashType; byte contentDigest[WC_MAX_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */ + byte contentDigestSet:1; byte contentAttribsDigest[WC_MAX_DIGEST_SIZE]; byte encContentDigest[MAX_ENCRYPTED_KEY_SZ]; @@ -1740,27 +1741,10 @@ static int FlattenAttributes(PKCS7* pkcs7, byte* output, EncodedAttrib* ea, #ifndef NO_RSA -/* returns size of signature put into out, negative on error */ -static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) +static int wc_PKCS7_ImportRSA(PKCS7* pkcs7, RsaKey* privKey) { int ret; word32 idx; -#ifdef WOLFSSL_SMALL_STACK - RsaKey* privKey; -#else - RsaKey privKey[1]; -#endif - - if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) { - return BAD_FUNC_ARG; - } - -#ifdef WOLFSSL_SMALL_STACK - privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (privKey == NULL) - return MEMORY_E; -#endif ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, pkcs7->devId); if (ret == 0) { @@ -1794,6 +1778,32 @@ static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) } } + return ret; +} + + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + RsaKey* privKey; +#else + RsaKey privKey[1]; +#endif + + if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; +#endif + + ret = wc_PKCS7_ImportRSA(pkcs7, privKey); if (ret == 0) { #ifdef WOLFSSL_ASYNC_CRYPT do { @@ -1824,27 +1834,10 @@ static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) #ifdef HAVE_ECC -/* returns size of signature put into out, negative on error */ -static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) +static int wc_PKCS7_ImportECC(PKCS7* pkcs7, ecc_key* privKey) { int ret; - word32 outSz, idx; -#ifdef WOLFSSL_SMALL_STACK - ecc_key* privKey; -#else - ecc_key privKey[1]; -#endif - - if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) { - return BAD_FUNC_ARG; - } - -#ifdef WOLFSSL_SMALL_STACK - privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (privKey == NULL) - return MEMORY_E; -#endif + word32 idx; ret = wc_ecc_init_ex(privKey, pkcs7->heap, pkcs7->devId); if (ret == 0) { @@ -1874,6 +1867,33 @@ static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) } } + return ret; +} + + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) +{ + int ret; + word32 outSz; +#ifdef WOLFSSL_SMALL_STACK + ecc_key* privKey; +#else + ecc_key privKey[1]; +#endif + + if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; +#endif + + ret = wc_PKCS7_ImportECC(pkcs7, privKey); if (ret == 0) { outSz = sizeof(esd->encContentDigest); #ifdef WOLFSSL_ASYNC_CRYPT @@ -1903,6 +1923,67 @@ static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) #endif /* HAVE_ECC */ +/* returns encContentDigestSz based on the signature set to be used */ +static int wc_PKCS7_GetSignSize(PKCS7* pkcs7) +{ + int ret = 0; + + switch (pkcs7->publicKeyOID) { + + #ifndef NO_RSA + case RSAk: + { + #ifndef WOLFSSL_SMALL_STACK + RsaKey privKey[1]; + #else + RsaKey* privKey; + privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; + #endif + + ret = wc_PKCS7_ImportRSA(pkcs7, privKey); + if (ret == 0) { + ret = wc_RsaEncryptSize(privKey); + } + wc_FreeRsaKey(privKey); + #ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + break; + #endif + + #ifdef HAVE_ECC + case ECDSAk: + { + #ifndef WOLFSSL_SMALL_STACK + ecc_key privKey[1]; + #else + ecc_key* privKey; + privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; + #endif + + ret = wc_PKCS7_ImportECC(pkcs7, privKey); + if (ret == 0) { + ret = wc_ecc_sig_size(privKey); + } + wc_ecc_free(privKey); + #ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + break; + #endif + } + + return ret; +} + /* builds up SignedData signed attributes, including default ones. * @@ -2345,10 +2426,278 @@ static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, return ret; } +#ifndef BER_OCTET_LENGTH + #define BER_OCTET_LENGTH 4096 +#endif + + +/* Used for encoding the content, potentially one octet chunck at a time if + * in streaming mode with IO callbacks set. + * Can handle the cipher types: + * - WC_CIPHER_NONE, used for encoding signed bundle where no encryption is + * done. + * - WC_CIPHER_AES_CBC + * - WC_CIPHER_AES_GCM, requires WOLFSSL_AESGCM_STREAM for streaming + * encryption + * If ESD is passed in then hash of the conentet is collected as processed. + * + * Returns 0 on success */ +#ifndef NO_AES +static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, Aes* aes, + byte* in, int inSz, byte* out, int cipherType) +#else +static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, + byte* in, int inSz, byte* out, int cipherType) +#endif +{ + int ret = 0; + int devId = pkcs7->devId; + void* heap = pkcs7->heap; + + if (pkcs7->encodeStream) { + int sz; + word32 totalSz = 0; + byte encContentOutOct[MAX_OCTET_STR_SZ]; + word32 encContentOutOctSz = 0; + byte* buf; + byte* encContentOut; + byte* contentData; + word32 idx = 0, outIdx = 0; + int padSz = 0; + + if (cipherType != WC_CIPHER_NONE) { + padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, + wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID)); + } + + if (cipherType == WC_CIPHER_NONE && esd && esd->contentDigestSet != 1) { + /* calculate hash for content */ + ret = wc_HashInit(&esd->hash, esd->hashType); + } + + encContentOut = XMALLOC(BER_OCTET_LENGTH + MAX_OCTET_STR_SZ, + heap, DYNAMIC_TYPE_PKCS7); + contentData = XMALLOC(BER_OCTET_LENGTH + padSz, + heap, DYNAMIC_TYPE_PKCS7); + + if (encContentOut == NULL || contentData == NULL) { + XFREE(encContentOut, heap, DYNAMIC_TYPE_PKCS7); + XFREE(contentData, heap, DYNAMIC_TYPE_PKCS7); + WOLFSSL_MSG("Memory allocation failed for content data"); + return MEMORY_E; + } + + encContentOutOctSz = SetOctetString(BER_OCTET_LENGTH, + encContentOutOct); + + /* keep pulling from content until empty */ + do { + int contentDataRead = 0; + + #ifdef ASN_BER_TO_DER + if (pkcs7->getContentCb) { + contentDataRead = pkcs7->getContentCb(pkcs7, + &buf); + } + else + #endif + { + int szLeft = BER_OCTET_LENGTH; + + if (szLeft + totalSz > (word32)inSz) + szLeft = inSz - totalSz; + + contentDataRead = szLeft; + buf = in + totalSz; + } + + if (contentDataRead <= 0) { + /* no more data returned from callback */ + break; + } + + if (buf == NULL) { + WOLFSSL_MSG("Get content callback returned null " + "buffer pointer"); + XFREE(encContentOut, heap, DYNAMIC_TYPE_PKCS7); + XFREE(contentData, heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + } + totalSz += (word32)contentDataRead; + + /* check and handle octet boundary */ + sz = contentDataRead; + if (idx + sz > BER_OCTET_LENGTH) { + sz = BER_OCTET_LENGTH - idx; + contentDataRead -= sz; + + XMEMCPY(contentData + idx, buf, sz); + + /* encrypt and flush out data */ + switch (cipherType) { + case WC_CIPHER_NONE: + XMEMCPY(encContentOut, contentData, BER_OCTET_LENGTH); + if (esd && esd->contentDigestSet != 1) { + ret = wc_HashUpdate(&esd->hash, esd->hashType, + contentData, BER_OCTET_LENGTH); + } + break; + + #ifndef NO_AES + case WC_CIPHER_AES_CBC: + ret = wc_AesCbcEncrypt(aes, encContentOut, + contentData, BER_OCTET_LENGTH); + break; + #endif + + #ifdef WOLFSSL_AESGCM_STREAM + case WC_CIPHER_AES_GCM: + ret = wc_AesGcmEncryptUpdate(aes, encContentOut, + contentData, BER_OCTET_LENGTH, NULL, 0); + break; + #endif + } + + #ifdef WOLFSSL_ASYNC_CRYPT + /* async encrypt not available here, so block till done */ + if (cipherType != WC_CIPHER_NONE) { + ret = wc_AsyncWait(ret, &aes->asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (pkcs7->encodeStream) { + wc_PKCS7_WriteOut(pkcs7, + (out)? out + outIdx: NULL, + encContentOutOct, + encContentOutOctSz); + outIdx += encContentOutOctSz; + } + wc_PKCS7_WriteOut(pkcs7, + (out)? out + outIdx : NULL, + encContentOut, + BER_OCTET_LENGTH); + outIdx += BER_OCTET_LENGTH; + + /* copy over any remaining data */ + XMEMCPY(contentData, buf + sz, contentDataRead); + idx = contentDataRead; + } + else { + /* was not on an octet boundary, copy full + * amount over */ + XMEMCPY(contentData + idx, buf, sz); + idx += sz; + } + } while (totalSz < pkcs7->contentSz); + + /* add in padding to the end */ + if ((cipherType != WC_CIPHER_NONE) && (totalSz == pkcs7->contentSz)) { + int i; + + if (BER_OCTET_LENGTH < idx) { + XFREE(encContentOut, heap, DYNAMIC_TYPE_PKCS7); + XFREE(contentData, heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + } + + for (i = 0; i < padSz; i++) { + contentData[idx + i] = (byte)padSz; + } + idx += padSz; + } + + + /* encrypt and flush out remainder of content data */ + switch (cipherType) { + case WC_CIPHER_NONE: + XMEMCPY(encContentOut, contentData, idx); + if (esd && esd->contentDigestSet != 1) { + ret = wc_HashUpdate(&esd->hash, esd->hashType, contentData, idx); + } + break; + + #ifndef NO_AES + case WC_CIPHER_AES_CBC: + ret = wc_AesCbcEncrypt(aes, encContentOut, contentData, idx); + break; + #endif + + #ifdef WOLFSSL_AESGCM_STREAM + case WC_CIPHER_AES_GCM: + ret = wc_AesGcmEncryptUpdate(aes, encContentOut, + contentData, idx, NULL, 0); + break; + #endif + } + #ifdef WOLFSSL_ASYNC_CRYPT + /* async encrypt not available here, so block till done */ + if (cipherType != WC_CIPHER_NONE) { + ret = wc_AsyncWait(ret, &aes->asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (pkcs7->encodeStream) { + encContentOutOctSz = SetOctetString(idx, + encContentOutOct); + wc_PKCS7_WriteOut(pkcs7, (out)? out + outIdx: NULL, + encContentOutOct, encContentOutOctSz); + outIdx += encContentOutOctSz; + } + wc_PKCS7_WriteOut(pkcs7, (out)? out + outIdx : NULL, + encContentOut, idx); + + if (cipherType == WC_CIPHER_NONE && esd && esd->contentDigestSet != 1) { + ret = wc_HashFinal(&esd->hash, esd->hashType, esd->contentDigest + 2); + wc_HashFree(&esd->hash, esd->hashType); + } + + XFREE(encContentOut, heap, DYNAMIC_TYPE_PKCS7); + XFREE(contentData, heap, DYNAMIC_TYPE_PKCS7); + } + else { + switch (cipherType) { + case WC_CIPHER_NONE: + if (!pkcs7->detached) { + XMEMCPY(out, in, inSz); + } + if (esd && esd->contentDigestSet != 1) { + ret = wc_HashInit(&esd->hash, esd->hashType); + if (ret == 0) + ret = wc_HashUpdate(&esd->hash, esd->hashType, in, inSz); + if (ret == 0) + ret = wc_HashFinal(&esd->hash, esd->hashType, esd->contentDigest + 2); + wc_HashFree(&esd->hash, esd->hashType); + } + break; + + #ifndef NO_AES + case WC_CIPHER_AES_CBC: + ret = wc_AesCbcEncrypt(aes, out, in, inSz); + break; + #endif + + #ifdef WOLFSSL_AESGCM_STREAM + case WC_CIPHER_AES_GCM: + ret = wc_AesGcmEncryptUpdate(aes, out, in, inSz, NULL, 0); + break; + #endif + } + #ifdef WOLFSSL_ASYNC_CRYPT + /* async encrypt not available here, so block till done */ + if (cipherType != WC_CIPHER_NONE) { + ret = wc_AsyncWait(ret, &aes->asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + } + + (void)devId; + (void)heap; + + return ret; +} + /* build PKCS#7 signedData content type */ /* To get the output size then set output = 0 and *outputSz = 0 */ -static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, +static int PKCS7_EncodeSigned(PKCS7* pkcs7, const byte* hashBuf, word32 hashSz, byte* output, word32* outputSz, byte* output2, word32* output2Sz) { @@ -2378,6 +2727,14 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, byte* flatSignedAttribs = NULL; word32 flatSignedAttribsSz = 0; +#ifdef WOLFSSL_SMALL_STACK + ESD* esd; +#else + ESD esd[1]; +#endif +#ifdef ASN_BER_TO_DER + word32 streamSz = 0; +#endif #ifdef WOLFSSL_SMALL_STACK byte *signedDataOid = NULL; #else @@ -2388,8 +2745,22 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, byte signingTime[MAX_TIME_STRING_SZ]; if (pkcs7 == NULL || pkcs7->hashOID == 0 || - outputSz == NULL || hashSz == 0 || - hashBuf == NULL) { + outputSz == NULL) { + WOLFSSL_MSG("PKCS7 struct / outputSz null, or hashOID is 0"); + return BAD_FUNC_ARG; + } + + if (hashSz == 0 && hashBuf != NULL) { + return BAD_FUNC_ARG; + } + + /* signature size varies with ECDSA, with a varying sign size the content + * hash must be known in order to create the surrounding ASN1 syntax + * properly before writing out the content and generating the hash on the + * fly and then creating the signature */ + if (pkcs7->getContentCb != NULL && hashBuf == NULL && + pkcs7->publicKeyOID == ECDSAk) { + WOLFSSL_MSG("Pre-calculated content hash is needed in this case"); return BAD_FUNC_ARG; } @@ -2444,16 +2815,24 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, if (pkcs7->sidType != DEGENERATE_SID) { esd->hashType = wc_OidGetHash(pkcs7->hashOID); - if (wc_HashGetDigestSize(esd->hashType) != (int)hashSz) { + if (hashBuf != NULL && + wc_HashGetDigestSize(esd->hashType) != (int)hashSz) { WOLFSSL_MSG("hashSz did not match hashOID"); idx = BUFFER_E; goto out; } - /* include hash */ + /* include hash if provided, otherwise create hash when processing + * content data */ esd->contentDigest[0] = ASN_OCTET_STRING; - esd->contentDigest[1] = (byte)hashSz; - XMEMCPY(&esd->contentDigest[2], hashBuf, hashSz); + if (hashBuf != NULL) { + esd->contentDigestSet = 1; + esd->contentDigest[1] = (byte)hashSz; + XMEMCPY(&esd->contentDigest[2], hashBuf, hashSz); + } + else { + esd->contentDigest[1] = (byte)wc_HashGetDigestSize(esd->hashType); + } } if (pkcs7->detached == 1) { @@ -2559,9 +2938,13 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, esd->signedAttribSetSz = 0; } - /* Calculate the final hash and encrypt it. */ - ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs, - flatSignedAttribsSz, esd); + if (pkcs7->publicKeyOID != ECDSAk && hashBuf == NULL) { + ret = esd->encContentDigestSz = wc_PKCS7_GetSignSize(pkcs7); + } + else { + ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs, + flatSignedAttribsSz, esd); + } if (ret < 0) { idx = ret; goto out; @@ -2613,11 +2996,12 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, #ifdef ASN_BER_TO_DER if (pkcs7->encodeStream) { - word32 sz = 0, tmpIdx = 0; + word32 tmpIdx = 0; totalSz += (3 * ASN_INDEF_END_SZ) ; /* 00's for BER with inner content */ - StreamOctetString(pkcs7->content, pkcs7->contentSz, NULL, &sz, &tmpIdx); - totalSz += sz + (3 * ASN_INDEF_END_SZ); + StreamOctetString(pkcs7->content, pkcs7->contentSz, NULL, &streamSz, + &tmpIdx); + totalSz += streamSz + (3 * ASN_INDEF_END_SZ); } else #endif @@ -2673,7 +3057,11 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, totalSz += total2Sz; } - if (totalSz > *outputSz) { + if (totalSz > *outputSz + #ifdef ASN_BER_TO_DER + && pkcs7->streamOutCb == NULL + #endif + ) { if (*outputSz == 0) { #ifdef HAVE_ECC if (pkcs7->publicKeyOID == ECDSAk) { @@ -2688,33 +3076,48 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, goto out; } +#ifdef ASN_BER_TO_DER + if (output == NULL && pkcs7->streamOutCb == NULL) { +#else if (output == NULL) { +#endif idx = BUFFER_E; goto out; } idx = 0; - XMEMCPY(output + idx, esd->outerSeq, esd->outerSeqSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + esd->outerSeq, esd->outerSeqSz); idx += esd->outerSeqSz; - XMEMCPY(output + idx, signedDataOid, signedDataOidSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + signedDataOid, signedDataOidSz); idx += signedDataOidSz; - XMEMCPY(output + idx, esd->outerContent, esd->outerContentSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + esd->outerContent, esd->outerContentSz); idx += esd->outerContentSz; - XMEMCPY(output + idx, esd->innerSeq, esd->innerSeqSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + esd->innerSeq, esd->innerSeqSz); idx += esd->innerSeqSz; - XMEMCPY(output + idx, esd->version, esd->versionSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + esd->version, esd->versionSz); idx += esd->versionSz; - XMEMCPY(output + idx, esd->digAlgoIdSet, esd->digAlgoIdSetSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + esd->digAlgoIdSet, esd->digAlgoIdSetSz); idx += esd->digAlgoIdSetSz; - XMEMCPY(output + idx, esd->singleDigAlgoId, esd->singleDigAlgoIdSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + esd->singleDigAlgoId, esd->singleDigAlgoIdSz); idx += esd->singleDigAlgoIdSz; - XMEMCPY(output + idx, esd->contentInfoSeq, esd->contentInfoSeqSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + esd->contentInfoSeq, esd->contentInfoSeqSz); idx += esd->contentInfoSeqSz; - XMEMCPY(output + idx, pkcs7->contentType, pkcs7->contentTypeSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + pkcs7->contentType, pkcs7->contentTypeSz); idx += pkcs7->contentTypeSz; - XMEMCPY(output + idx, esd->innerContSeq, esd->innerContSeqSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + esd->innerContSeq, esd->innerContSeqSz); idx += esd->innerContSeqSz; - XMEMCPY(output + idx, esd->innerOctets, esd->innerOctetsSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + esd->innerOctets, esd->innerOctetsSz); idx += esd->innerOctetsSz; /* support returning header and footer without content */ @@ -2723,39 +3126,56 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, idx = 0; } else { - if (!pkcs7->detached && pkcs7->content != NULL && pkcs7->contentSz > 0) { + if ( #ifdef ASN_BER_TO_DER - if (pkcs7->encodeStream) { - StreamOctetString(pkcs7->content, pkcs7->contentSz, output, - outputSz, (word32*)&idx); - - /* end of content octet string */ - idx += SetIndefEnd(output + idx); - - /* end of inner content seq */ - idx += SetIndefEnd(output + idx); - - /* end of inner content info seq */ - idx += SetIndefEnd(output + idx); - } - else + (pkcs7->content != NULL || pkcs7->getContentCb != NULL) + #else + pkcs7->content != NULL #endif - { - XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz); - idx += pkcs7->contentSz; + && pkcs7->contentSz > 0) { + wc_PKCS7_EncodeContentStream(pkcs7, esd, NULL, pkcs7->content, + pkcs7->contentSz, (output)? output + idx : NULL, WC_CIPHER_NONE); + if (!pkcs7->detached) { + #ifdef ASN_BER_TO_DER + if (pkcs7->encodeStream) { + byte indefEnd[ASN_INDEF_END_SZ * 3]; + word32 localIdx = 0; + + idx += streamSz; + + /* end of content octet string */ + localIdx += SetIndefEnd(indefEnd + localIdx); + + /* end of inner content seq */ + localIdx += SetIndefEnd(indefEnd + localIdx); + + /* end of inner content info seq */ + localIdx += SetIndefEnd(indefEnd + localIdx); + + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + indefEnd, localIdx); + idx += localIdx; + } + else + #endif + { + idx += pkcs7->contentSz; + } } } output2 = output; } /* certificates */ - XMEMCPY(output2 + idx, esd->certsSet, esd->certsSetSz); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + esd->certsSet, esd->certsSetSz); idx += esd->certsSetSz; if (pkcs7->noCerts != 1) { certPtr = pkcs7->certList; while (certPtr != NULL) { - XMEMCPY(output2 + idx, certPtr->der, certPtr->derSz); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + certPtr->der, certPtr->derSz); idx += certPtr->derSz; certPtr = certPtr->next; } @@ -2763,30 +3183,40 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, wc_PKCS7_FreeCertSet(pkcs7); - XMEMCPY(output2 + idx, esd->signerInfoSet, esd->signerInfoSetSz); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + esd->signerInfoSet, esd->signerInfoSetSz); idx += esd->signerInfoSetSz; - XMEMCPY(output2 + idx, esd->signerInfoSeq, esd->signerInfoSeqSz); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + esd->signerInfoSeq, esd->signerInfoSeqSz); idx += esd->signerInfoSeqSz; - XMEMCPY(output2 + idx, esd->signerVersion, esd->signerVersionSz); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + esd->signerVersion, esd->signerVersionSz); idx += esd->signerVersionSz; /* SignerIdentifier */ if (pkcs7->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { /* IssuerAndSerialNumber */ - XMEMCPY(output2 + idx, esd->issuerSnSeq, esd->issuerSnSeqSz); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + esd->issuerSnSeq, esd->issuerSnSeqSz); idx += esd->issuerSnSeqSz; - XMEMCPY(output2 + idx, esd->issuerName, esd->issuerNameSz); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + esd->issuerName, esd->issuerNameSz); idx += esd->issuerNameSz; - XMEMCPY(output2 + idx, pkcs7->issuer, pkcs7->issuerSz); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + pkcs7->issuer, pkcs7->issuerSz); idx += pkcs7->issuerSz; - XMEMCPY(output2 + idx, esd->issuerSn, esd->issuerSnSz); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + esd->issuerSn, esd->issuerSnSz); idx += esd->issuerSnSz; } else if (pkcs7->sidType == CMS_SKID) { /* SubjectKeyIdentifier */ - XMEMCPY(output2 + idx, esd->issuerSKIDSeq, esd->issuerSKIDSeqSz); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + esd->issuerSKIDSeq, esd->issuerSKIDSeqSz); idx += esd->issuerSKIDSeqSz; - XMEMCPY(output2 + idx, esd->issuerSKID, esd->issuerSKIDSz); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + esd->issuerSKID, esd->issuerSKIDSz); idx += esd->issuerSKIDSz; - XMEMCPY(output2 + idx, pkcs7->issuerSubjKeyId, keyIdSize); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + pkcs7->issuerSubjKeyId, keyIdSize); idx += keyIdSize; } else if (pkcs7->sidType == DEGENERATE_SID) { /* no signer infos in degenerate case */ @@ -2794,34 +3224,92 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, idx = SKID_E; goto out; } - XMEMCPY(output2 + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + esd->signerDigAlgoId, esd->signerDigAlgoIdSz); idx += esd->signerDigAlgoIdSz; /* SignerInfo:Attributes */ if (flatSignedAttribsSz > 0) { - XMEMCPY(output2 + idx, esd->signedAttribSet, esd->signedAttribSetSz); + /* if the original hash buffer passed in was null then recreate the + * signature */ + if (hashBuf == NULL && pkcs7->sidType != DEGENERATE_SID) { + /* recreate flat attribs after the content hash is known if needed + * build up signed attributes, include contentType, signingTime, and + messageDigest by default */ + esd->signedAttribsCount = 0; + esd->signedAttribsSz = 0; + ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, pkcs7->contentType, + pkcs7->contentTypeSz, + contentTypeOid, sizeof(contentTypeOid), + messageDigestOid, sizeof(messageDigestOid), + signingTimeOid, sizeof(signingTimeOid), + signingTime, sizeof(signingTime)); + if (ret < 0) { + idx = ret; + goto out; + } + + if (esd->signedAttribsSz > 0) { + if (flatSignedAttribs == NULL) { + idx = MEMORY_E; + goto out; + } + + flatSignedAttribsSz = esd->signedAttribsSz; + FlattenAttributes(pkcs7, flatSignedAttribs, + esd->signedAttribs, esd->signedAttribsCount); + } else { + esd->signedAttribSetSz = 0; + } + } + + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + esd->signedAttribSet, esd->signedAttribSetSz); idx += esd->signedAttribSetSz; - XMEMCPY(output2 + idx, flatSignedAttribs, flatSignedAttribsSz); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + flatSignedAttribs, flatSignedAttribsSz); idx += flatSignedAttribsSz; } - XMEMCPY(output2 + idx, esd->digEncAlgoId, esd->digEncAlgoIdSz); + if (hashBuf == NULL && pkcs7->sidType != DEGENERATE_SID) { + /* Calculate the final hash and encrypt it. */ + WOLFSSL_MSG("Recreating signature with new hash"); + ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs, + flatSignedAttribsSz, esd); + if (ret < 0) { + idx = ret; + goto out; + } + } + + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + esd->digEncAlgoId, esd->digEncAlgoIdSz); idx += esd->digEncAlgoIdSz; - XMEMCPY(output2 + idx, esd->signerDigest, esd->signerDigestSz); + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + esd->signerDigest, esd->signerDigestSz); idx += esd->signerDigestSz; - XMEMCPY(output2 + idx, esd->encContentDigest, esd->encContentDigestSz); + + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + esd->encContentDigest, esd->encContentDigestSz); idx += esd->encContentDigestSz; #ifdef ASN_BER_TO_DER if (pkcs7->encodeStream) { + byte indefEnd[ASN_INDEF_END_SZ * 3]; + word32 localIdx = 0; + /* end of signedData seq */ - idx += SetIndefEnd(output2 + idx); + localIdx += SetIndefEnd(indefEnd + localIdx); /* end of outer content set */ - idx += SetIndefEnd(output2 + idx); + localIdx += SetIndefEnd(indefEnd + localIdx); /* end of outer content info seq */ - idx += SetIndefEnd(output2 + idx); + localIdx += SetIndefEnd(indefEnd + localIdx); + + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + indefEnd, localIdx); + idx += localIdx; } #endif @@ -2861,32 +3349,25 @@ int wc_PKCS7_EncodeSignedData_ex(PKCS7* pkcs7, const byte* hashBuf, word32* outputFootSz) { int ret; -#ifdef WOLFSSL_SMALL_STACK - ESD* esd; -#else - ESD esd[1]; -#endif /* other args checked in wc_PKCS7_EncodeSigned_ex */ - if (pkcs7 == NULL || outputFoot == NULL || outputFootSz == NULL) { + if (pkcs7 == NULL) { return BAD_FUNC_ARG; } -#ifdef WOLFSSL_SMALL_STACK - esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (esd == NULL) - return MEMORY_E; +#ifndef ASN_BER_TO_DER + if (outputFoot == NULL || outputFootSz == NULL) +#else + if (pkcs7->getContentCb == NULL && + (outputFoot == NULL || outputFootSz == NULL)) #endif + { + return BAD_FUNC_ARG; + } - XMEMSET(esd, 0, sizeof(ESD)); - - ret = PKCS7_EncodeSigned(pkcs7, esd, hashBuf, hashSz, + ret = PKCS7_EncodeSigned(pkcs7, hashBuf, hashSz, outputHead, outputHeadSz, outputFoot, outputFootSz); -#ifdef WOLFSSL_SMALL_STACK - XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; } @@ -2973,55 +3454,50 @@ int wc_PKCS7_SetDefaultSignedAttribs(PKCS7* pkcs7, word16 flag) int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) { int ret; - int hashSz; - enum wc_HashType hashType; - byte hashBuf[WC_MAX_DIGEST_SIZE]; -#ifdef WOLFSSL_SMALL_STACK - ESD* esd; -#else - ESD esd[1]; -#endif /* other args checked in wc_PKCS7_EncodeSigned_ex */ - if (pkcs7 == NULL || (pkcs7->contentSz > 0 && pkcs7->content == NULL)) { + if (pkcs7 == NULL || (pkcs7->contentSz > 0 && + #ifdef ASN_BER_TO_DER + (pkcs7->content == NULL && pkcs7->getContentCb == NULL)) + #else + pkcs7->content == NULL) + #endif + ) { return BAD_FUNC_ARG; } - /* get hash type and size, validate hashOID */ - hashType = wc_OidGetHash(pkcs7->hashOID); - hashSz = wc_HashGetDigestSize(hashType); - if (hashSz < 0) - return hashSz; + /* pre-calculate hash for ECC signatures */ + if (pkcs7->publicKeyOID == ECDSAk) { + int hashSz; + enum wc_HashType hashType; + byte hashBuf[WC_MAX_DIGEST_SIZE]; + wc_HashAlg hash; -#ifdef WOLFSSL_SMALL_STACK - esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (esd == NULL) - return MEMORY_E; -#endif + /* get hash type and size, validate hashOID */ + hashType = wc_OidGetHash(pkcs7->hashOID); + hashSz = wc_HashGetDigestSize(hashType); + if (hashSz < 0) + return hashSz; - XMEMSET(esd, 0, sizeof(ESD)); - esd->hashType = hashType; - - /* calculate hash for content */ - ret = wc_HashInit(&esd->hash, esd->hashType); - if (ret == 0) { - ret = wc_HashUpdate(&esd->hash, esd->hashType, - pkcs7->content, pkcs7->contentSz); + /* calculate hash for content */ + ret = wc_HashInit(&hash, hashType); if (ret == 0) { - ret = wc_HashFinal(&esd->hash, esd->hashType, hashBuf); + ret = wc_HashUpdate(&hash, hashType, + pkcs7->content, pkcs7->contentSz); + if (ret == 0) { + ret = wc_HashFinal(&hash, hashType, hashBuf); + } + wc_HashFree(&hash, hashType); + } + if (ret == 0) { + ret = PKCS7_EncodeSigned(pkcs7, hashBuf, hashSz, + output, &outputSz, NULL, NULL); } - wc_HashFree(&esd->hash, esd->hashType); } - - if (ret == 0) { - ret = PKCS7_EncodeSigned(pkcs7, esd, hashBuf, hashSz, - output, &outputSz, NULL, NULL); + else { + ret = PKCS7_EncodeSigned(pkcs7, NULL, 0, output, &outputSz, + NULL, NULL); } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; } @@ -7064,12 +7540,44 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, #endif /* !NO_RSA */ +/* abstraction for writing out PKCS7 bundle during creation + returns 0 on success + */ +int wc_PKCS7_WriteOut(PKCS7* pkcs7, byte* output, const byte* input, + word32 inputSz) +{ + int ret = 0; + +#ifdef ASN_BER_TO_DER + if (pkcs7->streamOutCb) { + ret = pkcs7->streamOutCb(pkcs7, input, inputSz); + /* sanity check on user provided ret value */ + if (ret < 0) { + WOLFSSL_MSG("Return value error from stream out callback"); + ret = BUFFER_E; + } + } + else +#endif + if (output) { + XMEMCPY(output, input, inputSz); + } + else { + WOLFSSL_MSG("No provided way to output bundle"); + ret = BUFFER_E; + } + + (void)pkcs7; + return ret; +} + /* encrypt content using encryptOID algo */ -static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, +static int wc_PKCS7_EncryptContent(PKCS7* pkcs7, int encryptOID, byte* key, + int keySz, byte* iv, int ivSz, byte* aad, word32 aadSz, byte* authTag, word32 authTagSz, byte* in, - int inSz, byte* out, int devId, void* heap) + int inSz, byte* out) { int ret; #ifndef NO_AES @@ -7083,10 +7591,23 @@ static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, Des des; Des3 des3; #endif + int devId = pkcs7->devId; + void* heap = pkcs7->heap; - if (key == NULL || iv == NULL || in == NULL || out == NULL) + if (key == NULL || iv == NULL) return BAD_FUNC_ARG; +#ifdef ASN_BER_TO_DER + if ((in == NULL && pkcs7->getContentCb == NULL) || + (out == NULL && pkcs7->streamOutCb == NULL)) { + WOLFSSL_MSG("No input or output set for encrypt"); + return BAD_FUNC_ARG; + } +#else + if (in == NULL || out == NULL) + return BAD_FUNC_ARG; +#endif + switch (encryptOID) { #ifndef NO_AES #ifdef HAVE_AES_CBC @@ -7121,11 +7642,8 @@ static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, if (ret == 0) { ret = wc_AesSetKey(aes, key, keySz, iv, AES_ENCRYPTION); if (ret == 0) { - ret = wc_AesCbcEncrypt(aes, out, in, inSz); - #ifdef WOLFSSL_ASYNC_CRYPT - /* async encrypt not available here, so block till done */ - ret = wc_AsyncWait(ret, &aes->asyncDev, WC_ASYNC_FLAG_NONE); - #endif + ret = wc_PKCS7_EncodeContentStream(pkcs7, NULL, aes, in, + inSz, out, WC_CIPHER_AES_CBC); } wc_AesFree(aes); } @@ -7158,12 +7676,32 @@ static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, if (ret == 0) { ret = wc_AesGcmSetKey(aes, key, keySz); if (ret == 0) { + #ifndef WOLFSSL_AESGCM_STREAM + if (pkcs7->encodeStream) { + WOLFSSL_MSG("Not AES-GCM stream support compiled in"); + ret = NOT_COMPILED_IN; + } ret = wc_AesGcmEncrypt(aes, out, in, inSz, iv, ivSz, authTag, authTagSz, aad, aadSz); #ifdef WOLFSSL_ASYNC_CRYPT /* async encrypt not available here, so block till done */ ret = wc_AsyncWait(ret, &aes->asyncDev, WC_ASYNC_FLAG_NONE); #endif + #else + ret = wc_AesGcmEncryptInit(aes, key, keySz, iv, ivSz); + if (ret == 0) { + ret = wc_AesGcmEncryptUpdate(aes, NULL, NULL, 0, aad, + aadSz); + } + if (ret == 0) { + ret = wc_PKCS7_EncodeContentStream(pkcs7, NULL, aes, in, + inSz, out, WC_CIPHER_AES_GCM); + } + + if (ret == 0) { + ret = wc_AesGcmEncryptFinal(aes, authTag, authTagSz); + } + #endif } wc_AesFree(aes); } @@ -7188,6 +7726,11 @@ static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, if (authTag == NULL) return BAD_FUNC_ARG; + if (pkcs7->encodeStream) { + WOLFSSL_MSG("Streaming encoding not supported with AES-CCM"); + return BAD_FUNC_ARG; + } + #ifdef WOLFSSL_SMALL_STACK if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL, DYNAMIC_TYPE_AES)) == NULL) @@ -7218,6 +7761,11 @@ static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE) return BAD_FUNC_ARG; + if (pkcs7->encodeStream) { + WOLFSSL_MSG("Streaming encoding not supported with DES3"); + return BAD_FUNC_ARG; + } + ret = wc_Des_SetKey(&des, key, iv, DES_ENCRYPTION); if (ret == 0) ret = wc_Des_CbcEncrypt(&des, out, in, inSz); @@ -7228,6 +7776,11 @@ static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE) return BAD_FUNC_ARG; + if (pkcs7->encodeStream) { + WOLFSSL_MSG("Streaming encoding not supported with DES3"); + return BAD_FUNC_ARG; + } + ret = wc_Des3Init(&des3, heap, devId); if (ret == 0) { ret = wc_Des3_SetKey(&des3, key, iv, DES_ENCRYPTION); @@ -7776,17 +8329,16 @@ static int wc_PKCS7_PwriKek_KeyWrap(PKCS7* pkcs7, const byte* kek, word32 kekSz, if (ret == 0) { /* encrypt, normal */ - ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, (byte*)iv, - ivSz, NULL, 0, NULL, 0, out, outLen, out, - pkcs7->devId, pkcs7->heap); + ret = wc_PKCS7_EncryptContent(pkcs7, algID, (byte*)kek, kekSz, (byte*)iv, + ivSz, NULL, 0, NULL, 0, out, outLen, out); } if (ret == 0) { /* encrypt again, using last ciphertext block as IV */ lastBlock = out + (((outLen / blockSz) - 1) * blockSz); - ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, lastBlock, + ret = wc_PKCS7_EncryptContent(pkcs7, algID, (byte*)kek, kekSz, lastBlock, blockSz, NULL, 0, NULL, 0, out, - outLen, out, pkcs7->devId, pkcs7->heap); + outLen, out); } if (ret == 0) { @@ -8474,8 +9026,8 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) WC_RNG rng; int blockSz, blockKeySz; - byte* plain; - byte* encryptedContent; + byte* plain = NULL; + byte* encryptedContent = NULL; Pkcs7EncodedRecip* tmpRecip = NULL; int recipSz, recipSetSz; @@ -8489,12 +9041,27 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) byte tmpIv[MAX_CONTENT_IV_SIZE]; byte ivOctetString[MAX_OCTET_STR_SZ]; byte encContentOctet[MAX_OCTET_STR_SZ]; +#ifdef ASN_BER_TO_DER + word32 streamSz = 0; +#endif - if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0) + if (pkcs7 == NULL + #ifndef ASN_BER_TO_DER + || pkcs7->content == NULL + #endif + || pkcs7->contentSz == 0) { return BAD_FUNC_ARG; + } +#ifndef ASN_BER_TO_DER if (output == NULL || outputSz == 0) return BAD_FUNC_ARG; +#else + /* if both output and callback are not set then error out */ + if ((output == NULL || outputSz == 0) && (pkcs7->streamOutCb == NULL)) { + return BAD_FUNC_ARG; + } +#endif blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); if (blockKeySz < 0) @@ -8603,26 +9170,37 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) encryptedOutSz = pkcs7->contentSz + padSz; - plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - if (plain == NULL) { - wc_PKCS7_FreeEncodedRecipientSet(pkcs7); - return MEMORY_E; +#ifdef ASN_BER_TO_DER + if (pkcs7->getContentCb == NULL) +#endif + { + plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (plain == NULL) { + wc_PKCS7_FreeEncodedRecipientSet(pkcs7); + return MEMORY_E; + } + + ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain, + encryptedOutSz, blockSz); + if (ret < 0) { + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_PKCS7_FreeEncodedRecipientSet(pkcs7); + return ret; + } + } - ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain, - encryptedOutSz, blockSz); - if (ret < 0) { - XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - wc_PKCS7_FreeEncodedRecipientSet(pkcs7); - return ret; - } - - encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, - DYNAMIC_TYPE_PKCS7); - if (encryptedContent == NULL) { - XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - wc_PKCS7_FreeEncodedRecipientSet(pkcs7); - return MEMORY_E; +#ifdef ASN_BER_TO_DER + if (pkcs7->streamOutCb == NULL) +#endif + { + encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedContent == NULL) { + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_PKCS7_FreeEncodedRecipientSet(pkcs7); + return MEMORY_E; + } } /* put together IV OCTET STRING */ @@ -8640,19 +9218,6 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) return BAD_FUNC_ARG; } - /* encrypt content */ - ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek, - pkcs7->cekSz, tmpIv, blockSz, NULL, 0, NULL, 0, plain, - encryptedOutSz, encryptedContent, - pkcs7->devId, pkcs7->heap); - - if (ret != 0) { - XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - wc_PKCS7_FreeEncodedRecipientSet(pkcs7); - return ret; - } - encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz, encContentOctet, pkcs7->encodeStream); encContentSeqSz = SetSequenceEx(contentTypeSz + contentEncAlgoSz + @@ -8668,7 +9233,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) /* EnvelopedData */ #ifdef ASN_BER_TO_DER if (pkcs7->encodeStream) { - word32 streamSz = 0, tmpIdx = 0; + word32 tmpIdx = 0; /* account for ending of encContentOctet */ totalSz += ASN_INDEF_END_SZ; @@ -8679,6 +9244,18 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) /* account for asn1 syntax around octet strings */ StreamOctetString(NULL, encryptedOutSz, NULL, &streamSz, &tmpIdx); totalSz += (streamSz - encryptedOutSz); + + /* resize encrytped content buffer */ + if (encryptedContent != NULL) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + encryptedContent = (byte*)XMALLOC(streamSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedContent == NULL) { + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_PKCS7_FreeEncodedRecipientSet(pkcs7); + return MEMORY_E; + } + } } #endif envDataSeqSz = SetSequenceEx(totalSz, envDataSeq, pkcs7->encodeStream); @@ -8711,7 +9288,11 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) #endif } - if (totalSz > (int)outputSz) { + if ((totalSz > (int)outputSz) + #ifdef ASN_BER_TO_DER + && (pkcs7->streamOutCb == NULL) + #endif + ) { WOLFSSL_MSG("Pkcs7_encrypt output buffer too small"); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -8719,75 +9300,121 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) return BUFFER_E; } + /* begin writing out PKCS7 bundle */ if (pkcs7->contentOID != FIRMWARE_PKG_DATA) { - XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + contentInfoSeq, contentInfoSeqSz); idx += contentInfoSeqSz; - XMEMCPY(output + idx, outerContentType, outerContentTypeSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + outerContentType, outerContentTypeSz); idx += outerContentTypeSz; - XMEMCPY(output + idx, outerContent, outerContentSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + outerContent, outerContentSz); idx += outerContentSz; } - XMEMCPY(output + idx, envDataSeq, envDataSeqSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + envDataSeq, envDataSeqSz); idx += envDataSeqSz; - XMEMCPY(output + idx, ver, verSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + ver, verSz); idx += verSz; - XMEMCPY(output + idx, recipSet, recipSetSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + recipSet, recipSetSz); idx += recipSetSz; /* copy in recipients from list */ tmpRecip = pkcs7->recipList; while (tmpRecip != NULL) { - XMEMCPY(output + idx, tmpRecip->recip, tmpRecip->recipSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + tmpRecip->recip, tmpRecip->recipSz); idx += tmpRecip->recipSz; tmpRecip = tmpRecip->next; } wc_PKCS7_FreeEncodedRecipientSet(pkcs7); - XMEMCPY(output + idx, encContentSeq, encContentSeqSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + encContentSeq, encContentSeqSz); idx += encContentSeqSz; - XMEMCPY(output + idx, contentType, contentTypeSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + contentType, contentTypeSz); idx += contentTypeSz; - XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + contentEncAlgo, contentEncAlgoSz); idx += contentEncAlgoSz; - XMEMCPY(output + idx, ivOctetString, ivOctetStringSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + ivOctetString, ivOctetStringSz); idx += ivOctetStringSz; - XMEMCPY(output + idx, tmpIv, blockSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + tmpIv, blockSz); idx += blockSz; - XMEMCPY(output + idx, encContentOctet, encContentOctetSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + encContentOctet, encContentOctetSz); idx += encContentOctetSz; + /* encrypt content */ + ret = wc_PKCS7_EncryptContent(pkcs7, pkcs7->encryptOID, pkcs7->cek, + pkcs7->cekSz, tmpIv, blockSz, NULL, 0, NULL, 0, plain, + encryptedOutSz, encryptedContent); + if (ret != 0) { + if (encryptedContent != NULL) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + + if (plain != NULL) { + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + + wc_PKCS7_FreeEncodedRecipientSet(pkcs7); + return ret; + } + #ifdef ASN_BER_TO_DER /* stream the content (octet string with multiple octet elements) */ if (pkcs7->encodeStream) { - if (StreamOctetString(encryptedContent, encryptedOutSz, output, - &outputSz, (word32*)&idx) != 0) { - return BUFFER_E; + byte indefEnd[ASN_INDEF_END_SZ * 5]; + word32 localIdx = 0; + + /* advance index past encrypted content */ + if (!pkcs7->streamOutCb) { + wc_PKCS7_WriteOut(pkcs7, (output)? output + idx : NULL, + encryptedContent, streamSz); } + idx += streamSz; /* end of encrypted content */ - idx += SetIndefEnd(output + idx); + localIdx += SetIndefEnd(indefEnd + localIdx); /* end of encrypted content info */ - idx += SetIndefEnd(output + idx); + localIdx += SetIndefEnd(indefEnd + localIdx); /* end of Enveloped Data seq */ - idx += SetIndefEnd(output + idx); + localIdx += SetIndefEnd(indefEnd + localIdx); /* end of outer content set */ - idx += SetIndefEnd(output + idx); + localIdx += SetIndefEnd(indefEnd + localIdx); /* end of outer content info seq */ - idx += SetIndefEnd(output + idx); + localIdx += SetIndefEnd(indefEnd + localIdx); + + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + indefEnd, localIdx); + idx += localIdx; } else #endif { - XMEMCPY(output + idx, encryptedContent, encryptedOutSz); + wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, + encryptedContent, encryptedOutSz); idx += encryptedOutSz; } - XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (plain != NULL) { + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + + if (encryptedContent != NULL) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } return idx; } @@ -11719,10 +12346,9 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, } /* encrypt content */ - ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek, + ret = wc_PKCS7_EncryptContent(pkcs7, pkcs7->encryptOID, pkcs7->cek, pkcs7->cekSz, nonce, nonceSz, aadBuffer, aadBufferSz, authTag, - sizeof(authTag), plain, encryptedOutSz, encryptedContent, - pkcs7->devId, pkcs7->heap); + sizeof(authTag), plain, encryptedOutSz, encryptedContent); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); plain = NULL; @@ -12659,10 +13285,9 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) return ret; } - ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->encryptionKey, + ret = wc_PKCS7_EncryptContent(pkcs7, pkcs7->encryptOID, pkcs7->encryptionKey, pkcs7->encryptionKeySz, tmpIv, blockSz, NULL, 0, NULL, 0, - plain, encryptedOutSz, encryptedContent, - pkcs7->devId, pkcs7->heap); + plain, encryptedOutSz, encryptedContent); if (ret != 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -13228,16 +13853,22 @@ int wc_PKCS7_SetDecodeEncryptedCtx(PKCS7* pkcs7, void* ctx) /* set stream mode for encoding and signing * returns 0 on success */ -int wc_PKCS7_SetStreamMode(PKCS7* pkcs7, byte flag) +int wc_PKCS7_SetStreamMode(PKCS7* pkcs7, byte flag, + CallbackGetContent getContentCb, + CallbackStreamOut streamOutCb) { if (pkcs7 == NULL) { return BAD_FUNC_ARG; } #ifdef ASN_BER_TO_DER pkcs7->encodeStream = flag; + pkcs7->getContentCb = getContentCb; + pkcs7->streamOutCb = streamOutCb; return 0; #else (void)flag; + (void)getContentCb; + (void)streamOutCb; return NOT_COMPILED_IN; #endif } diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index f397a8f26..d87ebaa79 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -224,6 +224,11 @@ typedef int (*CallbackWrapCEK)(PKCS7* pkcs7, byte* cek, word32 cekSz, byte* out, word32 outSz, int keyWrapAlgo, int type, int dir); +/* Callbacks for supporting different stream cases */ +typedef int (*CallbackGetContent)(PKCS7* pkcs7, byte** content); +typedef int (*CallbackStreamOut)(PKCS7* pkcs7, const byte* output, + word32 outputSz); + #if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA) /* RSA sign raw digest callback, user builds DigestInfo */ typedef int (*CallbackRsaSignRawDigest)(PKCS7* pkcs7, byte* digest, @@ -247,6 +252,8 @@ struct PKCS7 { #ifdef ASN_BER_TO_DER byte* der; /* DER encoded version of message */ word32 derSz; + CallbackGetContent getContentCb; + CallbackStreamOut streamOutCb; #endif byte encodeStream:1; /* use BER when encoding */ byte noCerts:1; /* if certificates should be added into bundle @@ -498,7 +505,11 @@ WOLFSSL_API int wc_PKCS7_SetDecodeEncryptedCb(PKCS7* pkcs7, WOLFSSL_API int wc_PKCS7_SetDecodeEncryptedCtx(PKCS7* pkcs7, void* ctx); #endif /* NO_PKCS7_ENCRYPTED_DATA */ -WOLFSSL_API int wc_PKCS7_SetStreamMode(PKCS7* pkcs7, byte flag); +/* stream and certs */ +WOLFSSL_LOCAL int wc_PKCS7_WriteOut(PKCS7* pkcs7, byte* output, + const byte* input, word32 inputSz); +WOLFSSL_API int wc_PKCS7_SetStreamMode(PKCS7* pkcs7, byte flag, + CallbackGetContent getContentCb, CallbackStreamOut streamOutCb); WOLFSSL_API int wc_PKCS7_GetStreamMode(PKCS7* pkcs7); WOLFSSL_API int wc_PKCS7_SetNoCerts(PKCS7* pkcs7, byte flag); WOLFSSL_API int wc_PKCS7_GetNoCerts(PKCS7* pkcs7); From 9eac8cb41f6ac178428a9c9b3fb5dcddf29142ae Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Mon, 26 Feb 2024 09:44:23 -0700 Subject: [PATCH 2/9] add a test case --- tests/api.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 7 deletions(-) diff --git a/tests/api.c b/tests/api.c index 1af455a75..5fb4a6a45 100644 --- a/tests/api.c +++ b/tests/api.c @@ -26871,6 +26871,38 @@ static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz, } #endif +#if defined(HAVE_PKCS7) && defined(ASN_BER_TO_DER) +static byte encodeSignedDataStreamOut[FOURK_BUF*3] = {0}; +static int encodeSignedDataStreamIdx = 0; +static word32 encodeSignedDataStreamOutIdx = 0; + + +/* content is 8k of partially created bundle */ +static int GetContentCB(PKCS7* pkcs7, byte** content) +{ + int ret = 0; + + if (encodeSignedDataStreamOutIdx < pkcs7->contentSz) { + ret = (pkcs7->contentSz > encodeSignedDataStreamOutIdx + FOURK_BUF)? + FOURK_BUF : pkcs7->contentSz - encodeSignedDataStreamOutIdx; + *content = encodeSignedDataStreamOut + encodeSignedDataStreamOutIdx; + encodeSignedDataStreamOutIdx += ret; + } + + (void)pkcs7; + return ret; +} + +static int StreamOutputCB(PKCS7* pkcs7, const byte* output, word32 outputSz) +{ + XMEMCPY(encodeSignedDataStreamOut + encodeSignedDataStreamIdx, output, + outputSz); + encodeSignedDataStreamIdx += outputSz; + (void)pkcs7; + return 0; +} +#endif + /* * Testing wc_PKCS7_EncodeSignedData() @@ -27033,6 +27065,39 @@ static int test_wc_PKCS7_EncodeSignedData(void) /* use exact signed buffer size since BER encoded */ ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, signedSz), 0); + wc_PKCS7_Free(pkcs7); + + /* now try with using callbacks for IO */ + ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); + ExpectIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); + + ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); + + if (pkcs7 != NULL) { + pkcs7->contentSz = FOURK_BUF*2; + pkcs7->privateKey = key; + pkcs7->privateKeySz = (word32)sizeof(key); + pkcs7->encryptOID = RSAk; + #ifdef NO_SHA + pkcs7->hashOID = SHA256h; + #else + pkcs7->hashOID = SHAh; + #endif + pkcs7->rng = &rng; + } + ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1, GetContentCB, + StreamOutputCB), 0); + + ExpectIntGT(signedSz = wc_PKCS7_EncodeSignedData(pkcs7, NULL, 0), 0); + wc_PKCS7_Free(pkcs7); + pkcs7 = NULL; + + ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); + ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + + /* use exact signed buffer size since BER encoded */ + ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, encodeSignedDataStreamOut, + signedSz), 0); } #endif @@ -28270,7 +28335,7 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void) testSz = (int)sizeof(testVectors)/(int)sizeof(pkcs7EnvelopedVector); for (i = 0; i < testSz; i++) { #ifdef ASN_BER_TO_DER - /* test setting stream mode */ + /* test setting stream mode, the first one using IO callbacks */ ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (testVectors + i)->cert, (word32)(testVectors + i)->certSz), 0); if (pkcs7 != NULL) { @@ -28278,7 +28343,8 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void) pkcs7->rng = &rng; #endif - pkcs7->content = (byte*)(testVectors + i)->content; + if (i != 0) + pkcs7->content = (byte*)(testVectors + i)->content; pkcs7->contentSz = (testVectors + i)->contentSz; pkcs7->contentOID = (testVectors + i)->contentOID; pkcs7->encryptOID = (testVectors + i)->encryptOID; @@ -28287,10 +28353,17 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void) pkcs7->privateKey = (testVectors + i)->privateKey; pkcs7->privateKeySz = (testVectors + i)->privateKeySz; } - ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1, NULL, NULL), 0); - encodedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, output, - (word32)sizeof(output)); + if (i == 0) { + ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1, GetContentCB, + StreamOutputCB), 0); + encodedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, NULL, 0); + } + else { + ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1, NULL, NULL), 0); + encodedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, output, + (word32)sizeof(output)); + } switch ((testVectors + i)->encryptOID) { #ifndef NO_DES3 @@ -28321,8 +28394,15 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void) } if (encodedSz > 0) { - decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, output, - (word32)encodedSz, decoded, (word32)sizeof(decoded)); + if (i == 0) { + decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, + encodeSignedDataStreamOut, (word32)encodedSz, decoded, + (word32)sizeof(decoded)); + } + else { + decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, output, + (word32)encodedSz, decoded, (word32)sizeof(decoded)); + } ExpectIntGE(decodedSz, 0); /* Verify the size of each buffer. */ ExpectIntEQ((word32)sizeof(input)/sizeof(char), decodedSz); From c32d9c826c1c1c8a05cf45774327f278a93d8cf6 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Fri, 1 Mar 2024 21:14:15 +0700 Subject: [PATCH 3/9] fix for check on hash with ECDSAk case --- wolfcrypt/src/pkcs7.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 55b56fda0..9414f8d06 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -2758,8 +2758,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, * hash must be known in order to create the surrounding ASN1 syntax * properly before writing out the content and generating the hash on the * fly and then creating the signature */ - if (pkcs7->getContentCb != NULL && hashBuf == NULL && - pkcs7->publicKeyOID == ECDSAk) { + if (hashBuf == NULL && pkcs7->publicKeyOID == ECDSAk) { WOLFSSL_MSG("Pre-calculated content hash is needed in this case"); return BAD_FUNC_ARG; } From fbf1b783da5832393f8aeff0d4b94ac2dc514b21 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Fri, 1 Mar 2024 21:39:27 +0700 Subject: [PATCH 4/9] initialize value to resolve warning --- wolfcrypt/src/pkcs7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 9414f8d06..11f0fa7d8 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -2728,7 +2728,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, word32 flatSignedAttribsSz = 0; #ifdef WOLFSSL_SMALL_STACK - ESD* esd; + ESD* esd = NULL; #else ESD esd[1]; #endif From 66f419bd1891119035939a5a34377f81b3b05c6d Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Mon, 4 Mar 2024 06:00:07 -0700 Subject: [PATCH 5/9] add user ctx to stream IO callbacks --- tests/api.c | 52 +++++++++++++++++++++++---------------- wolfcrypt/src/pkcs7.c | 8 +++--- wolfssl/wolfcrypt/pkcs7.h | 7 +++--- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/tests/api.c b/tests/api.c index 5fb4a6a45..fbaab39c9 100644 --- a/tests/api.c +++ b/tests/api.c @@ -26872,32 +26872,37 @@ static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz, #endif #if defined(HAVE_PKCS7) && defined(ASN_BER_TO_DER) -static byte encodeSignedDataStreamOut[FOURK_BUF*3] = {0}; -static int encodeSignedDataStreamIdx = 0; -static word32 encodeSignedDataStreamOutIdx = 0; +typedef struct encodeSignedDataStream { + byte out[FOURK_BUF*3]; + int idx; + word32 outIdx; +} encodeSignedDataStream; /* content is 8k of partially created bundle */ -static int GetContentCB(PKCS7* pkcs7, byte** content) +static int GetContentCB(PKCS7* pkcs7, byte** content, void* ctx) { int ret = 0; + encodeSignedDataStream* strm = (encodeSignedDataStream*)ctx; - if (encodeSignedDataStreamOutIdx < pkcs7->contentSz) { - ret = (pkcs7->contentSz > encodeSignedDataStreamOutIdx + FOURK_BUF)? - FOURK_BUF : pkcs7->contentSz - encodeSignedDataStreamOutIdx; - *content = encodeSignedDataStreamOut + encodeSignedDataStreamOutIdx; - encodeSignedDataStreamOutIdx += ret; + if (strm->outIdx < pkcs7->contentSz) { + ret = (pkcs7->contentSz > strm->outIdx + FOURK_BUF)? + FOURK_BUF : pkcs7->contentSz - strm->outIdx; + *content = strm->out + strm->outIdx; + strm->outIdx += ret; } (void)pkcs7; return ret; } -static int StreamOutputCB(PKCS7* pkcs7, const byte* output, word32 outputSz) +static int StreamOutputCB(PKCS7* pkcs7, const byte* output, word32 outputSz, + void* ctx) { - XMEMCPY(encodeSignedDataStreamOut + encodeSignedDataStreamIdx, output, - outputSz); - encodeSignedDataStreamIdx += outputSz; + encodeSignedDataStream* strm = (encodeSignedDataStream*)ctx; + + XMEMCPY(strm->out + strm->idx, output, outputSz); + strm->idx += outputSz; (void)pkcs7; return 0; } @@ -27031,6 +27036,7 @@ static int test_wc_PKCS7_EncodeSignedData(void) /* reinitialize and test setting stream mode */ { int signedSz; + encodeSignedDataStream strm; ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); ExpectIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); @@ -27051,8 +27057,9 @@ static int test_wc_PKCS7_EncodeSignedData(void) pkcs7->rng = &rng; } ExpectIntEQ(wc_PKCS7_GetStreamMode(pkcs7), 0); - ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1, NULL, NULL), 0); - ExpectIntEQ(wc_PKCS7_SetStreamMode(NULL, 1, NULL, NULL), BAD_FUNC_ARG); + ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1, NULL, NULL, NULL), 0); + ExpectIntEQ(wc_PKCS7_SetStreamMode(NULL, 1, NULL, NULL, NULL), + BAD_FUNC_ARG); ExpectIntEQ(wc_PKCS7_GetStreamMode(pkcs7), 1); ExpectIntGT(signedSz = wc_PKCS7_EncodeSignedData(pkcs7, output, @@ -27085,8 +27092,9 @@ static int test_wc_PKCS7_EncodeSignedData(void) #endif pkcs7->rng = &rng; } + XMEMSET(&strm, 0, sizeof(strm)); ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1, GetContentCB, - StreamOutputCB), 0); + StreamOutputCB, (void*)&strm), 0); ExpectIntGT(signedSz = wc_PKCS7_EncodeSignedData(pkcs7, NULL, 0), 0); wc_PKCS7_Free(pkcs7); @@ -27096,8 +27104,7 @@ static int test_wc_PKCS7_EncodeSignedData(void) ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); /* use exact signed buffer size since BER encoded */ - ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, encodeSignedDataStreamOut, - signedSz), 0); + ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, strm.out, signedSz), 0); } #endif @@ -28335,6 +28342,8 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void) testSz = (int)sizeof(testVectors)/(int)sizeof(pkcs7EnvelopedVector); for (i = 0; i < testSz; i++) { #ifdef ASN_BER_TO_DER + encodeSignedDataStream strm; + /* test setting stream mode, the first one using IO callbacks */ ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (testVectors + i)->cert, (word32)(testVectors + i)->certSz), 0); @@ -28355,12 +28364,13 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void) } if (i == 0) { + XMEMSET(&strm, 0, sizeof(strm)); ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1, GetContentCB, - StreamOutputCB), 0); + StreamOutputCB, (void*)&strm), 0); encodedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, NULL, 0); } else { - ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1, NULL, NULL), 0); + ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1, NULL, NULL, NULL), 0); encodedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, output, (word32)sizeof(output)); } @@ -28396,7 +28406,7 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void) if (encodedSz > 0) { if (i == 0) { decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, - encodeSignedDataStreamOut, (word32)encodedSz, decoded, + strm.out, (word32)encodedSz, decoded, (word32)sizeof(decoded)); } else { diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 11f0fa7d8..8b1141976 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -2497,7 +2497,7 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, #ifdef ASN_BER_TO_DER if (pkcs7->getContentCb) { contentDataRead = pkcs7->getContentCb(pkcs7, - &buf); + &buf, pkcs7->streamCtx); } else #endif @@ -7549,7 +7549,7 @@ int wc_PKCS7_WriteOut(PKCS7* pkcs7, byte* output, const byte* input, #ifdef ASN_BER_TO_DER if (pkcs7->streamOutCb) { - ret = pkcs7->streamOutCb(pkcs7, input, inputSz); + ret = pkcs7->streamOutCb(pkcs7, input, inputSz, pkcs7->streamCtx); /* sanity check on user provided ret value */ if (ret < 0) { WOLFSSL_MSG("Return value error from stream out callback"); @@ -13854,7 +13854,7 @@ int wc_PKCS7_SetDecodeEncryptedCtx(PKCS7* pkcs7, void* ctx) * returns 0 on success */ int wc_PKCS7_SetStreamMode(PKCS7* pkcs7, byte flag, CallbackGetContent getContentCb, - CallbackStreamOut streamOutCb) + CallbackStreamOut streamOutCb, void* ctx) { if (pkcs7 == NULL) { return BAD_FUNC_ARG; @@ -13863,11 +13863,13 @@ int wc_PKCS7_SetStreamMode(PKCS7* pkcs7, byte flag, pkcs7->encodeStream = flag; pkcs7->getContentCb = getContentCb; pkcs7->streamOutCb = streamOutCb; + pkcs7->streamCtx = ctx; return 0; #else (void)flag; (void)getContentCb; (void)streamOutCb; + (void)ctx; return NOT_COMPILED_IN; #endif } diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index d87ebaa79..405771239 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -225,9 +225,9 @@ typedef int (*CallbackWrapCEK)(PKCS7* pkcs7, byte* cek, word32 cekSz, int keyWrapAlgo, int type, int dir); /* Callbacks for supporting different stream cases */ -typedef int (*CallbackGetContent)(PKCS7* pkcs7, byte** content); +typedef int (*CallbackGetContent)(PKCS7* pkcs7, byte** content, void* ctx); typedef int (*CallbackStreamOut)(PKCS7* pkcs7, const byte* output, - word32 outputSz); + word32 outputSz, void* ctx); #if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA) /* RSA sign raw digest callback, user builds DigestInfo */ @@ -254,6 +254,7 @@ struct PKCS7 { word32 derSz; CallbackGetContent getContentCb; CallbackStreamOut streamOutCb; + void* streamCtx; /* passed to getcontentCb and streamOutCb */ #endif byte encodeStream:1; /* use BER when encoding */ byte noCerts:1; /* if certificates should be added into bundle @@ -509,7 +510,7 @@ WOLFSSL_API int wc_PKCS7_SetDecodeEncryptedCtx(PKCS7* pkcs7, void* ctx); WOLFSSL_LOCAL int wc_PKCS7_WriteOut(PKCS7* pkcs7, byte* output, const byte* input, word32 inputSz); WOLFSSL_API int wc_PKCS7_SetStreamMode(PKCS7* pkcs7, byte flag, - CallbackGetContent getContentCb, CallbackStreamOut streamOutCb); + CallbackGetContent getContentCb, CallbackStreamOut streamOutCb, void* ctx); WOLFSSL_API int wc_PKCS7_GetStreamMode(PKCS7* pkcs7); WOLFSSL_API int wc_PKCS7_SetNoCerts(PKCS7* pkcs7, byte flag); WOLFSSL_API int wc_PKCS7_GetNoCerts(PKCS7* pkcs7); From f05e47bc09a20487451f36d991c03cac196c4712 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Mon, 4 Mar 2024 07:05:07 -0700 Subject: [PATCH 6/9] length of characters and extra sanity check on input --- wolfcrypt/src/pkcs7.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 8b1141976..b935028bd 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -2611,7 +2611,8 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, case WC_CIPHER_NONE: XMEMCPY(encContentOut, contentData, idx); if (esd && esd->contentDigestSet != 1) { - ret = wc_HashUpdate(&esd->hash, esd->hashType, contentData, idx); + ret = wc_HashUpdate(&esd->hash, esd->hashType, contentData, + idx); } break; @@ -2645,7 +2646,8 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, encContentOut, idx); if (cipherType == WC_CIPHER_NONE && esd && esd->contentDigestSet != 1) { - ret = wc_HashFinal(&esd->hash, esd->hashType, esd->contentDigest + 2); + ret = wc_HashFinal(&esd->hash, esd->hashType, + esd->contentDigest + 2); wc_HashFree(&esd->hash, esd->hashType); } @@ -2661,9 +2663,11 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, if (esd && esd->contentDigestSet != 1) { ret = wc_HashInit(&esd->hash, esd->hashType); if (ret == 0) - ret = wc_HashUpdate(&esd->hash, esd->hashType, in, inSz); + ret = wc_HashUpdate(&esd->hash, esd->hashType, in, + inSz); if (ret == 0) - ret = wc_HashFinal(&esd->hash, esd->hashType, esd->contentDigest + 2); + ret = wc_HashFinal(&esd->hash, esd->hashType, + esd->contentDigest + 2); wc_HashFree(&esd->hash, esd->hashType); } break; @@ -7547,6 +7551,14 @@ int wc_PKCS7_WriteOut(PKCS7* pkcs7, byte* output, const byte* input, { int ret = 0; + if (inputSz == 0) + return 0; + + if (input == NULL) { + WOLFSSL_MSG("Internal error, trying to write out NULL buffer"); + return -1; + } + #ifdef ASN_BER_TO_DER if (pkcs7->streamOutCb) { ret = pkcs7->streamOutCb(pkcs7, input, inputSz, pkcs7->streamCtx); @@ -8328,15 +8340,16 @@ static int wc_PKCS7_PwriKek_KeyWrap(PKCS7* pkcs7, const byte* kek, word32 kekSz, if (ret == 0) { /* encrypt, normal */ - ret = wc_PKCS7_EncryptContent(pkcs7, algID, (byte*)kek, kekSz, (byte*)iv, - ivSz, NULL, 0, NULL, 0, out, outLen, out); + ret = wc_PKCS7_EncryptContent(pkcs7, algID, (byte*)kek, kekSz, + (byte*)iv, ivSz, NULL, 0, NULL, 0, out, + outLen, out); } if (ret == 0) { /* encrypt again, using last ciphertext block as IV */ lastBlock = out + (((outLen / blockSz) - 1) * blockSz); - ret = wc_PKCS7_EncryptContent(pkcs7, algID, (byte*)kek, kekSz, lastBlock, - blockSz, NULL, 0, NULL, 0, out, + ret = wc_PKCS7_EncryptContent(pkcs7, algID, (byte*)kek, kekSz, + lastBlock, blockSz, NULL, 0, NULL, 0, out, outLen, out); } @@ -13284,9 +13297,9 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) return ret; } - ret = wc_PKCS7_EncryptContent(pkcs7, pkcs7->encryptOID, pkcs7->encryptionKey, - pkcs7->encryptionKeySz, tmpIv, blockSz, NULL, 0, NULL, 0, - plain, encryptedOutSz, encryptedContent); + ret = wc_PKCS7_EncryptContent(pkcs7, pkcs7->encryptOID, + pkcs7->encryptionKey, pkcs7->encryptionKeySz, tmpIv, blockSz, NULL, + 0, NULL, 0, plain, encryptedOutSz, encryptedContent); if (ret != 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); From 089e57371f4bae0c92b5f5d3390ad65bf75c5ec3 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Mon, 4 Mar 2024 08:10:41 -0700 Subject: [PATCH 7/9] remove a hard tab --- wolfcrypt/src/pkcs7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index b935028bd..73c17235a 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -13867,7 +13867,7 @@ int wc_PKCS7_SetDecodeEncryptedCtx(PKCS7* pkcs7, void* ctx) * returns 0 on success */ int wc_PKCS7_SetStreamMode(PKCS7* pkcs7, byte flag, CallbackGetContent getContentCb, - CallbackStreamOut streamOutCb, void* ctx) + CallbackStreamOut streamOutCb, void* ctx) { if (pkcs7 == NULL) { return BAD_FUNC_ARG; From a07d92d3d39a8e77d3b9d8c66a230223906a1e03 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Thu, 7 Mar 2024 21:30:42 +0700 Subject: [PATCH 8/9] refactoring and fixes for new PKCS7 stream code --- wolfcrypt/src/pkcs7.c | 176 +++++++++++++++++++----------------------- 1 file changed, 80 insertions(+), 96 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 73c17235a..9e418963b 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -2430,6 +2430,72 @@ static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, #define BER_OCTET_LENGTH 4096 #endif +/** + * This helper function encodes a chunk of content stream and writes it out. + * + * @param pkcs7 Pointer to a PKCS7 structure. + * @param cipherType The type of cipher to use for encryption. + * @param aes Optional pointer to an Aes structure for AES encryption. + * @param encContentOut Buffer to hold the encrypted content. + * @param contentData Buffer holding the content to be encrypted. + * @param contentDataSz Size of the content to be encrypted. + * @param out Buffer to hold the output data. + * @param outIdx Pointer to an index into the output buffer. + * @param esd Pointer to an ESD structure for digest calculation. + * @return Returns 0 on success, and a negative value on failure. + */ +static int wc_PKCS7_EncodeContentStreamHelper(PKCS7* pkcs7, int cipherType, + Aes* aes, byte* encContentOut, byte* contentData, int contentDataSz, + byte* out, word32* outIdx, ESD* esd) +{ + int ret = BAD_FUNC_ARG; + byte encContentOutOct[MAX_OCTET_STR_SZ]; + word32 encContentOutOctSz = 0; + + switch (cipherType) { + case WC_CIPHER_NONE: + XMEMCPY(encContentOut, contentData, contentDataSz); + if (esd && esd->contentDigestSet != 1) { + ret = wc_HashUpdate(&esd->hash, esd->hashType, + contentData, contentDataSz); + } + break; + + #ifndef NO_AES + case WC_CIPHER_AES_CBC: + ret = wc_AesCbcEncrypt(aes, encContentOut, + contentData, contentDataSz); + break; + #endif + + #ifdef WOLFSSL_AESGCM_STREAM + case WC_CIPHER_AES_GCM: + ret = wc_AesGcmEncryptUpdate(aes, encContentOut, + contentData, contentDataSz, NULL, 0); + break; + #endif + } + + #ifdef WOLFSSL_ASYNC_CRYPT + /* async encrypt not available here, so block till done */ + if (ret == WC_PENDING_E && cipherType != WC_CIPHER_NONE) { + ret = wc_AsyncWait(ret, &aes->asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + + if (ret == 0) { + encContentOutOctSz = SetOctetString(contentDataSz, encContentOutOct); + wc_PKCS7_WriteOut(pkcs7, (out)? out + *outIdx: NULL, + encContentOutOct, encContentOutOctSz); + *outIdx += encContentOutOctSz; + wc_PKCS7_WriteOut(pkcs7, (out)? out + *outIdx : NULL, + encContentOut, contentDataSz); + *outIdx += contentDataSz; + } + + return ret; +} + /* Used for encoding the content, potentially one octet chunck at a time if * in streaming mode with IO callbacks set. @@ -2457,8 +2523,6 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, if (pkcs7->encodeStream) { int sz; word32 totalSz = 0; - byte encContentOutOct[MAX_OCTET_STR_SZ]; - word32 encContentOutOctSz = 0; byte* buf; byte* encContentOut; byte* contentData; @@ -2487,9 +2551,6 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, return MEMORY_E; } - encContentOutOctSz = SetOctetString(BER_OCTET_LENGTH, - encContentOutOct); - /* keep pulling from content until empty */ do { int contentDataRead = 0; @@ -2498,6 +2559,14 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, if (pkcs7->getContentCb) { contentDataRead = pkcs7->getContentCb(pkcs7, &buf, pkcs7->streamCtx); + + if (buf == NULL) { + WOLFSSL_MSG("Get content callback returned null " + "buffer pointer"); + XFREE(encContentOut, heap, DYNAMIC_TYPE_PKCS7); + XFREE(contentData, heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + } } else #endif @@ -2515,14 +2584,6 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, /* no more data returned from callback */ break; } - - if (buf == NULL) { - WOLFSSL_MSG("Get content callback returned null " - "buffer pointer"); - XFREE(encContentOut, heap, DYNAMIC_TYPE_PKCS7); - XFREE(contentData, heap, DYNAMIC_TYPE_PKCS7); - return BAD_FUNC_ARG; - } totalSz += (word32)contentDataRead; /* check and handle octet boundary */ @@ -2532,50 +2593,9 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, contentDataRead -= sz; XMEMCPY(contentData + idx, buf, sz); - - /* encrypt and flush out data */ - switch (cipherType) { - case WC_CIPHER_NONE: - XMEMCPY(encContentOut, contentData, BER_OCTET_LENGTH); - if (esd && esd->contentDigestSet != 1) { - ret = wc_HashUpdate(&esd->hash, esd->hashType, - contentData, BER_OCTET_LENGTH); - } - break; - - #ifndef NO_AES - case WC_CIPHER_AES_CBC: - ret = wc_AesCbcEncrypt(aes, encContentOut, - contentData, BER_OCTET_LENGTH); - break; - #endif - - #ifdef WOLFSSL_AESGCM_STREAM - case WC_CIPHER_AES_GCM: - ret = wc_AesGcmEncryptUpdate(aes, encContentOut, - contentData, BER_OCTET_LENGTH, NULL, 0); - break; - #endif - } - - #ifdef WOLFSSL_ASYNC_CRYPT - /* async encrypt not available here, so block till done */ - if (cipherType != WC_CIPHER_NONE) { - ret = wc_AsyncWait(ret, &aes->asyncDev, WC_ASYNC_FLAG_NONE); - } - #endif - if (pkcs7->encodeStream) { - wc_PKCS7_WriteOut(pkcs7, - (out)? out + outIdx: NULL, - encContentOutOct, - encContentOutOctSz); - outIdx += encContentOutOctSz; - } - wc_PKCS7_WriteOut(pkcs7, - (out)? out + outIdx : NULL, - encContentOut, - BER_OCTET_LENGTH); - outIdx += BER_OCTET_LENGTH; + ret = wc_PKCS7_EncodeContentStreamHelper(pkcs7, cipherType, + aes, encContentOut, contentData, BER_OCTET_LENGTH, out, + &outIdx, esd); /* copy over any remaining data */ XMEMCPY(contentData, buf + sz, contentDataRead); @@ -2605,45 +2625,9 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, idx += padSz; } - /* encrypt and flush out remainder of content data */ - switch (cipherType) { - case WC_CIPHER_NONE: - XMEMCPY(encContentOut, contentData, idx); - if (esd && esd->contentDigestSet != 1) { - ret = wc_HashUpdate(&esd->hash, esd->hashType, contentData, - idx); - } - break; - - #ifndef NO_AES - case WC_CIPHER_AES_CBC: - ret = wc_AesCbcEncrypt(aes, encContentOut, contentData, idx); - break; - #endif - - #ifdef WOLFSSL_AESGCM_STREAM - case WC_CIPHER_AES_GCM: - ret = wc_AesGcmEncryptUpdate(aes, encContentOut, - contentData, idx, NULL, 0); - break; - #endif - } - #ifdef WOLFSSL_ASYNC_CRYPT - /* async encrypt not available here, so block till done */ - if (cipherType != WC_CIPHER_NONE) { - ret = wc_AsyncWait(ret, &aes->asyncDev, WC_ASYNC_FLAG_NONE); - } - #endif - if (pkcs7->encodeStream) { - encContentOutOctSz = SetOctetString(idx, - encContentOutOct); - wc_PKCS7_WriteOut(pkcs7, (out)? out + outIdx: NULL, - encContentOutOct, encContentOutOctSz); - outIdx += encContentOutOctSz; - } - wc_PKCS7_WriteOut(pkcs7, (out)? out + outIdx : NULL, - encContentOut, idx); + ret = wc_PKCS7_EncodeContentStreamHelper(pkcs7, cipherType, aes, + encContentOut, contentData, idx, out, &outIdx, esd); if (cipherType == WC_CIPHER_NONE && esd && esd->contentDigestSet != 1) { ret = wc_HashFinal(&esd->hash, esd->hashType, @@ -7574,7 +7558,7 @@ int wc_PKCS7_WriteOut(PKCS7* pkcs7, byte* output, const byte* input, XMEMCPY(output, input, inputSz); } else { - WOLFSSL_MSG("No provided way to output bundle"); + WOLFSSL_MSG("No way provided to output bundle"); ret = BUFFER_E; } From c24b187a8815c9b50094cd93e6b392b472534a5b Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Fri, 8 Mar 2024 01:54:37 +0700 Subject: [PATCH 9/9] fixes for clang-tidy warnings --- wolfcrypt/src/pkcs7.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 9e418963b..780a97f0c 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -2537,6 +2537,9 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, if (cipherType == WC_CIPHER_NONE && esd && esd->contentDigestSet != 1) { /* calculate hash for content */ ret = wc_HashInit(&esd->hash, esd->hashType); + if (ret != 0) { + return ret; + } } encContentOut = XMALLOC(BER_OCTET_LENGTH + MAX_OCTET_STR_SZ, @@ -2596,6 +2599,11 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, ret = wc_PKCS7_EncodeContentStreamHelper(pkcs7, cipherType, aes, encContentOut, contentData, BER_OCTET_LENGTH, out, &outIdx, esd); + if (ret != 0) { + XFREE(encContentOut, heap, DYNAMIC_TYPE_PKCS7); + XFREE(contentData, heap, DYNAMIC_TYPE_PKCS7); + return ret; + } /* copy over any remaining data */ XMEMCPY(contentData, buf + sz, contentDataRead); @@ -2628,11 +2636,13 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, /* encrypt and flush out remainder of content data */ ret = wc_PKCS7_EncodeContentStreamHelper(pkcs7, cipherType, aes, encContentOut, contentData, idx, out, &outIdx, esd); - - if (cipherType == WC_CIPHER_NONE && esd && esd->contentDigestSet != 1) { - ret = wc_HashFinal(&esd->hash, esd->hashType, - esd->contentDigest + 2); - wc_HashFree(&esd->hash, esd->hashType); + if (ret == 0) { + if (cipherType == WC_CIPHER_NONE && esd && + esd->contentDigestSet != 1) { + ret = wc_HashFinal(&esd->hash, esd->hashType, + esd->contentDigest + 2); + wc_HashFree(&esd->hash, esd->hashType); + } } XFREE(encContentOut, heap, DYNAMIC_TYPE_PKCS7);