diff --git a/certs/pkcs7-indef-len-signed-data.bin b/certs/pkcs7-indef-len-signed-data.bin new file mode 100644 index 00000000000..d03715ec180 Binary files /dev/null and b/certs/pkcs7-indef-len-signed-data.bin differ diff --git a/tests/api/test_pkcs7.c b/tests/api/test_pkcs7.c index 78ae915e8d2..b5404dccd56 100644 --- a/tests/api/test_pkcs7.c +++ b/tests/api/test_pkcs7.c @@ -4856,3 +4856,47 @@ int test_wc_PKCS7_VerifySignedData_PKCS7ContentSeq(void) return EXPECT_RESULT(); } +/* + * Test PKCS7 VerifySignedData with indefinite-length BER-encoded SignedData + * containing mismatched nesting depth. Verifies bounds checking in the + * end-of-content octet verification loop in streaming mode. + */ +int test_wc_PKCS7_VerifySignedData_IndefLenOOB(void) +{ + EXPECT_DECLS; +#if defined(HAVE_PKCS7) && !defined(NO_PKCS7_STREAM) && !defined(NO_FILESYSTEM) + PKCS7* pkcs7 = NULL; + char fName[] = "./certs/pkcs7-indef-len-signed-data.bin"; + XFILE f = XBADFILE; + byte* der = NULL; + word32 derSz = 0; + + /* PKCS#7 SignedData with indefinite-length BER encoding where the + * nesting depth exceeds the available end-of-content octets. */ + ExpectTrue((f = XFOPEN(fName, "rb")) != XBADFILE); + if (f != XBADFILE) { + XFSEEK(f, 0, XSEEK_END); + derSz = (word32)XFTELL(f); + XFSEEK(f, 0, XSEEK_SET); + ExpectNotNull(der = (byte*)XMALLOC(derSz, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER)); + if (der != NULL) { + ExpectTrue(XFREAD(der, 1, derSz, f) == derSz); + } + XFCLOSE(f); + } + + if (der != NULL) { + /* Should return a parse error for malformed input */ + ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); + ExpectIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); + ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + ExpectIntNE(wc_PKCS7_VerifySignedData(pkcs7, der, derSz), 0); + wc_PKCS7_Free(pkcs7); + } + + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + +#endif /* HAVE_PKCS7 && !NO_PKCS7_STREAM && !NO_FILESYSTEM */ + return EXPECT_RESULT(); +} diff --git a/tests/api/test_pkcs7.h b/tests/api/test_pkcs7.h index 21e923011b3..084744d43c6 100644 --- a/tests/api/test_pkcs7.h +++ b/tests/api/test_pkcs7.h @@ -58,6 +58,7 @@ int test_wc_PKCS7_SetOriDecryptCtx(void); int test_wc_PKCS7_DecodeCompressedData(void); int test_wc_PKCS7_DecodeEnvelopedData_multiple_recipients(void); int test_wc_PKCS7_VerifySignedData_PKCS7ContentSeq(void); +int test_wc_PKCS7_VerifySignedData_IndefLenOOB(void); #define TEST_PKCS7_DECLS \ @@ -92,7 +93,8 @@ int test_wc_PKCS7_VerifySignedData_PKCS7ContentSeq(void); TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_Degenerate), \ TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_BER), \ TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_NoDefaultSignedAttribs), \ - TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_VerifySignedData_PKCS7ContentSeq) + TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_VerifySignedData_PKCS7ContentSeq), \ + TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_VerifySignedData_IndefLenOOB) #define TEST_PKCS7_ENCRYPTED_DATA_DECLS \ TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_DecodeEnvelopedData_stream), \ diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 5a02c97d219..ac1bd0474e6 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -6897,6 +6897,10 @@ static int PKCS7_VerifySignedData(wc_PKCS7* pkcs7, const byte* hashBuf, word32 sz = (word32)pkcs7->stream->cntIdfCnt * ASN_INDEF_END_SZ; localIdx = idx; for (i = 0; i < sz; i++) { + if (localIdx + i >= pkiMsg2Sz) { + ret = ASN_PARSE_E; + break; + } if (pkiMsg2[localIdx + i] == 0) continue; else {