fix for PKCS7 decompress

This commit is contained in:
Jacob Barthelmeh
2020-12-03 18:57:25 +07:00
parent 69d642206d
commit fbf56bcf96
4 changed files with 166 additions and 9 deletions

View File

@ -24622,6 +24622,60 @@ static void test_wc_PKCS7_SetOriDecryptCtx (void)
printf(resultFmt, passed);
#endif
}
static void test_wc_PKCS7_DecodeCompressedData(void)
{
#if defined(HAVE_PKCS7) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) \
&& !defined(NO_AES) && defined(HAVE_LIBZ)
PKCS7* pkcs7;
void* heap = NULL;
byte out[3072];
byte *decompressed;
int outSz, decompressedSz;
const char* cert = "./certs/client-cert.pem";
byte* cert_buf = NULL;
size_t cert_sz = 0;
printf(testingFmt, "wc_PKCS7_DecodeCompressedData()");
AssertIntEQ(load_file(cert, &cert_buf, &cert_sz), 0);
AssertNotNull((decompressed =
(byte*)XMALLOC(cert_sz, heap, DYNAMIC_TYPE_TMP_BUFFER)));
decompressedSz = (int)cert_sz;
AssertNotNull((pkcs7 = wc_PKCS7_New(heap, devId)));
pkcs7->content = (byte*)cert;
pkcs7->contentSz = (word32)cert_sz;
pkcs7->contentOID = DATA;
AssertIntGT((outSz = wc_PKCS7_EncodeCompressedData(pkcs7, out,
sizeof(out))), 0);
wc_PKCS7_Free(pkcs7);
/* compressed key should be smaller than when started */
AssertIntLT(outSz, cert_sz);
/* test decompression */
AssertNotNull((pkcs7 = wc_PKCS7_New(heap, devId)));
/* fail case with out buffer too small */
AssertIntLT(wc_PKCS7_DecodeCompressedData(pkcs7, out, outSz,
decompressed, outSz), 0);
/* success case */
AssertIntEQ(wc_PKCS7_DecodeCompressedData(pkcs7, out, outSz,
decompressed, decompressedSz), cert_sz);
AssertIntEQ(XMEMCMP(decompressed, cert, cert_sz), 0);
if (cert_buf)
free(cert_buf);
XFREE(decompressed, heap, DYNAMIC_TYPE_TMP_BUFFER);
wc_PKCS7_Free(pkcs7);
printf(resultFmt, passed);
#endif
}
static void test_wc_i2d_PKCS12(void)
{
#if !defined(NO_ASN) && !defined(NO_PWDBASED) && defined(HAVE_PKCS12) \
@ -39664,6 +39718,7 @@ void ApiTest(void)
test_wc_PKCS7_NoDefaultSignedAttribs();
test_wc_PKCS7_SetOriEncryptCtx();
test_wc_PKCS7_SetOriDecryptCtx();
test_wc_PKCS7_DecodeCompressedData();
test_wc_i2d_PKCS12();

View File

@ -194,5 +194,112 @@ int wc_DeCompress(byte* out, word32 outSz, const byte* in, word32 inSz)
}
/* Decompress the input buffer and create output buffer. Free'ing 'out' buffer
* is the callers responsibility on successful return.
*
* out gets set to the output buffer created, *out gets overwritten
* memoryType the memory hint to use for 'out' i.e. DYNAMIC_TYPE_TMP_BUFFER
* in compressed input buffer
* inSz size of 'in' buffer
* windowBits decompression behavior flag (can be 0)
* heap hint to use when mallocing 'out' buffer
*
* 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)
{
z_stream stream;
int result = 0;
word32 tmpSz = 0;
byte* tmp;
if (out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
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 */
tmp = (byte*)XMALLOC(tmpSz, heap, memoryType);
if (tmp == NULL)
return MEMORY_E;
stream.next_out = tmp;
stream.avail_out = (uInt)tmpSz;
if ((uLong)stream.avail_out != tmpSz) return DECOMPRESS_INIT_E;
stream.zalloc = (alloc_func)myAlloc;
stream.zfree = (free_func)myFree;
stream.opaque = (voidpf)0;
if (inflateInit2(&stream, DEFLATE_DEFAULT_WINDOWBITS | windowBits) != Z_OK) {
return DECOMPRESS_INIT_E;
}
/*
Wanted to use inflateGetHeader here for uncompressed size but
structure gz_headerp does not contain the ISIZE from RFC1952
gz_headerp header;
inflateGetHeader(&stream, &header);
*/
/* loop through doing the decompression block by block to get full size */
do {
result = inflate(&stream, Z_BLOCK);
if (result == Z_STREAM_END) {
/* hit end of decompression */
break;
}
/* 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 */
byte* newTmp;
newTmp = (byte*)XMALLOC(newSz, heap, memoryType);
if (newTmp == NULL) {
XFREE(tmp, heap, memoryType);
return MEMORY_E;
}
XMEMCPY(newTmp, tmp, tmpSz);
XFREE(tmp, heap, memoryType);
tmp = newTmp;
stream.next_out = tmp + stream.total_out;
stream.avail_out = stream.avail_out + (uInt)tmpSz;
tmpSz = newSz;
result = inflate(&stream, Z_BLOCK);
}
} while (result == Z_OK);
if (result == Z_STREAM_END) {
result = (int)stream.total_out;
*out = (byte*)XMALLOC(result, heap, memoryType);
if (*out != NULL) {
XMEMCPY(*out, tmp, result);
}
else {
result = MEMORY_E;
}
}
else {
result = DECOMPRESS_E;
}
if (inflateEnd(&stream) != Z_OK)
result = DECOMPRESS_E;
if (tmp != NULL) {
XFREE(tmp, heap, memoryType);
tmp = NULL;
}
return result;
}
#endif /* HAVE_LIBZ */

View File

@ -12659,17 +12659,10 @@ int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
return ASN_PARSE_E;
/* allocate space for decompressed data */
decompressed = (byte*)XMALLOC(length, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
if (decompressed == NULL) {
WOLFSSL_MSG("Error allocating memory for CMS decompression buffer");
return MEMORY_E;
}
/* decompress content */
ret = wc_DeCompress(decompressed, length, &pkiMsg[idx], length);
ret = wc_DeCompressDynamic(&decompressed, DYNAMIC_TYPE_PKCS7,
&pkiMsg[idx], length, 0, pkcs7->heap);
if (ret < 0) {
XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
return ret;
}
decompressedSz = (word32)ret;

View File

@ -47,6 +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);
#ifdef __cplusplus
} /* extern "C" */