diff --git a/tests/api.c b/tests/api.c index b13a4cc3b..9b1412a4a 100644 --- a/tests/api.c +++ b/tests/api.c @@ -233,6 +233,9 @@ #ifdef HAVE_PKCS7 #include #include + #ifdef HAVE_LIBZ + #include + #endif #endif #ifdef WOLFSSL_SMALL_CERT_VERIFY @@ -24645,7 +24648,7 @@ static void test_wc_PKCS7_DecodeCompressedData(void) decompressedSz = (int)cert_sz; AssertNotNull((pkcs7 = wc_PKCS7_New(heap, devId))); - pkcs7->content = (byte*)cert; + pkcs7->content = (byte*)cert_buf; pkcs7->contentSz = (word32)cert_sz; pkcs7->contentOID = DATA; @@ -24666,12 +24669,34 @@ static void test_wc_PKCS7_DecodeCompressedData(void) /* success case */ AssertIntEQ(wc_PKCS7_DecodeCompressedData(pkcs7, out, outSz, decompressed, decompressedSz), cert_sz); - AssertIntEQ(XMEMCMP(decompressed, cert, cert_sz), 0); + AssertIntEQ(XMEMCMP(decompressed, cert_buf, cert_sz), 0); + XFREE(decompressed, heap, DYNAMIC_TYPE_TMP_BUFFER); + decompressed = NULL; + + /* test decompression function with different 'max' inputs */ + outSz = sizeof(out); + AssertIntGT((outSz = wc_Compress(out, outSz, cert_buf, (word32)cert_sz, 0)), + 0); + AssertIntLT(wc_DeCompressDynamic(&decompressed, 1, DYNAMIC_TYPE_TMP_BUFFER, + out, outSz, 0, heap), 0); + AssertNull(decompressed); + AssertIntGT(wc_DeCompressDynamic(&decompressed, -1, DYNAMIC_TYPE_TMP_BUFFER, + out, outSz, 0, heap), 0); + AssertNotNull(decompressed); + AssertIntEQ(XMEMCMP(decompressed, cert_buf, cert_sz), 0); + XFREE(decompressed, heap, DYNAMIC_TYPE_TMP_BUFFER); + decompressed = NULL; + + AssertIntGT(wc_DeCompressDynamic(&decompressed, DYNAMIC_TYPE_TMP_BUFFER, 5, + out, outSz, 0, heap), 0); + AssertNotNull(decompressed); + AssertIntEQ(XMEMCMP(decompressed, cert_buf, cert_sz), 0); + XFREE(decompressed, heap, DYNAMIC_TYPE_TMP_BUFFER); if (cert_buf) free(cert_buf); - XFREE(decompressed, heap, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); + printf(resultFmt, passed); #endif } diff --git a/wolfcrypt/src/compress.c b/wolfcrypt/src/compress.c index 24397d5d3..5a91d851f 100644 --- a/wolfcrypt/src/compress.c +++ b/wolfcrypt/src/compress.c @@ -198,6 +198,8 @@ int wc_DeCompress(byte* out, word32 outSz, const byte* in, word32 inSz) * is the callers responsibility on successful return. * * out gets set to the output buffer created, *out gets overwritten + * max is the max decompression multiplier, i.e if 2 then max out size created + * would be 2*inSz, if set to -1 then there is no limit on out buffer size * memoryType the memory hint to use for 'out' i.e. DYNAMIC_TYPE_TMP_BUFFER * in compressed input buffer * inSz size of 'in' buffer @@ -206,24 +208,27 @@ int wc_DeCompress(byte* out, word32 outSz, const byte* in, word32 inSz) * * return the decompressed size, creates and grows out buffer as needed */ -int wc_DeCompressDynamic(byte** out, int memoryType, const byte* in, - word32 inSz, int windowBits, void* heap) +int wc_DeCompressDynamic(byte** out, int max, int memoryType, + const byte* in, word32 inSz, int windowBits, void* heap) { z_stream stream; int result = 0; + int i; word32 tmpSz = 0; byte* tmp; if (out == NULL || in == NULL) { return BAD_FUNC_ARG; } + i = (max == 1)? 1 : 2; /* start with output buffer twice the size of input + * unless max was set to 1 */ stream.next_in = (Bytef*)in; stream.avail_in = (uInt)inSz; /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != inSz) return DECOMPRESS_INIT_E; - tmpSz = inSz * 2; /* start with output buffer twice the size of input */ + tmpSz = inSz * i; tmp = (byte*)XMALLOC(tmpSz, heap, memoryType); if (tmp == NULL) return MEMORY_E; @@ -259,12 +264,20 @@ int wc_DeCompressDynamic(byte** out, int memoryType, const byte* in, /* good chance output buffer ran out of space with Z_BUF_ERROR try increasing output buffer size */ if (result == Z_BUF_ERROR) { - word32 newSz = tmpSz * 2; /* double size of tmp buffer */ + word32 newSz; byte* newTmp; + + if (max > 0 && i >= max) { + WOLFSSL_MSG("Hit max decompress size!"); + break; + } + i++; + + newSz = tmpSz + inSz; newTmp = (byte*)XMALLOC(newSz, heap, memoryType); if (newTmp == NULL) { - XFREE(tmp, heap, memoryType); - return MEMORY_E; + WOLFSSL_MSG("Memory error with increasing buffer size"); + break; } XMEMCPY(newTmp, tmp, tmpSz); XFREE(tmp, heap, memoryType); diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 61894dc29..e3d4e2af3 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -67,6 +67,14 @@ struct PKCS7SignerInfo { }; +#ifndef WOLFSSL_PKCS7_MAX_DECOMPRESSION + /* 1031 comes from "Maximum Compression Factor" in the zlib tech document, + * typical compression is from 2:1 to 5:1 but there is rare cases where + * 1030.3:1 could happen (like a file with all 0's) + */ + #define WOLFSSL_PKCS7_MAX_DECOMPRESSION 1031 +#endif + #ifndef NO_PKCS7_STREAM #define MAX_PKCS7_STREAM_BUFFER 256 @@ -12661,7 +12669,8 @@ int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, /* decompress content */ ret = wc_DeCompressDynamic(&decompressed, DYNAMIC_TYPE_PKCS7, - &pkiMsg[idx], length, 0, pkcs7->heap); + WOLFSSL_PKCS7_MAX_DECOMPRESSION, &pkiMsg[idx], length, 0, + pkcs7->heap); if (ret < 0) { return ret; } diff --git a/wolfssl/wolfcrypt/compress.h b/wolfssl/wolfcrypt/compress.h index 3cfaa58ae..b3a98ac82 100644 --- a/wolfssl/wolfcrypt/compress.h +++ b/wolfssl/wolfcrypt/compress.h @@ -47,8 +47,8 @@ WOLFSSL_API int wc_Compress_ex(byte* out, word32 outSz, const byte* in, WOLFSSL_API int wc_DeCompress(byte*, word32, const byte*, word32); WOLFSSL_API int wc_DeCompress_ex(byte* out, word32 outSz, const byte* in, word32 inSz, int windowBits); -WOLFSSL_API int wc_DeCompressDynamic(byte** out, int memoryType, const byte* in, - word32 inSz, int windowBits, void* heap); +WOLFSSL_API int wc_DeCompressDynamic(byte** out, int max, int memoryType, + const byte* in, word32 inSz, int windowBits, void* heap); #ifdef __cplusplus } /* extern "C" */