diff --git a/tests/api.c b/tests/api.c index 659114aa2..ad2c4849c 100644 --- a/tests/api.c +++ b/tests/api.c @@ -26570,6 +26570,7 @@ static void test_wc_PKCS7_DecodeCompressedData(void) /* test decompression */ AssertNotNull((pkcs7 = wc_PKCS7_New(heap, devId))); + AssertIntEQ(pkcs7->contentOID, 0); /* fail case with out buffer too small */ AssertIntLT(wc_PKCS7_DecodeCompressedData(pkcs7, out, outSz, @@ -26578,6 +26579,7 @@ static void test_wc_PKCS7_DecodeCompressedData(void) /* success case */ AssertIntEQ(wc_PKCS7_DecodeCompressedData(pkcs7, out, outSz, decompressed, decompressedSz), cert_sz); + AssertIntEQ(pkcs7->contentOID, DATA); AssertIntEQ(XMEMCMP(decompressed, cert_buf, cert_sz), 0); XFREE(decompressed, heap, DYNAMIC_TYPE_TMP_BUFFER); decompressed = NULL; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index e5ef7e478..60a2fa593 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -10105,7 +10105,11 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, return BAD_FUNC_ARG; if ((type != ENVELOPED_DATA) && (type != AUTH_ENVELOPED_DATA) && - pkcs7->contentOID != FIRMWARE_PKG_DATA) + pkcs7->contentOID != FIRMWARE_PKG_DATA + #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + && pkcs7->contentOID != COMPRESSED_DATA + #endif + ) return BAD_FUNC_ARG; #ifndef NO_PKCS7_STREAM @@ -10554,6 +10558,10 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, ret = ASN_PARSE_E; } + if (ret == 0) { + pkcs7->contentOID = contentType; + } + if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0) { ret = ASN_PARSE_E; @@ -12369,6 +12377,10 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, pkiMsgSz) < 0) ret = ASN_PARSE_E; + if (ret == 0) { + pkcs7->contentOID = contentType; + } + if (ret == 0 && (ret = GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz)) < 0) ret = ASN_PARSE_E; @@ -12723,15 +12735,37 @@ int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, word32 outputSz) compressedDataSeqSz = SetSequence(totalSz, compressedDataSeq); totalSz += compressedDataSeqSz; - /* ContentInfo content EXPLICIT SEQUENCE */ - contentInfoContentSeqSz = SetExplicit(0, totalSz, contentInfoContentSeq); - totalSz += contentInfoContentSeqSz; - - /* ContentInfo ContentType (compressedData) */ if (pkcs7->version == 3) { - contentInfoTypeOidSz = 0; + /* RFC 4108 section 2 + * When the SignedData is version 3 and eContent is compressedData then + * the encoding is : + * CompressedData { + * version + * compressionAlgorithm + * encapContentInfo + * } + */ + contentInfoSeqSz = 0; + contentInfoTypeOidSz = 0; + contentInfoContentSeqSz = 0; } else { + /* EncryptedData eContent type is encoded with: + * EncryptedData { + * version + * EncryptedContentInfo { + * contentType (i.e id-ct-compressedData) + * contentEncryptionAlgorithm + * octet string of CompressedData or FirmwarePkgData + * } + * attributes + * } + */ + + /* ContentInfo content EXPLICIT SEQUENCE */ + contentInfoContentSeqSz = SetExplicit(0, totalSz, contentInfoContentSeq); + totalSz += contentInfoContentSeqSz; + ret = wc_SetContentType(COMPRESSED_DATA, contentInfoTypeOid, sizeof(contentInfoTypeOid)); if (ret < 0) { @@ -12741,11 +12775,11 @@ int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, word32 outputSz) contentInfoTypeOidSz = ret; totalSz += contentInfoTypeOidSz; - } - /* ContentInfo SEQUENCE */ - contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); - totalSz += contentInfoSeqSz; + /* ContentInfo SEQUENCE */ + contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); + totalSz += contentInfoSeqSz; + } if (outputSz < totalSz) { XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -12753,12 +12787,18 @@ int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, word32 outputSz) } idx = 0; - XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); - idx += contentInfoSeqSz; - XMEMCPY(output + idx, contentInfoTypeOid, contentInfoTypeOidSz); - idx += contentInfoTypeOidSz; - XMEMCPY(output + idx, contentInfoContentSeq, contentInfoContentSeqSz); - idx += contentInfoContentSeqSz; + if (contentInfoSeqSz > 0) { + XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); + idx += contentInfoSeqSz; + } + if (contentInfoTypeOidSz > 0) { + XMEMCPY(output + idx, contentInfoTypeOid, contentInfoTypeOidSz); + idx += contentInfoTypeOidSz; + } + if (contentInfoContentSeqSz > 0) { + XMEMCPY(output + idx, contentInfoContentSeq, contentInfoContentSeqSz); + idx += contentInfoContentSeqSz; + } XMEMCPY(output + idx, compressedDataSeq, compressedDataSeqSz); idx += compressedDataSeqSz; XMEMCPY(output + idx, cmsVersion, cmsVersionSz); @@ -12782,6 +12822,7 @@ int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, word32 outputSz) } /* unwrap and decompress PKCS#7/CMS compressedData object, + * Handles content wrapped compressed data and raw compressed data packet * returned decoded size */ int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* output, word32 outputSz) @@ -12798,29 +12839,47 @@ int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, return BAD_FUNC_ARG; } - /* get ContentInfo SEQUENCE */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; + /* unwarp content surrounding if found */ + { + word32 localIdx = idx; + int err = 0; - if (pkcs7->version != 3) { - /* get ContentInfo contentType */ - if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) - return ASN_PARSE_E; + /* get ContentInfo SEQUENCE */ + if (GetSequence(pkiMsg, &localIdx, &length, pkiMsgSz) < 0) + err = ASN_PARSE_E; - if (contentType != COMPRESSED_DATA) - return ASN_PARSE_E; + if (err == 0 && pkcs7->version != 3) { + /* get ContentInfo contentType */ + if (wc_GetContentType(pkiMsg, &localIdx, &contentType, pkiMsgSz) + < 0) + err = ASN_PARSE_E; + + if (err == 0 && contentType != COMPRESSED_DATA) + err = ASN_PARSE_E; + } + + /* get ContentInfo content EXPLICIT SEQUENCE */ + if (err == 0) { + if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) < 0) + err = ASN_PARSE_E; + } + + if (err == 0) { + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + err = ASN_PARSE_E; + } + + if (err == 0) { + if (GetLength(pkiMsg, &localIdx, &length, pkiMsgSz) < 0) + err = ASN_PARSE_E; + } + + /* successful content unwrap, update index */ + if (err == 0) { + idx = localIdx; + } } - /* get ContentInfo content EXPLICIT SEQUENCE */ - if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) - return ASN_PARSE_E; - - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - /* get CompressedData SEQUENCE */ if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index aebd59594..741b6bf0b 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -30632,9 +30632,11 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, } /* decode envelopedData */ + pkcs7->contentOID = 0; decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, enveloped, envelopedSz, decoded, PKCS7_BUF_SIZE); - if (decodedSz <= 0) { + if (pkcs7->contentOID != testVectors[i].contentOID || + decodedSz <= 0) { wc_PKCS7_Free(pkcs7); ERROR_OUT(-12187, out); } @@ -31584,6 +31586,11 @@ static int getFirmwareKey(PKCS7* pkcs7, byte* key, word32 keySz) envPkcs7->contentOID = FIRMWARE_PKG_DATA; ret = wc_PKCS7_DecodeEnvelopedData(envPkcs7, atr, atrSz, key, keySz); + if (envPkcs7->contentOID != FIRMWARE_PKG_DATA) { + /* the contentOID should have been set to the inner + * FIRMWARE_PKG_DATA content */ + ret = BAD_STATE_E; + } } wc_PKCS7_Free(envPkcs7); } @@ -33319,7 +33326,7 @@ static int pkcs7signed_run_SingleShotVectors( pkcs7->contentSz, encryptedTmp, encryptedTmpSz); - if (encryptedTmpSz < 0) { + if (encryptedTmpSz < 0 || pkcs7->contentOID != COMPRESSED_DATA) { XFREE(encryptedTmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7);