forked from wolfSSL/wolfssl
Merge pull request #3533 from JacobBarthelmeh/PKCS7
fix for PKCS7 decompress
This commit is contained in:
80
tests/api.c
80
tests/api.c
@@ -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
|
||||||
@@ -24622,6 +24625,82 @@ static void test_wc_PKCS7_SetOriDecryptCtx (void)
|
|||||||
printf(resultFmt, passed);
|
printf(resultFmt, passed);
|
||||||
#endif
|
#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_buf;
|
||||||
|
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_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);
|
||||||
|
wc_PKCS7_Free(pkcs7);
|
||||||
|
|
||||||
|
printf(resultFmt, passed);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void test_wc_i2d_PKCS12(void)
|
static void test_wc_i2d_PKCS12(void)
|
||||||
{
|
{
|
||||||
#if !defined(NO_ASN) && !defined(NO_PWDBASED) && defined(HAVE_PKCS12) \
|
#if !defined(NO_ASN) && !defined(NO_PWDBASED) && defined(HAVE_PKCS12) \
|
||||||
@@ -39832,6 +39911,7 @@ void ApiTest(void)
|
|||||||
test_wc_PKCS7_NoDefaultSignedAttribs();
|
test_wc_PKCS7_NoDefaultSignedAttribs();
|
||||||
test_wc_PKCS7_SetOriEncryptCtx();
|
test_wc_PKCS7_SetOriEncryptCtx();
|
||||||
test_wc_PKCS7_SetOriDecryptCtx();
|
test_wc_PKCS7_SetOriDecryptCtx();
|
||||||
|
test_wc_PKCS7_DecodeCompressedData();
|
||||||
|
|
||||||
|
|
||||||
test_wc_i2d_PKCS12();
|
test_wc_i2d_PKCS12();
|
||||||
|
@@ -194,5 +194,125 @@ 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
|
||||||
|
* 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
|
||||||
|
* 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 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 * i;
|
||||||
|
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;
|
||||||
|
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) {
|
||||||
|
WOLFSSL_MSG("Memory error with increasing buffer size");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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 */
|
#endif /* HAVE_LIBZ */
|
||||||
|
|
||||||
|
@@ -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
|
||||||
@@ -12659,17 +12667,10 @@ int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
|
|||||||
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
return ASN_PARSE_E;
|
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 */
|
/* decompress content */
|
||||||
ret = wc_DeCompress(decompressed, length, &pkiMsg[idx], length);
|
ret = wc_DeCompressDynamic(&decompressed, WOLFSSL_PKCS7_MAX_DECOMPRESSION,
|
||||||
|
DYNAMIC_TYPE_PKCS7, &pkiMsg[idx], length, 0, pkcs7->heap);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
decompressedSz = (word32)ret;
|
decompressedSz = (word32)ret;
|
||||||
|
@@ -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(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 max, int memoryType,
|
||||||
|
const byte* in, word32 inSz, int windowBits, void* heap);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
Reference in New Issue
Block a user