forked from wolfSSL/wolfssl
stream of PKCS7 decode encrypted
This commit is contained in:
committed by
David Garske
parent
40ef246b1f
commit
83a150c4df
@ -15022,6 +15022,7 @@ static void test_wc_PKCS7_EncodeData (void)
|
||||
|
||||
XMEMSET(output, 0, sizeof(output));
|
||||
|
||||
pkcs7.isDynamic = 0;
|
||||
AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, INVALID_DEVID), 0);
|
||||
|
||||
AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, (byte*)cert, certSz), 0);
|
||||
|
@ -281,6 +281,9 @@ const char* wc_GetErrorString(int error)
|
||||
case PKCS7_RECIP_E:
|
||||
return "PKCS#7 error: no matching recipient found";
|
||||
|
||||
case WC_PKCS7_WANT_READ_E:
|
||||
return "PKCS#7 operations wants more input, call again";
|
||||
|
||||
case FIPS_NOT_ALLOWED_E:
|
||||
return "FIPS mode not allowed error";
|
||||
|
||||
|
@ -58,6 +58,145 @@ typedef enum {
|
||||
WC_PKCS7_DECODE
|
||||
} pkcs7Direction;
|
||||
|
||||
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
|
||||
#define MAX_PKCS7_STREAM_BUFFER 256
|
||||
typedef struct PKCS7State {
|
||||
byte* tmpCert;
|
||||
word32 varOne;
|
||||
word32 varTwo;
|
||||
word32 varThree;
|
||||
word32 vers;
|
||||
word32 idx; /* index read into current input buffer */
|
||||
word32 maxLen; /* sanity cap on maximum amount of data to allow
|
||||
* needed for GetSequence and other calls */
|
||||
word32 length; /* amount of data stored */
|
||||
word32 expected; /* next amount of data expected, if needed */
|
||||
word32 totalRd; /* total amount of bytes read */
|
||||
byte hasAtrib:1;
|
||||
byte buffer[4096];
|
||||
byte tmpIv[MAX_CONTENT_IV_SIZE]; /* store IV if needed */
|
||||
} PKCS7State;
|
||||
|
||||
|
||||
enum PKCS7_MaxLen {
|
||||
PKCS7_DEFAULT_PEEK = 0,
|
||||
PKCS7_SEQ_PEEK
|
||||
};
|
||||
|
||||
/* creates a PKCS7State structure and returns 0 on success */
|
||||
static int wc_PKCS7_CreateStream(PKCS7* pkcs7)
|
||||
{
|
||||
WOLFSSL_MSG("creating PKCS7 stream structure");
|
||||
pkcs7->stream = (PKCS7State*)XMALLOC(sizeof(PKCS7State), pkcs7->heap,
|
||||
DYNAMIC_TYPE_PKCS7);
|
||||
if (pkcs7->stream == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(pkcs7->stream, 0, sizeof(PKCS7State));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void wc_PKCS7_ResetStream(PKCS7* pkcs7)
|
||||
{
|
||||
/* free any buffers that may be allocated */
|
||||
|
||||
/* reset values */
|
||||
XMEMSET(pkcs7->stream, 0, sizeof(PKCS7State));
|
||||
}
|
||||
|
||||
|
||||
static void wc_PKCS7_FreeStream(PKCS7* pkcs7)
|
||||
{
|
||||
if (pkcs7 != NULL && pkcs7->stream != NULL) {
|
||||
wc_PKCS7_ResetStream(pkcs7);
|
||||
XFREE(pkcs7->stream, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* pt gets set to the buffer that is holding data in the case that stream struct
|
||||
* is used.
|
||||
*
|
||||
* returns 0 on success
|
||||
*/
|
||||
static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz,
|
||||
word32 expected, byte** pt, word32* idx)
|
||||
{
|
||||
word32 rdSz;
|
||||
|
||||
if (inSz >= expected && pkcs7->stream->length == 0) {
|
||||
/* storing input buffer is not needed */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* is there enough stored in buffer already? */
|
||||
if (pkcs7->stream->length >= expected) {
|
||||
*idx = 0;
|
||||
*pt = pkcs7->stream->buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check if all data has been read from input */
|
||||
rdSz = pkcs7->stream->idx;
|
||||
if (rdSz >= inSz) {
|
||||
/* no more input to read */
|
||||
pkcs7->stream->idx = 0;
|
||||
return WC_PKCS7_WANT_READ_E;
|
||||
}
|
||||
|
||||
if (inSz - rdSz > 0 && pkcs7->stream->length < expected) {
|
||||
int len = min(inSz - rdSz, expected - pkcs7->stream->length);
|
||||
XMEMCPY(pkcs7->stream->buffer + pkcs7->stream->length, in + rdSz, len);
|
||||
pkcs7->stream->length += len;
|
||||
pkcs7->stream->idx += len;
|
||||
pkcs7->stream->totalRd += len;
|
||||
}
|
||||
|
||||
if (pkcs7->stream->length < expected) {
|
||||
pkcs7->stream->idx = 0;
|
||||
return WC_PKCS7_WANT_READ_E;
|
||||
}
|
||||
|
||||
/* read from stored buffer */
|
||||
*idx = 0;
|
||||
*pt = pkcs7->stream->buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Does two things
|
||||
* 1) Tries to get the length from current buffer and set it as max length
|
||||
* 2) Retrieves the set max length
|
||||
*
|
||||
* if no flag value is set then the stored max length is returned.
|
||||
* returns length found on success and defSz if no stored data is found
|
||||
*/
|
||||
static word32 wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, word32 defSz)
|
||||
{
|
||||
/* check there is a buffer to read from */
|
||||
if (pkcs7 && pkcs7->stream->length > 0) {
|
||||
int length = 0, ret;
|
||||
word32 idx = 0;
|
||||
if (flag & PKCS7_SEQ_PEEK) {
|
||||
if ((ret = GetSequence(pkcs7->stream->buffer, &idx,
|
||||
&length, (word32)-1)) < 0) {
|
||||
return ret;
|
||||
}
|
||||
pkcs7->stream->maxLen = length + idx;
|
||||
}
|
||||
return pkcs7->stream->maxLen;
|
||||
}
|
||||
|
||||
if (pkcs7->stream->maxLen == 0) {
|
||||
pkcs7->stream->maxLen = defSz;
|
||||
}
|
||||
return defSz;
|
||||
}
|
||||
#endif /* NO_PKCS7_STREAM */
|
||||
|
||||
#define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ + \
|
||||
MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE)
|
||||
|
||||
@ -595,6 +734,10 @@ void wc_PKCS7_Free(PKCS7* pkcs7)
|
||||
if (pkcs7 == NULL)
|
||||
return;
|
||||
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
wc_PKCS7_FreeStream(pkcs7);
|
||||
#endif
|
||||
|
||||
wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap);
|
||||
wc_PKCS7_FreeCertSet(pkcs7);
|
||||
|
||||
@ -6774,7 +6917,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* pkiMsg,
|
||||
word32 pkiMsgSz, word32* idx,
|
||||
int type)
|
||||
{
|
||||
int version, length;
|
||||
int version, length, ret;
|
||||
word32 contentType;
|
||||
|
||||
if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || idx == NULL)
|
||||
@ -6859,6 +7002,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* pkiMsg,
|
||||
if (GetSet(pkiMsg, idx, &length, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
(void)ret;
|
||||
return length;
|
||||
}
|
||||
|
||||
@ -8076,20 +8220,24 @@ static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg,
|
||||
|
||||
|
||||
/* unwrap and decrypt PKCS#7/CMS encrypted-data object, returned decoded size */
|
||||
int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
|
||||
int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz,
|
||||
byte* output, word32 outputSz)
|
||||
{
|
||||
int ret, version, length, haveAttribs;
|
||||
word32 idx = 0;
|
||||
int ret = 0, version, length, haveAttribs;
|
||||
word32 idx = 0, tmpIdx = 0;
|
||||
word32 contentType, encOID;
|
||||
|
||||
int expBlockSz;
|
||||
byte tmpIv[MAX_CONTENT_IV_SIZE];
|
||||
int expBlockSz = 0;
|
||||
byte tmpIvBuf[MAX_CONTENT_IV_SIZE];
|
||||
byte *tmpIv = tmpIvBuf;
|
||||
|
||||
int encryptedContentSz;
|
||||
byte padLen;
|
||||
byte* encryptedContent = NULL;
|
||||
|
||||
byte* pkiMsg = in;
|
||||
word32 pkiMsgSz = inSz;
|
||||
|
||||
if (pkcs7 == NULL || pkcs7->encryptionKey == NULL ||
|
||||
pkcs7->encryptionKeySz == 0)
|
||||
return BAD_FUNC_ARG;
|
||||
@ -8098,119 +8246,343 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
|
||||
output == NULL || outputSz == 0)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
/* read past ContentInfo, verify type is encrypted-data */
|
||||
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (contentType != ENCRYPTED_DATA) {
|
||||
WOLFSSL_MSG("PKCS#7 input not of type EncryptedData");
|
||||
return PKCS7_OID_E;
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
if (pkcs7->stream == NULL) {
|
||||
if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
|
||||
return ASN_PARSE_E;
|
||||
switch (pkcs7->state) {
|
||||
case WC_PKCS7_START:
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ +
|
||||
MAX_ALGO_SZ, &pkiMsg, &idx)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz);
|
||||
#endif
|
||||
|
||||
/* remove EncryptedData and version */
|
||||
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
/* read past ContentInfo, verify type is encrypted-data */
|
||||
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
/* get version, check later */
|
||||
haveAttribs = 0;
|
||||
if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType,
|
||||
pkiMsgSz) < 0)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
/* remove EncryptedContentInfo */
|
||||
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
if (ret == 0 && contentType != ENCRYPTED_DATA) {
|
||||
WOLFSSL_MSG("PKCS#7 input not of type EncryptedData");
|
||||
ret = PKCS7_OID_E;
|
||||
}
|
||||
|
||||
if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
if (ret != 0) break;
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
if (pkcs7->stream->length > 0) {
|
||||
if (pkcs7->stream->length < idx) {
|
||||
ret = BUFFER_E;
|
||||
break;
|
||||
}
|
||||
XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx,
|
||||
pkcs7->stream->length - idx);
|
||||
pkcs7->stream->length -= idx;
|
||||
}
|
||||
else {
|
||||
pkcs7->stream->totalRd += idx - tmpIdx;
|
||||
tmpIdx = idx;
|
||||
}
|
||||
#endif
|
||||
pkcs7->state = WC_PKCS7_STAGE2;
|
||||
/* end of stage 1 */
|
||||
|
||||
if (GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
case WC_PKCS7_STAGE2:
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
|
||||
MAX_LENGTH_SZ + MAX_SEQ_SZ + ASN_TAG_SZ, &pkiMsg,
|
||||
&idx)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID);
|
||||
if (expBlockSz < 0)
|
||||
return expBlockSz;
|
||||
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz);
|
||||
#endif
|
||||
if (ret == 0 && pkiMsg[idx++] != (ASN_CONSTRUCTED |
|
||||
ASN_CONTEXT_SPECIFIC | 0))
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
/* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
|
||||
if (pkiMsg[idx++] != ASN_OCTET_STRING)
|
||||
return ASN_PARSE_E;
|
||||
if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
/* remove EncryptedData and version */
|
||||
if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
if (length != expBlockSz) {
|
||||
WOLFSSL_MSG("Incorrect IV length, must be of content alg block size");
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
if (ret != 0) break;
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
if (pkcs7->stream->length > 0) {
|
||||
if (pkcs7->stream->length < idx) {
|
||||
ret = BUFFER_E;
|
||||
break;
|
||||
}
|
||||
XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx,
|
||||
pkcs7->stream->length - idx);
|
||||
pkcs7->stream->length -= idx;
|
||||
}
|
||||
else {
|
||||
pkcs7->stream->totalRd += idx - tmpIdx;
|
||||
tmpIdx = idx;
|
||||
}
|
||||
#endif
|
||||
pkcs7->state = WC_PKCS7_STAGE3;
|
||||
/* end of stage 2 */
|
||||
|
||||
XMEMCPY(tmpIv, &pkiMsg[idx], length);
|
||||
idx += length;
|
||||
case WC_PKCS7_STAGE3:
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
|
||||
MAX_VERSION_SZ + MAX_SEQ_SZ + MAX_ALGO_SZ * 2,
|
||||
&pkiMsg, &idx)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* read encryptedContent, cont[0] */
|
||||
if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0))
|
||||
return ASN_PARSE_E;
|
||||
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz);
|
||||
#endif
|
||||
/* get version, check later */
|
||||
haveAttribs = 0;
|
||||
if (ret == 0 && GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0)
|
||||
return ASN_PARSE_E;
|
||||
/* remove EncryptedContentInfo */
|
||||
if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap,
|
||||
DYNAMIC_TYPE_PKCS7);
|
||||
if (encryptedContent == NULL)
|
||||
return MEMORY_E;
|
||||
if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType,
|
||||
pkiMsgSz) < 0)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
|
||||
idx += encryptedContentSz;
|
||||
if (ret == 0 && (ret = GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType,
|
||||
pkiMsgSz)) < 0)
|
||||
ret = ASN_PARSE_E;
|
||||
if (ret == 0 && (expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID)) < 0)
|
||||
ret = expBlockSz;
|
||||
|
||||
/* decrypt encryptedContent */
|
||||
ret = wc_PKCS7_DecryptContent(encOID, pkcs7->encryptionKey,
|
||||
if (ret != 0) break;
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
/* store expBlockSz for later */
|
||||
pkcs7->stream->varOne = expBlockSz;
|
||||
pkcs7->stream->varTwo = encOID;
|
||||
|
||||
if (pkcs7->stream->length > 0) {
|
||||
if (pkcs7->stream->length < idx) {
|
||||
ret = BUFFER_E;
|
||||
break;
|
||||
}
|
||||
XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx,
|
||||
pkcs7->stream->length - idx);
|
||||
pkcs7->stream->length -= idx;
|
||||
}
|
||||
else {
|
||||
pkcs7->stream->totalRd += idx - tmpIdx;
|
||||
tmpIdx = idx;
|
||||
}
|
||||
|
||||
/* store version for later */
|
||||
pkcs7->stream->vers = version;
|
||||
#endif
|
||||
pkcs7->state = WC_PKCS7_STAGE4;
|
||||
/* end of stage 3 */
|
||||
|
||||
/* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
|
||||
case WC_PKCS7_STAGE4:
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
|
||||
ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz);
|
||||
|
||||
/* restore saved variables */
|
||||
expBlockSz = pkcs7->stream->varOne;
|
||||
#endif
|
||||
if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
if (ret == 0 && length != expBlockSz) {
|
||||
WOLFSSL_MSG("Incorrect IV length, must be of content alg block size");
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
|
||||
if (ret != 0) break;
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
/* next chunk of data expected should have the IV */
|
||||
pkcs7->stream->expected = length;
|
||||
|
||||
if (pkcs7->stream->length > 0) {
|
||||
if (pkcs7->stream->length < idx) {
|
||||
ret = BUFFER_E;
|
||||
break;
|
||||
}
|
||||
XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx,
|
||||
pkcs7->stream->length - idx);
|
||||
pkcs7->stream->length -= idx;
|
||||
}
|
||||
else {
|
||||
pkcs7->stream->totalRd += idx - tmpIdx;
|
||||
tmpIdx = idx;
|
||||
}
|
||||
#endif
|
||||
pkcs7->state = WC_PKCS7_STAGE5;
|
||||
/* end of stage 4 */
|
||||
|
||||
case WC_PKCS7_STAGE5:
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
|
||||
pkcs7->stream->expected + ASN_TAG_SZ +
|
||||
MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz);
|
||||
|
||||
/* restore saved variables */
|
||||
expBlockSz = pkcs7->stream->varOne;
|
||||
|
||||
/* use IV buffer from stream structure */
|
||||
tmpIv = pkcs7->stream->tmpIv;
|
||||
#endif
|
||||
XMEMCPY(tmpIv, &pkiMsg[idx], length);
|
||||
idx += length;
|
||||
/* read encryptedContent, cont[0] */
|
||||
if (ret == 0 && pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0))
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz,
|
||||
pkiMsgSz) <= 0)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
/* next chunk of data should contain encrypted content */
|
||||
pkcs7->stream->varThree = encryptedContentSz;
|
||||
if (pkcs7->stream->length > 0) {
|
||||
if (pkcs7->stream->length < idx) {
|
||||
ret = BUFFER_E;
|
||||
break;
|
||||
}
|
||||
XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx,
|
||||
pkcs7->stream->length - idx);
|
||||
pkcs7->stream->length -= idx;
|
||||
}
|
||||
else {
|
||||
pkcs7->stream->totalRd += idx - tmpIdx;
|
||||
tmpIdx = idx;
|
||||
}
|
||||
|
||||
if (pkcs7->stream->totalRd + encryptedContentSz < pkiMsgSz) {
|
||||
pkcs7->stream->hasAtrib = 1;
|
||||
}
|
||||
|
||||
pkcs7->stream->expected = (pkcs7->stream->maxLen -
|
||||
pkcs7->stream->totalRd) + pkcs7->stream->length;
|
||||
|
||||
#endif
|
||||
pkcs7->state = WC_PKCS7_STAGE6;
|
||||
/* end of stage 5 */
|
||||
|
||||
case WC_PKCS7_STAGE6:
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
//@TODO
|
||||
if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
|
||||
pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz);
|
||||
|
||||
/* restore saved variables */
|
||||
expBlockSz = pkcs7->stream->varOne;
|
||||
encOID = pkcs7->stream->varTwo;
|
||||
encryptedContentSz = pkcs7->stream->varThree;
|
||||
version = pkcs7->stream->vers;
|
||||
tmpIv = pkcs7->stream->tmpIv;
|
||||
#endif
|
||||
if (ret == 0 && (encryptedContent = (byte*)XMALLOC(
|
||||
encryptedContentSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7)) == NULL)
|
||||
ret = MEMORY_E;
|
||||
|
||||
if (ret == 0) {
|
||||
XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
|
||||
idx += encryptedContentSz;
|
||||
}
|
||||
|
||||
/* decrypt encryptedContent */
|
||||
ret = wc_PKCS7_DecryptContent(encOID, pkcs7->encryptionKey,
|
||||
pkcs7->encryptionKeySz, tmpIv, expBlockSz,
|
||||
NULL, 0, NULL, 0, encryptedContent,
|
||||
encryptedContentSz, encryptedContent);
|
||||
if (ret != 0) {
|
||||
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
return ret;
|
||||
}
|
||||
if (ret != 0) {
|
||||
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
}
|
||||
|
||||
padLen = encryptedContent[encryptedContentSz-1];
|
||||
if (ret == 0) {
|
||||
padLen = encryptedContent[encryptedContentSz-1];
|
||||
|
||||
/* copy plaintext to output */
|
||||
XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
|
||||
/* copy plaintext to output */
|
||||
XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
|
||||
|
||||
/* get implicit[1] unprotected attributes, optional */
|
||||
pkcs7->decodedAttrib = NULL;
|
||||
if (idx < pkiMsgSz) {
|
||||
/* get implicit[1] unprotected attributes, optional */
|
||||
pkcs7->decodedAttrib = NULL;
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
if (pkcs7->stream->hasAtrib) {
|
||||
#else
|
||||
if (idx < pkiMsgSz) {
|
||||
#endif
|
||||
haveAttribs = 1;
|
||||
|
||||
haveAttribs = 1;
|
||||
|
||||
ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg,
|
||||
ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg,
|
||||
pkiMsgSz, &idx);
|
||||
if (ret != 0) {
|
||||
ForceZero(encryptedContent, encryptedContentSz);
|
||||
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
if (ret != 0) {
|
||||
ForceZero(encryptedContent, encryptedContentSz);
|
||||
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
/* go back and check the version now that attribs have been processed */
|
||||
if ((haveAttribs == 0 && version != 0) ||
|
||||
(haveAttribs == 1 && version != 2) ) {
|
||||
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
WOLFSSL_MSG("Wrong PKCS#7 EncryptedData version");
|
||||
return ASN_VERSION_E;
|
||||
}
|
||||
ForceZero(encryptedContent, encryptedContentSz);
|
||||
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
ret = encryptedContentSz - padLen;
|
||||
}
|
||||
|
||||
if (ret != 0) break;
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
wc_PKCS7_ResetStream(pkcs7);
|
||||
#endif
|
||||
pkcs7->state = WC_PKCS7_START;
|
||||
break;
|
||||
|
||||
default:
|
||||
WOLFSSL_MSG("Error in unknown PKCS#7 state");
|
||||
return BAD_STATE_E;
|
||||
}
|
||||
|
||||
/* go back and check the version now that attribs have been processed */
|
||||
if ((haveAttribs == 0 && version != 0) ||
|
||||
(haveAttribs == 1 && version != 2) ) {
|
||||
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
WOLFSSL_MSG("Wrong PKCS#7 EncryptedData version");
|
||||
return ASN_VERSION_E;
|
||||
if (ret != 0) {
|
||||
/* restart in error case */
|
||||
wc_PKCS7_ResetStream(pkcs7);
|
||||
pkcs7->state = WC_PKCS7_START;
|
||||
}
|
||||
|
||||
ForceZero(encryptedContent, encryptedContentSz);
|
||||
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
|
||||
return encryptedContentSz - padLen;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* NO_PKCS7_ENCRYPTED_DATA */
|
||||
@ -8378,10 +8750,8 @@ int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
|
||||
if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (contentType != COMPRESSED_DATA) {
|
||||
printf("ContentInfo not of type CompressedData");
|
||||
if (contentType != COMPRESSED_DATA)
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
/* get ContentInfo content EXPLICIT SEQUENCE */
|
||||
if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
|
||||
|
@ -20300,6 +20300,25 @@ int pkcs7encrypted_test(void)
|
||||
}
|
||||
|
||||
/* decode encryptedData */
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
{ /* test reading byte by byte */
|
||||
int z;
|
||||
for (z = 0; z < encryptedSz; z++) {
|
||||
decodedSz = wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted + z, 1,
|
||||
decoded, sizeof(decoded));
|
||||
if (decodedSz <= 0 && decodedSz != WC_PKCS7_WANT_READ_E) {
|
||||
printf("unexpected error %d\n", decodedSz);
|
||||
return -9402;
|
||||
}
|
||||
}
|
||||
/* test decode result */
|
||||
if (XMEMCMP(decoded, data, sizeof(data)) != 0) {
|
||||
printf("stream read failed\n");
|
||||
wc_PKCS7_Free(pkcs7);
|
||||
return -9403;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
decodedSz = wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, encryptedSz,
|
||||
decoded, sizeof(decoded));
|
||||
if (decodedSz <= 0){
|
||||
|
@ -303,6 +303,7 @@ enum Misc_ASN {
|
||||
HEADER_ENCRYPTED_KEY_SIZE = 0,
|
||||
#endif
|
||||
TRAILING_ZERO = 1, /* Used for size of zero pad */
|
||||
ASN_TAG_SZ = 1, /* single byte ASN.1 tag */
|
||||
MIN_VERSION_SZ = 3, /* Min bytes needed for GetMyVersion */
|
||||
#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \
|
||||
defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
|
||||
|
@ -221,8 +221,9 @@ enum {
|
||||
ZLIB_DECOMPRESS_ERROR = -268, /* zlib decompression error */
|
||||
|
||||
PKCS7_NO_SIGNER_E = -269, /* No signer in PKCS#7 signed data msg */
|
||||
WC_PKCS7_WANT_READ_E= -270, /* PKCS7 operations wants more input */
|
||||
|
||||
WC_LAST_E = -269, /* Update this to indicate last error */
|
||||
WC_LAST_E = -270, /* Update this to indicate last error */
|
||||
MIN_CODE_E = -300 /* errors -101 - -299 */
|
||||
|
||||
/* add new companion error id strings for any new error codes
|
||||
|
@ -86,6 +86,15 @@ enum PKCS7_TYPES {
|
||||
AUTH_ENVELOPED_DATA = 692 /* 1.2.840.113549.1.9.16.1.23, RFC 5083 */
|
||||
};
|
||||
|
||||
enum PKCS7_STATE {
|
||||
WC_PKCS7_START = 0,
|
||||
WC_PKCS7_STAGE2,
|
||||
WC_PKCS7_STAGE3,
|
||||
WC_PKCS7_STAGE4,
|
||||
WC_PKCS7_STAGE5,
|
||||
WC_PKCS7_STAGE6
|
||||
};
|
||||
|
||||
enum Pkcs7_Misc {
|
||||
PKCS7_NONCE_SZ = 16,
|
||||
MAX_ENCRYPTED_KEY_SZ = 512, /* max enc. key size, RSA <= 4096 */
|
||||
@ -131,6 +140,7 @@ typedef struct PKCS7DecodedAttrib {
|
||||
word32 valueSz;
|
||||
} PKCS7DecodedAttrib;
|
||||
|
||||
typedef struct PKCS7State PKCS7State;
|
||||
typedef struct Pkcs7Cert Pkcs7Cert;
|
||||
typedef struct Pkcs7EncodedRecip Pkcs7EncodedRecip;
|
||||
typedef struct PKCS7 PKCS7;
|
||||
@ -222,6 +232,11 @@ typedef struct PKCS7 {
|
||||
PKCS7Attrib* unauthAttribs; /* unauthenticated attribs */
|
||||
word32 unauthAttribsSz;
|
||||
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
PKCS7State* stream;
|
||||
#endif
|
||||
enum PKCS7_STATE state;
|
||||
|
||||
/* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */
|
||||
} PKCS7;
|
||||
|
||||
|
Reference in New Issue
Block a user