set optional limit on max decompression buffer size

This commit is contained in:
Jacob Barthelmeh
2020-12-08 20:16:27 +07:00
parent fbf56bcf96
commit 081cea7405
4 changed files with 59 additions and 12 deletions

View File

@ -233,6 +233,9 @@
#ifdef HAVE_PKCS7 #ifdef HAVE_PKCS7
#include <wolfssl/wolfcrypt/pkcs7.h> #include <wolfssl/wolfcrypt/pkcs7.h>
#include <wolfssl/wolfcrypt/asn.h> #include <wolfssl/wolfcrypt/asn.h>
#ifdef HAVE_LIBZ
#include <wolfssl/wolfcrypt/compress.h>
#endif
#endif #endif
#ifdef WOLFSSL_SMALL_CERT_VERIFY #ifdef WOLFSSL_SMALL_CERT_VERIFY
@ -24645,7 +24648,7 @@ static void test_wc_PKCS7_DecodeCompressedData(void)
decompressedSz = (int)cert_sz; decompressedSz = (int)cert_sz;
AssertNotNull((pkcs7 = wc_PKCS7_New(heap, devId))); AssertNotNull((pkcs7 = wc_PKCS7_New(heap, devId)));
pkcs7->content = (byte*)cert; pkcs7->content = (byte*)cert_buf;
pkcs7->contentSz = (word32)cert_sz; pkcs7->contentSz = (word32)cert_sz;
pkcs7->contentOID = DATA; pkcs7->contentOID = DATA;
@ -24666,12 +24669,34 @@ static void test_wc_PKCS7_DecodeCompressedData(void)
/* success case */ /* success case */
AssertIntEQ(wc_PKCS7_DecodeCompressedData(pkcs7, out, outSz, AssertIntEQ(wc_PKCS7_DecodeCompressedData(pkcs7, out, outSz,
decompressed, decompressedSz), cert_sz); 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) if (cert_buf)
free(cert_buf); free(cert_buf);
XFREE(decompressed, heap, DYNAMIC_TYPE_TMP_BUFFER);
wc_PKCS7_Free(pkcs7); wc_PKCS7_Free(pkcs7);
printf(resultFmt, passed); printf(resultFmt, passed);
#endif #endif
} }

View File

@ -198,6 +198,8 @@ int wc_DeCompress(byte* out, word32 outSz, const byte* in, word32 inSz)
* is the callers responsibility on successful return. * is the callers responsibility on successful return.
* *
* out gets set to the output buffer created, *out gets overwritten * 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 * memoryType the memory hint to use for 'out' i.e. DYNAMIC_TYPE_TMP_BUFFER
* in compressed input buffer * in compressed input buffer
* inSz size of 'in' 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 * return the decompressed size, creates and grows out buffer as needed
*/ */
int wc_DeCompressDynamic(byte** out, int memoryType, const byte* in, int wc_DeCompressDynamic(byte** out, int max, int memoryType,
word32 inSz, int windowBits, void* heap) const byte* in, word32 inSz, int windowBits, void* heap)
{ {
z_stream stream; z_stream stream;
int result = 0; int result = 0;
int i;
word32 tmpSz = 0; word32 tmpSz = 0;
byte* tmp; byte* tmp;
if (out == NULL || in == NULL) { if (out == NULL || in == NULL) {
return BAD_FUNC_ARG; 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.next_in = (Bytef*)in;
stream.avail_in = (uInt)inSz; stream.avail_in = (uInt)inSz;
/* Check for source > 64K on 16-bit machine: */ /* Check for source > 64K on 16-bit machine: */
if ((uLong)stream.avail_in != inSz) return DECOMPRESS_INIT_E; 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); tmp = (byte*)XMALLOC(tmpSz, heap, memoryType);
if (tmp == NULL) if (tmp == NULL)
return MEMORY_E; 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 /* good chance output buffer ran out of space with Z_BUF_ERROR
try increasing output buffer size */ try increasing output buffer size */
if (result == Z_BUF_ERROR) { if (result == Z_BUF_ERROR) {
word32 newSz = tmpSz * 2; /* double size of tmp buffer */ word32 newSz;
byte* newTmp; byte* newTmp;
if (max > 0 && i >= max) {
WOLFSSL_MSG("Hit max decompress size!");
break;
}
i++;
newSz = tmpSz + inSz;
newTmp = (byte*)XMALLOC(newSz, heap, memoryType); newTmp = (byte*)XMALLOC(newSz, heap, memoryType);
if (newTmp == NULL) { if (newTmp == NULL) {
XFREE(tmp, heap, memoryType); WOLFSSL_MSG("Memory error with increasing buffer size");
return MEMORY_E; break;
} }
XMEMCPY(newTmp, tmp, tmpSz); XMEMCPY(newTmp, tmp, tmpSz);
XFREE(tmp, heap, memoryType); XFREE(tmp, heap, memoryType);

View File

@ -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 #ifndef NO_PKCS7_STREAM
#define MAX_PKCS7_STREAM_BUFFER 256 #define MAX_PKCS7_STREAM_BUFFER 256
@ -12661,7 +12669,8 @@ int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
/* decompress content */ /* decompress content */
ret = wc_DeCompressDynamic(&decompressed, DYNAMIC_TYPE_PKCS7, 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) { if (ret < 0) {
return ret; return ret;
} }

View File

@ -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(byte*, word32, const byte*, word32);
WOLFSSL_API int wc_DeCompress_ex(byte* out, word32 outSz, const byte* in, WOLFSSL_API int wc_DeCompress_ex(byte* out, word32 outSz, const byte* in,
word32 inSz, int windowBits); word32 inSz, int windowBits);
WOLFSSL_API int wc_DeCompressDynamic(byte** out, int memoryType, const byte* in, WOLFSSL_API int wc_DeCompressDynamic(byte** out, int max, int memoryType,
word32 inSz, int windowBits, void* heap); const byte* in, word32 inSz, int windowBits, void* heap);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */