Merge pull request #7184 from JacobBarthelmeh/pkcs7-enc

PKCS7 streaming with encode/sign
This commit is contained in:
Daniel Pouzzner
2024-02-02 18:00:12 -05:00
committed by GitHub
6 changed files with 467 additions and 85 deletions

View File

@ -26916,13 +26916,56 @@ static int test_wc_PKCS7_EncodeSignedData(void)
}
ExpectIntGT(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), 0);
wc_PKCS7_Free(pkcs7);
pkcs7 = NULL;
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0);
ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, outputSz), 0);
#ifdef ASN_BER_TO_DER
wc_PKCS7_Free(pkcs7);
/* reinitialize and test setting stream mode */
{
int signedSz;
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->content = data;
pkcs7->contentSz = (word32)sizeof(data);
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_GetStreamMode(pkcs7), 0);
ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1), 0);
ExpectIntEQ(wc_PKCS7_SetStreamMode(NULL, 1), BAD_FUNC_ARG);
ExpectIntEQ(wc_PKCS7_GetStreamMode(pkcs7), 1);
ExpectIntGT(signedSz = wc_PKCS7_EncodeSignedData(pkcs7, output,
outputSz), 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, output, signedSz), 0);
}
#endif
/* Pass in bad args. */
ExpectIntEQ(wc_PKCS7_EncodeSignedData(NULL, output, outputSz),
BAD_FUNC_ARG);
@ -27953,6 +27996,9 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void)
EXPECT_DECLS;
#if defined(HAVE_PKCS7)
PKCS7* pkcs7 = NULL;
#ifdef ASN_BER_TO_DER
int encodedSz = 0;
#endif
#ifdef ECC_TIMING_RESISTANT
WC_RNG rng;
#endif
@ -28153,6 +28199,39 @@ 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 */
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (testVectors + i)->cert,
(word32)(testVectors + i)->certSz), 0);
if (pkcs7 != NULL) {
#ifdef ECC_TIMING_RESISTANT
pkcs7->rng = &rng;
#endif
pkcs7->content = (byte*)(testVectors + i)->content;
pkcs7->contentSz = (testVectors + i)->contentSz;
pkcs7->contentOID = (testVectors + i)->contentOID;
pkcs7->encryptOID = (testVectors + i)->encryptOID;
pkcs7->keyWrapOID = (testVectors + i)->keyWrapOID;
pkcs7->keyAgreeOID = (testVectors + i)->keyAgreeOID;
pkcs7->privateKey = (testVectors + i)->privateKey;
pkcs7->privateKeySz = (testVectors + i)->privateKeySz;
}
ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1), 0);
ExpectIntGE(encodedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, output,
(word32)sizeof(output)), 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));
#endif
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (testVectors + i)->cert,
(word32)(testVectors + i)->certSz), 0);
if (pkcs7 != NULL) {
@ -28170,6 +28249,11 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void)
pkcs7->privateKeySz = (testVectors + i)->privateKeySz;
}
#ifdef ASN_BER_TO_DER
/* test without setting stream mode */
ExpectIntEQ(wc_PKCS7_GetStreamMode(pkcs7), 0);
#endif
ExpectIntGE(wc_PKCS7_EncodeEnvelopedData(pkcs7, output,
(word32)sizeof(output)), 0);
@ -28178,6 +28262,7 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void)
ExpectIntGE(decodedSz, 0);
/* Verify the size of each buffer. */
ExpectIntEQ((word32)sizeof(input)/sizeof(char), decodedSz);
/* Don't free the last time through the loop. */
if (i < testSz - 1) {
wc_PKCS7_Free(pkcs7);
@ -28871,7 +28956,6 @@ static int test_wc_PKCS7_signed_enveloped(void)
#ifdef HAVE_AES_CBC
PKCS7* inner = NULL;
#endif
void* pt = NULL;
WC_RNG rng;
unsigned char key[FOURK_BUF/2];
unsigned char cert[FOURK_BUF/2];
@ -28958,17 +29042,13 @@ static int test_wc_PKCS7_signed_enveloped(void)
pkcs7->rng = &rng;
}
/* Set no certs in bundle for this test. Hang on to the pointer though to
* free it later. */
/* Set no certs in bundle for this test. */
if (pkcs7 != NULL) {
pt = (void*)pkcs7->certList;
pkcs7->certList = NULL; /* no certs in bundle */
ExpectIntEQ(wc_PKCS7_SetNoCerts(pkcs7, 1), 0);
ExpectIntEQ(wc_PKCS7_SetNoCerts(NULL, 1), BAD_FUNC_ARG);
ExpectIntEQ(wc_PKCS7_GetNoCerts(pkcs7), 1);
}
ExpectIntGT((sigSz = wc_PKCS7_EncodeSignedData(pkcs7, sig, sigSz)), 0);
if (pkcs7 != NULL) {
/* restore pointer for PKCS7 free call */
pkcs7->certList = (Pkcs7Cert*)pt;
}
wc_PKCS7_Free(pkcs7);
pkcs7 = NULL;

View File

@ -3460,6 +3460,70 @@ word32 SetBitString(word32 len, byte unusedBits, byte* output)
#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 || HAVE_ED448 */
#ifdef ASN_BER_TO_DER
#define BER_OCTET_LENGTH 4096
/* sets the terminating 0x00 0x00 at the end of an indefinite length
* returns the number of bytes written */
word32 SetIndefEnd(byte* output)
{
byte terminate[ASN_INDEF_END_SZ] = { 0x00, 0x00 };
if (output != NULL) {
XMEMCPY(output, terminate, ASN_INDEF_END_SZ);
}
return (word32)ASN_INDEF_END_SZ;
}
/* Breaks an octet string up into chunks for use with streaming
* returns 0 on success and updates idx */
int StreamOctetString(const byte* inBuf, word32 inBufSz, byte* out, word32* outSz,
word32* idx)
{
word32 i = 0;
word32 outIdx = *idx;
byte* tmp = out;
if (tmp) tmp += outIdx;
while (i < inBufSz) {
word32 ret, sz;
sz = BER_OCTET_LENGTH;
if ((sz + i) > inBufSz) {
sz = inBufSz - i;
}
ret = SetOctetString(sz, tmp);
if (ret > 0) {
outIdx += ret;
}
if (tmp) {
if ((word32)ret + sz + i + outIdx > *outSz) {
return BUFFER_E;
}
XMEMCPY(tmp + ret, inBuf + i, sz);
tmp += sz + ret;
}
outIdx += sz;
i += sz;
}
if (tmp) {
*idx = outIdx;
return 0;
}
else {
*outSz = outIdx;
return LENGTH_ONLY_E;
}
}
/* Convert BER to DER */
/* Pull informtation from the ASN.1 BER encoded item header */
@ -15334,6 +15398,18 @@ word32 SetLength(word32 length, byte* output)
return i;
}
word32 SetLengthEx(word32 length, byte* output, byte isIndef)
{
if (isIndef) {
if (output != NULL) {
output[0] = ASN_INDEF_LENGTH;
}
return 1;
}
else {
return SetLength(length, output);
}
}
/* Encode a DER header - type/tag and length.
*
* @param [in] tag DER tag of ASN.1 item.
@ -15341,14 +15417,15 @@ word32 SetLength(word32 length, byte* output)
* @param [out] output Buffer to encode into.
* @return Number of bytes encoded.
*/
static word32 SetHeader(byte tag, word32 len, byte* output)
static word32 SetHeader(byte tag, word32 len, byte* output, byte isIndef)
{
if (output) {
/* Encode tag first. */
output[0] = tag;
}
/* Encode the length. */
return SetLength(len, output ? output + ASN_TAG_SZ : NULL) + ASN_TAG_SZ;
return SetLengthEx(len, output ? output + ASN_TAG_SZ : NULL, isIndef) +
ASN_TAG_SZ;
}
/* Encode a SEQUENCE header in DER.
@ -15359,7 +15436,12 @@ static word32 SetHeader(byte tag, word32 len, byte* output)
*/
word32 SetSequence(word32 len, byte* output)
{
return SetHeader(ASN_SEQUENCE | ASN_CONSTRUCTED, len, output);
return SetHeader(ASN_SEQUENCE | ASN_CONSTRUCTED, len, output, 0);
}
word32 SetSequenceEx(word32 len, byte* output, byte isIndef)
{
return SetHeader(ASN_SEQUENCE | ASN_CONSTRUCTED, len, output, isIndef);
}
/* Encode an OCTET STRING header in DER.
@ -15370,7 +15452,14 @@ word32 SetSequence(word32 len, byte* output)
*/
word32 SetOctetString(word32 len, byte* output)
{
return SetHeader(ASN_OCTET_STRING, len, output);
return SetHeader(ASN_OCTET_STRING, len, output, 0);
}
word32 SetOctetStringEx(word32 len, byte* output, byte indef)
{
if (indef)
return SetHeader(ASN_OCTET_STRING | ASN_CONSTRUCTED, len, output, indef);
return SetOctetString(len, output);
}
/* Encode a SET header in DER.
@ -15381,7 +15470,7 @@ word32 SetOctetString(word32 len, byte* output)
*/
word32 SetSet(word32 len, byte* output)
{
return SetHeader(ASN_SET | ASN_CONSTRUCTED, len, output);
return SetHeader(ASN_SET | ASN_CONSTRUCTED, len, output, 0);
}
/* Encode an implicit context specific header in DER.
@ -15394,11 +15483,23 @@ word32 SetSet(word32 len, byte* output)
* @param [out] output Buffer to encode into.
* @return Number of bytes encoded.
*/
word32 SetImplicit(byte tag, byte number, word32 len, byte* output)
word32 SetImplicit(byte tag, byte number, word32 len, byte* output, byte isIndef)
{
tag = (byte)(((tag == ASN_SEQUENCE || tag == ASN_SET) ? ASN_CONSTRUCTED : 0)
| ASN_CONTEXT_SPECIFIC | number);
return SetHeader(tag, len, output);
byte useIndef = 0;
if ((tag == ASN_OCTET_STRING) && isIndef) {
tag = ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | number;
}
else {
tag = (byte)(((tag == ASN_SEQUENCE || tag == ASN_SET) ?
ASN_CONSTRUCTED : 0) | ASN_CONTEXT_SPECIFIC | number);
}
if (isIndef && (tag & ASN_CONSTRUCTED)) {
useIndef = 1;
}
return SetHeader(tag, len, output, useIndef);
}
/* Encode an explicit context specific header in DER.
@ -15410,10 +15511,10 @@ word32 SetImplicit(byte tag, byte number, word32 len, byte* output)
* @param [out] output Buffer to encode into.
* @return Number of bytes encoded.
*/
word32 SetExplicit(byte number, word32 len, byte* output)
word32 SetExplicit(byte number, word32 len, byte* output, byte isIndef)
{
return SetHeader((byte)(ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | number),
len, output);
len, output, isIndef);
}
#if defined(OPENSSL_EXTRA)
@ -15439,8 +15540,8 @@ word32 SetOthername(void *name, byte *output)
nameSz = (word32)nm->value->value.utf8string->length;
len = nm->type_id->objSz +
SetHeader(ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC, nameSz + 2, NULL) +
SetHeader(CTC_UTF8, nameSz, NULL) + nameSz;
SetHeader(ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC, nameSz + 2, NULL, 0) +
SetHeader(CTC_UTF8, nameSz, NULL, 0) + nameSz;
if (output != NULL) {
/* otherName OID */
@ -15448,9 +15549,9 @@ word32 SetOthername(void *name, byte *output)
output += nm->type_id->objSz;
output += SetHeader(ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC, nameSz + 2,
output);
output, 0);
output += SetHeader(CTC_UTF8, nameSz, output);
output += SetHeader(CTC_UTF8, nameSz, output, 0);
XMEMCPY(output, nameStr, nameSz);
}
@ -34454,7 +34555,7 @@ int SetAsymKeyDer(const byte* privKey, word32 privKeyLen,
/* pubKey */
if (pubKey) {
idx += SetHeader(ASN_CONTEXT_SPECIFIC | ASN_ASYMKEY_PUBKEY |
1, pubKeyLen, output + idx);
1, pubKeyLen, output + idx, 0);
XMEMCPY(output + idx, pubKey, pubKeyLen);
idx += pubKeyLen;
}
@ -36355,7 +36456,7 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size)
*/
extSz = EncodeOcspRequestExtensions(req, extArray + 2,
OCSP_NONCE_EXT_SZ);
extSz += SetExplicit(2, extSz, extArray);
extSz += SetExplicit(2, extSz, extArray, 0);
}
totalSz = algoSz + issuerSz + issuerKeySz + snSz;

View File

@ -1836,7 +1836,7 @@ static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng,
/* rewind index and set tag and length */
tmpIdx -= MAX_LENGTH_SZ + 1;
sz = (word32)SetExplicit(0, (word32)ret, out + tmpIdx);
sz = (word32)SetExplicit(0, (word32)ret, out + tmpIdx, 0);
tmpIdx += sz; totalSz += sz;
XMEMMOVE(out + tmpIdx, out + MAX_LENGTH_SZ + 1, (size_t)ret);

View File

@ -2462,13 +2462,17 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd,
esd->innerContSeqSz = 0;
esd->contentInfoSeqSz = SetSequence(pkcs7->contentTypeSz,
esd->contentInfoSeq);
} else {
esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets);
}
else {
esd->innerOctetsSz = SetOctetStringEx(pkcs7->contentSz, esd->innerOctets,
pkcs7->encodeStream);
esd->innerContSeqSz = SetExplicit(0, esd->innerOctetsSz +
pkcs7->contentSz, esd->innerContSeq);
esd->contentInfoSeqSz = SetSequence(pkcs7->contentSz +
pkcs7->contentSz, esd->innerContSeq,
pkcs7->encodeStream);
esd->contentInfoSeqSz = SetSequenceEx(pkcs7->contentSz +
esd->innerOctetsSz + pkcs7->contentTypeSz +
esd->innerContSeqSz, esd->contentInfoSeq);
esd->innerContSeqSz, esd->contentInfoSeq,
pkcs7->encodeStream);
}
/* SignerIdentifier */
@ -2495,7 +2499,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd,
/* SubjectKeyIdentifier */
esd->issuerSKIDSz = SetOctetString(keyIdSize, esd->issuerSKID);
esd->issuerSKIDSeqSz = SetExplicit(0, esd->issuerSKIDSz + keyIdSize,
esd->issuerSKIDSeq);
esd->issuerSKIDSeq, 0);
signerInfoSz += (esd->issuerSKIDSz + esd->issuerSKIDSeqSz + keyIdSize);
/* version MUST be 3 */
@ -2550,7 +2554,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd,
FlattenAttributes(pkcs7, flatSignedAttribs,
esd->signedAttribs, esd->signedAttribsCount);
esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz,
esd->signedAttribSet);
esd->signedAttribSet, 0);
} else {
esd->signedAttribSetSz = 0;
}
@ -2577,15 +2581,17 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd,
/* certificates [0] IMPLICIT CertificateSet */
/* get total certificates size */
certPtr = pkcs7->certList;
while (certPtr != NULL) {
certSetSz += certPtr->derSz;
certPtr = certPtr->next;
if (pkcs7->noCerts != 1) {
certPtr = pkcs7->certList;
while (certPtr != NULL) {
certSetSz += certPtr->derSz;
certPtr = certPtr->next;
}
}
certPtr = NULL;
if (certSetSz > 0)
esd->certsSetSz = SetImplicit(ASN_SET, 0, certSetSz, esd->certsSet);
esd->certsSetSz = SetImplicit(ASN_SET, 0, certSetSz, esd->certsSet, 0);
if (pkcs7->sidType != DEGENERATE_SID) {
esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId,
@ -2603,19 +2609,47 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd,
totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz +
esd->contentInfoSeqSz + pkcs7->contentTypeSz +
esd->innerContSeqSz + esd->innerOctetsSz + pkcs7->contentSz;
esd->innerContSeqSz + esd->innerOctetsSz;
#ifdef ASN_BER_TO_DER
if (pkcs7->encodeStream) {
word32 sz = 0, 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);
}
else
#endif
{
totalSz += pkcs7->contentSz;
}
total2Sz = esd->certsSetSz + certSetSz + signerInfoSz;
if (pkcs7->detached) {
totalSz -= pkcs7->contentSz;
}
esd->innerSeqSz = SetSequence(totalSz + total2Sz, esd->innerSeq);
esd->innerSeqSz = SetSequenceEx(totalSz + total2Sz, esd->innerSeq,
pkcs7->encodeStream);
totalSz += esd->innerSeqSz;
esd->outerContentSz = SetExplicit(0, totalSz + total2Sz, esd->outerContent);
if (pkcs7->encodeStream) {
totalSz += ASN_INDEF_END_SZ;
}
esd->outerContentSz = SetExplicit(0, totalSz + total2Sz,
esd->outerContent, pkcs7->encodeStream);
totalSz += esd->outerContentSz + signedDataOidSz;
esd->outerSeqSz = SetSequence(totalSz + total2Sz, esd->outerSeq);
if (pkcs7->encodeStream) {
totalSz += ASN_INDEF_END_SZ;
}
esd->outerSeqSz = SetSequenceEx(totalSz + total2Sz, esd->outerSeq,
pkcs7->encodeStream);
totalSz += esd->outerSeqSz;
if (pkcs7->encodeStream) {
totalSz += ASN_INDEF_END_SZ;
}
/* if using header/footer, we are not returning the content */
if (output2 && output2Sz) {
@ -2690,8 +2724,26 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd,
}
else {
if (!pkcs7->detached && pkcs7->content != NULL && pkcs7->contentSz > 0) {
XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
idx += pkcs7->contentSz;
#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
#endif
{
XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
idx += pkcs7->contentSz;
}
}
output2 = output;
}
@ -2699,12 +2751,16 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd,
/* certificates */
XMEMCPY(output2 + idx, esd->certsSet, esd->certsSetSz);
idx += esd->certsSetSz;
certPtr = pkcs7->certList;
while (certPtr != NULL) {
XMEMCPY(output2 + idx, certPtr->der, certPtr->derSz);
idx += certPtr->derSz;
certPtr = certPtr->next;
if (pkcs7->noCerts != 1) {
certPtr = pkcs7->certList;
while (certPtr != NULL) {
XMEMCPY(output2 + idx, certPtr->der, certPtr->derSz);
idx += certPtr->derSz;
certPtr = certPtr->next;
}
}
wc_PKCS7_FreeCertSet(pkcs7);
XMEMCPY(output2 + idx, esd->signerInfoSet, esd->signerInfoSetSz);
@ -2756,6 +2812,19 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd,
XMEMCPY(output2 + idx, esd->encContentDigest, esd->encContentDigestSz);
idx += esd->encContentDigestSz;
#ifdef ASN_BER_TO_DER
if (pkcs7->encodeStream) {
/* end of signedData seq */
idx += SetIndefEnd(output2 + idx);
/* end of outer content set */
idx += SetIndefEnd(output2 + idx);
/* end of outer content info seq */
idx += SetIndefEnd(output2 + idx);
}
#endif
if (output2Sz) {
*output2Sz = idx;
idx = 0; /* success */
@ -6009,7 +6078,7 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID)
/* suppPubInfo */
suppPubInfoSeqSz = SetImplicit(ASN_SEQUENCE, 2,
kekOctetSz + sizeof(word32),
suppPubInfoSeq);
suppPubInfoSeq, 0);
sharedInfoSz += suppPubInfoSeqSz;
/* optional ukm/entityInfo */
@ -6019,7 +6088,7 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID)
entityUInfoExplicitSz = SetExplicit(0, entityUInfoOctetSz +
kari->ukmSz,
entityUInfoExplicitSeq);
entityUInfoExplicitSeq, 0);
sharedInfoSz += entityUInfoExplicitSz;
}
@ -6395,7 +6464,7 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz,
/* RecipientKeyIdentifier IMPLICIT [0] */
recipKeyIdSeqSz = SetImplicit(ASN_SEQUENCE, 0, subjKeyIdOctetSz +
keyIdSize, recipKeyIdSeq);
keyIdSize, recipKeyIdSeq, 0);
totalSz += recipKeyIdSeqSz;
/* RecipientEncryptedKey */
@ -6413,7 +6482,7 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz,
totalSz += (ukmOctetSz + kari->ukmSz);
ukmExplicitSz = SetExplicit(1, ukmOctetSz + kari->ukmSz,
ukmExplicitSeq);
ukmExplicitSeq, 0);
totalSz += ukmExplicitSz;
}
@ -6447,14 +6516,14 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz,
/* outer OriginatorPublicKey IMPLICIT [1] */
origPubKeySeqSz = SetImplicit(ASN_SEQUENCE, 1,
origAlgIdSz + origPubKeyStrSz +
kari->senderKeyExportSz, origPubKeySeq);
kari->senderKeyExportSz, origPubKeySeq, 0);
totalSz += origPubKeySeqSz;
/* outer OriginatorIdentifierOrKey IMPLICIT [0] */
origIdOrKeySeqSz = SetImplicit(ASN_SEQUENCE, 0,
origPubKeySeqSz + origAlgIdSz +
origPubKeyStrSz + kari->senderKeyExportSz,
origIdOrKeySeq);
origIdOrKeySeq, 0);
totalSz += origIdOrKeySeqSz;
/* version, always 3 */
@ -6463,7 +6532,7 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz,
recip->recipVersion = 3;
/* outer IMPLICIT [1] kari */
kariSeqSz = SetImplicit(ASN_SEQUENCE, 1, totalSz, kariSeq);
kariSeqSz = SetImplicit(ASN_SEQUENCE, 1, totalSz, kariSeq, 0);
totalSz += kariSeqSz;
if (totalSz > MAX_RECIP_SZ) {
@ -7578,7 +7647,7 @@ int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb,
oriTypeLenSz = SetLength(oriTypeSz, oriTypeLen);
recipSeqSz = SetImplicit(ASN_SEQUENCE, 4, 1 + oriTypeLenSz + oriTypeSz +
oriValueSz, recipSeq);
oriValueSz, recipSeq, 0);
idx = 0;
XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz);
@ -8028,7 +8097,7 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen,
/* set KeyDerivationAlgorithmIdentifier EXPLICIT [0] SEQ */
kdfAlgoIdSeqSz = SetExplicit(0, kdfAlgoIdSz + kdfParamsSeqSz +
kdfSaltOctetStrSz + saltSz + kdfIterationsSz,
kdfAlgoIdSeq);
kdfAlgoIdSeq, 0);
totalSz += kdfAlgoIdSeqSz;
/* set PasswordRecipientInfo CMSVersion, MUST be 0 */
@ -8037,7 +8106,7 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen,
recip->recipVersion = 0;
/* set PasswordRecipientInfo SEQ */
recipSeqSz = SetImplicit(ASN_SEQUENCE, 3, totalSz, recipSeq);
recipSeqSz = SetImplicit(ASN_SEQUENCE, 3, totalSz, recipSeq, 0);
totalSz += recipSeqSz;
if (totalSz > MAX_RECIP_SZ) {
@ -8280,7 +8349,7 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek,
recip->recipVersion = 4;
/* KEKRecipientInfo SEQ */
recipSeqSz = SetImplicit(ASN_SEQUENCE, 2, totalSz, recipSeq);
recipSeqSz = SetImplicit(ASN_SEQUENCE, 2, totalSz, recipSeq, 0);
totalSz += recipSeqSz;
if (totalSz > MAX_RECIP_SZ) {
@ -8585,12 +8654,11 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
}
encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz,
encContentOctet);
encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
ivOctetStringSz + blockSz +
encContentOctetSz + encryptedOutSz,
encContentSeq);
encContentOctet, pkcs7->encodeStream);
encContentSeqSz = SetSequenceEx(contentTypeSz + contentEncAlgoSz +
ivOctetStringSz + blockSz +
encContentOctetSz + encryptedOutSz,
encContentSeq, pkcs7->encodeStream);
/* keep track of sizes for outer wrapper layering */
totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz +
@ -8598,18 +8666,49 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
encContentOctetSz + encryptedOutSz;
/* EnvelopedData */
envDataSeqSz = SetSequence(totalSz, envDataSeq);
#ifdef ASN_BER_TO_DER
if (pkcs7->encodeStream) {
word32 streamSz = 0, tmpIdx = 0;
/* account for ending of encContentOctet */
totalSz += ASN_INDEF_END_SZ;
/* account for ending of encContentSeq */
totalSz += ASN_INDEF_END_SZ;
/* account for asn1 syntax around octet strings */
StreamOctetString(NULL, encryptedOutSz, NULL, &streamSz, &tmpIdx);
totalSz += (streamSz - encryptedOutSz);
}
#endif
envDataSeqSz = SetSequenceEx(totalSz, envDataSeq, pkcs7->encodeStream);
totalSz += envDataSeqSz;
#ifdef ASN_BER_TO_DER
if (pkcs7->encodeStream) {
totalSz += ASN_INDEF_END_SZ;
}
#endif
/* outer content */
outerContentSz = SetExplicit(0, totalSz, outerContent);
outerContentSz = SetExplicit(0, totalSz, outerContent, pkcs7->encodeStream);
#ifdef ASN_BER_TO_DER
if (pkcs7->encodeStream) {
totalSz += ASN_INDEF_END_SZ;
}
#endif
totalSz += outerContentTypeSz;
totalSz += outerContentSz;
if (pkcs7->contentOID != FIRMWARE_PKG_DATA) {
/* ContentInfo */
contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
contentInfoSeqSz = SetSequenceEx(totalSz, contentInfoSeq,
pkcs7->encodeStream);
totalSz += contentInfoSeqSz;
#ifdef ASN_BER_TO_DER
if (pkcs7->encodeStream) {
totalSz += ASN_INDEF_END_SZ;
}
#endif
}
if (totalSz > (int)outputSz) {
@ -8628,6 +8727,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
XMEMCPY(output + idx, outerContent, outerContentSz);
idx += outerContentSz;
}
XMEMCPY(output + idx, envDataSeq, envDataSeqSz);
idx += envDataSeqSz;
XMEMCPY(output + idx, ver, verSz);
@ -8642,6 +8742,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
tmpRecip = tmpRecip->next;
}
wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
XMEMCPY(output + idx, encContentSeq, encContentSeqSz);
idx += encContentSeqSz;
XMEMCPY(output + idx, contentType, contentTypeSz);
@ -8654,8 +8755,36 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
idx += blockSz;
XMEMCPY(output + idx, encContentOctet, encContentOctetSz);
idx += encContentOctetSz;
XMEMCPY(output + idx, encryptedContent, encryptedOutSz);
idx += encryptedOutSz;
#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;
}
/* end of encrypted content */
idx += SetIndefEnd(output + idx);
/* end of encrypted content info */
idx += SetIndefEnd(output + idx);
/* end of Enveloped Data seq */
idx += SetIndefEnd(output + idx);
/* end of outer content set */
idx += SetIndefEnd(output + idx);
/* end of outer content info seq */
idx += SetIndefEnd(output + idx);
}
else
#endif
{
XMEMCPY(output + idx, encryptedContent, encryptedOutSz);
idx += encryptedOutSz;
}
XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
@ -11498,7 +11627,7 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
}
authAttribsSetSz = SetImplicit(ASN_SET, 1, authAttribsSz,
authAttribSet);
authAttribSet, 0);
/* From RFC5083, "For the purpose of constructing the AAD, the
* IMPLICIT [1] tag in the authAttrs field is not used for the
@ -11544,7 +11673,7 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
FlattenAttributes(pkcs7, flatUnauthAttribs, unauthAttribs,
unauthAttribsCount);
unauthAttribsSetSz = SetImplicit(ASN_SET, 2, unauthAttribsSz,
unauthAttribSet);
unauthAttribSet, 0);
}
/* AES-GCM/CCM does NOT require padding for plaintext content or
@ -11656,8 +11785,7 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
}
encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz,
encContentOctet);
encContentOctet, 0);
encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
nonceOctetStringSz + nonceSz + macIntSz +
algoParamSeqSz + encContentOctetSz +
@ -11677,7 +11805,7 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
totalSz += envDataSeqSz;
/* outer content */
outerContentSz = SetExplicit(0, totalSz, outerContent);
outerContentSz = SetExplicit(0, totalSz, outerContent, 0);
totalSz += outerContentTypeSz;
totalSz += outerContentSz;
@ -11730,6 +11858,8 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
idx += nonceSz;
XMEMCPY(output + idx, macInt, macIntSz);
idx += macIntSz;
XMEMCPY(output + idx, encContentOctet, encContentOctetSz);
idx += encContentOctetSz;
XMEMCPY(output + idx, encryptedContent, encryptedOutSz);
@ -12540,7 +12670,7 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz)
}
encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0,
encryptedOutSz, encContentOctet);
encryptedOutSz, encContentOctet, 0);
encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
ivOctetStringSz + blockSz +
@ -12586,7 +12716,7 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz)
XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
return ret;
}
attribsSetSz = SetImplicit(ASN_SET, 1, attribsSz, attribSet);
attribsSetSz = SetImplicit(ASN_SET, 1, attribsSz, attribSet, 0);
} else {
attribsSz = 0;
@ -12604,7 +12734,7 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz)
if (pkcs7->version != 3) {
/* outer content */
outerContentSz = SetExplicit(0, totalSz, outerContent);
outerContentSz = SetExplicit(0, totalSz, outerContent, 0);
totalSz += outerContentTypeSz;
totalSz += outerContentSz;
/* ContentInfo */
@ -13095,6 +13225,60 @@ int wc_PKCS7_SetDecodeEncryptedCtx(PKCS7* pkcs7, void* ctx)
}
#endif /* NO_PKCS7_ENCRYPTED_DATA */
/* set stream mode for encoding and signing
* returns 0 on success */
int wc_PKCS7_SetStreamMode(PKCS7* pkcs7, byte flag)
{
if (pkcs7 == NULL) {
return BAD_FUNC_ARG;
}
#ifdef ASN_BER_TO_DER
pkcs7->encodeStream = flag;
return 0;
#else
(void)flag;
return NOT_COMPILED_IN;
#endif
}
/* returns to current stream mode flag on success, negative values on fail */
int wc_PKCS7_GetStreamMode(PKCS7* pkcs7)
{
if (pkcs7 == NULL) {
return BAD_FUNC_ARG;
}
#ifdef ASN_BER_TO_DER
return pkcs7->encodeStream;
#else
return 0;
#endif
}
/* set option to not include certificates when creating a bundle
* returns 0 on success */
int wc_PKCS7_SetNoCerts(PKCS7* pkcs7, byte flag)
{
if (pkcs7 == NULL) {
return BAD_FUNC_ARG;
}
pkcs7->noCerts = flag;
return 0;
}
/* returns the current noCerts flag value on success, negative values on fail */
int wc_PKCS7_GetNoCerts(PKCS7* pkcs7)
{
if (pkcs7 == NULL) {
return BAD_FUNC_ARG;
}
return pkcs7->noCerts;
}
#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA)
/* build PKCS#7 compressedData content type, return encrypted size */
@ -13149,7 +13333,7 @@ int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, word32 outputSz)
totalSz = contentOctetStrSz + compressedSz;
/* EXPLICIT [0] eContentType */
contentSeqSz = SetExplicit(0, totalSz, contentSeq);
contentSeqSz = SetExplicit(0, totalSz, contentSeq, 0);
totalSz += contentSeqSz;
/* eContentType OBJECT IDENTIFIER */
@ -13209,7 +13393,7 @@ int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, word32 outputSz)
*/
/* ContentInfo content EXPLICIT SEQUENCE */
contentInfoContentSeqSz = SetExplicit(0, totalSz, contentInfoContentSeq);
contentInfoContentSeqSz = SetExplicit(0, totalSz, contentInfoContentSeq, 0);
totalSz += contentInfoContentSeqSz;
ret = wc_SetContentType(COMPRESSED_DATA, contentInfoTypeOid,

View File

@ -1023,6 +1023,7 @@ enum Misc_ASN {
#endif
TRAILING_ZERO = 1, /* Used for size of zero pad */
ASN_TAG_SZ = 1, /* single byte ASN.1 tag */
ASN_INDEF_END_SZ = 2, /* 0x00 0x00 at end of indef */
MIN_VERSION_SZ = 3, /* Min bytes needed for GetMyVersion */
MAX_X509_VERSION = 3, /* Max X509 version allowed */
MIN_X509_VERSION = 0, /* Min X509 version allowed */
@ -2100,6 +2101,8 @@ WOLFSSL_LOCAL int GetName(DecodedCert* cert, int nameType, int maxIdx);
WOLFSSL_ASN_API int wc_BerToDer(const byte* ber, word32 berSz, byte* der,
word32* derSz);
WOLFSSL_LOCAL int StreamOctetString(const byte* inBuf, word32 inBufSz,
byte* out, word32* outSz, word32* idx);
WOLFSSL_ASN_API void FreeAltNames(DNS_entry* altNames, void* heap);
WOLFSSL_ASN_API DNS_entry* AltNameNew(void* heap);
@ -2274,12 +2277,18 @@ WOLFSSL_LOCAL word32 SetASNExplicit(byte number, word32 len, byte* output);
WOLFSSL_LOCAL word32 SetASNSet(word32 len, byte* output);
WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output);
WOLFSSL_LOCAL word32 SetLengthEx(word32 length, byte* output, byte isIndef);
WOLFSSL_LOCAL word32 SetSequence(word32 len, byte* output);
WOLFSSL_LOCAL word32 SetSequenceEx(word32 len, byte* output, byte isIndef);
WOLFSSL_LOCAL word32 SetIndefEnd(byte* output);
WOLFSSL_LOCAL word32 SetOctetString(word32 len, byte* output);
WOLFSSL_LOCAL word32 SetOctetStringEx(word32 len, byte* output, byte indef);
WOLFSSL_LOCAL int SetASNInt(int len, byte firstByte, byte* output);
WOLFSSL_LOCAL word32 SetBitString(word32 len, byte unusedBits, byte* output);
WOLFSSL_LOCAL word32 SetImplicit(byte tag,byte number,word32 len,byte* output);
WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output);
WOLFSSL_LOCAL word32 SetImplicit(byte tag,byte number,word32 len,byte* output,
byte isIndef);
WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output,
byte isIndef);
WOLFSSL_LOCAL word32 SetSet(word32 len, byte* output);
WOLFSSL_API word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz);
WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header);

View File

@ -248,6 +248,9 @@ struct PKCS7 {
byte* der; /* DER encoded version of message */
word32 derSz;
#endif
byte encodeStream:1; /* use BER when encoding */
byte noCerts:1; /* if certificates should be added into bundle
during creation */
byte* cert[MAX_PKCS7_CERTS]; /* array of certs parsed from bundle */
byte* verifyCert; /* cert from array used for verify */
word32 verifyCertSz;
@ -495,6 +498,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);
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);
/* CMS/PKCS#7 CompressedData */
#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA)
WOLFSSL_API int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output,