first addition of decode enveloped stream

This commit is contained in:
Jacob Barthelmeh
2018-10-19 09:55:20 -06:00
committed by David Garske
parent 5525f59852
commit 752259e343
3 changed files with 289 additions and 151 deletions

View File

@@ -328,6 +328,12 @@ static const char* wc_PKCS7_GetStateName(int in)
case WC_PKCS7_INFOSET_STAGE2: return "WC_PKCS7_INFOSET_STAGE2"; case WC_PKCS7_INFOSET_STAGE2: return "WC_PKCS7_INFOSET_STAGE2";
case WC_PKCS7_INFOSET_END: return "WC_PKCS7_INFOSET_END"; case WC_PKCS7_INFOSET_END: return "WC_PKCS7_INFOSET_END";
/* decode enveloped data */
case WC_PKCS7_ENV_2: return "WC_PKCS7_ENV_2";
case WC_PKCS7_ENV_3: return "WC_PKCS7_ENV_3";
case WC_PKCS7_ENV_4: return "WC_PKCS7_ENV_4";
case WC_PKCS7_ENV_5: return "WC_PKCS7_ENV_5";
/* decode auth enveloped */ /* decode auth enveloped */
case WC_PKCS7_AUTHENV_2: return "WC_PKCS7_AUTHENV_2"; case WC_PKCS7_AUTHENV_2: return "WC_PKCS7_AUTHENV_2";
case WC_PKCS7_AUTHENV_3: return "WC_PKCS7_AUTHENV_3"; case WC_PKCS7_AUTHENV_3: return "WC_PKCS7_AUTHENV_3";
@@ -3603,7 +3609,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
pkcs7->certSz[0] = certSz; pkcs7->certSz[0] = certSz;
certIdx = idx + certSz; certIdx = idx + certSz;
for (i = 1; i < MAX_PKCS7_CERTS && certIdx + 1 < pkiMsg2Sz; i++) { for (i = 1; i < MAX_PKCS7_CERTS && certIdx + 1 < pkiMsg2Sz
&& certIdx + 1 < (word32)length; i++) {
localIdx = certIdx; localIdx = certIdx;
if (pkiMsg2[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { if (pkiMsg2[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
@@ -8381,24 +8388,23 @@ WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz)
/* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */ /* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */
WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in,
word32 pkiMsgSz, byte* output, word32 inSz, byte* output,
word32 outputSz) word32 outputSz)
{ {
int recipFound = 0; int recipFound = 0;
int ret, length; int ret, length;
word32 idx = 0; word32 idx = 0, tmpIdx = 0;
word32 contentType, encOID; word32 contentType, encOID;
word32 decryptedKeySz; word32 decryptedKeySz;
int expBlockSz, blockKeySz; int expBlockSz = 0, blockKeySz = 0;
byte tmpIv[MAX_CONTENT_IV_SIZE]; byte tmpIvBuf[MAX_CONTENT_IV_SIZE];
byte* tmpIv = tmpIvBuf;
#ifdef WOLFSSL_SMALL_STACK byte* pkiMsg = in;
byte* decryptedKey; word32 pkiMsgSz = inSz;
#else byte* decryptedKey = NULL;
byte decryptedKey[MAX_ENCRYPTED_KEY_SZ];
#endif
int encryptedContentSz; int encryptedContentSz;
byte padLen; byte padLen;
byte* encryptedContent = NULL; byte* encryptedContent = NULL;
@@ -8411,174 +8417,282 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
output == NULL || outputSz == 0) output == NULL || outputSz == 0)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
length = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, &idx, #ifndef NO_PKCS7_STREAM
ENVELOPED_DATA); if (pkcs7->stream == NULL) {
if (length < 0) if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) {
return length; return ret;
}
#ifdef WOLFSSL_SMALL_STACK }
decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
DYNAMIC_TYPE_PKCS7);
if (decryptedKey == NULL)
return MEMORY_E;
#endif #endif
decryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, pkiMsg, pkiMsgSz, &idx, switch (pkcs7->state) {
case WC_PKCS7_START:
case WC_PKCS7_INFOSET_START:
case WC_PKCS7_INFOSET_BER:
case WC_PKCS7_INFOSET_STAGE1:
case WC_PKCS7_INFOSET_STAGE2:
case WC_PKCS7_INFOSET_END:
ret = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz,
&idx, ENVELOPED_DATA);
if (ret < 0) {
break;
}
tmpIdx = idx;
decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
DYNAMIC_TYPE_PKCS7);
if (decryptedKey == NULL)
return MEMORY_E;
wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_2);
#ifndef NO_PKCS7_STREAM
pkcs7->stream->aad = decryptedKey;
#endif
FALL_THROUGH;
case WC_PKCS7_ENV_2:
#ifndef NO_PKCS7_STREAM
/* store up enough buffer for initial info set decode */
if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ +
MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) {
return ret;
}
#endif
FALL_THROUGH;
case WC_PKCS7_DECRYPT_KTRI:
case WC_PKCS7_DECRYPT_KTRI_2:
case WC_PKCS7_DECRYPT_KTRI_3:
case WC_PKCS7_DECRYPT_KARI:
case WC_PKCS7_DECRYPT_KEKRI:
case WC_PKCS7_DECRYPT_PWRI:
case WC_PKCS7_DECRYPT_ORI:
#ifndef NO_PKCS7_STREAM
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK,
inSz);
decryptedKey = pkcs7->stream->aad;
decryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
#endif
ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx,
decryptedKey, &decryptedKeySz, decryptedKey, &decryptedKeySz,
&recipFound); &recipFound);
if (ret != 0) { if (ret == 0 && recipFound == 0) {
#ifdef WOLFSSL_SMALL_STACK WOLFSSL_MSG("No recipient found in envelopedData that matches input");
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); ret = PKCS7_RECIP_E;
#endif }
return ret;
}
if (recipFound == 0) { if (ret != 0)
WOLFSSL_MSG("No recipient found in envelopedData that matches input"); break;
#ifdef WOLFSSL_SMALL_STACK #ifndef NO_PKCS7_STREAM
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); tmpIdx = idx;
#endif pkcs7->stream->aadSz = decryptedKeySz;
return PKCS7_RECIP_E; #endif
} wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_3);
FALL_THROUGH;
/* remove EncryptedContentInfo */ case WC_PKCS7_ENV_3:
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
#endif
return ASN_PARSE_E;
}
if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) { #ifndef NO_PKCS7_STREAM
#ifdef WOLFSSL_SMALL_STACK if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ +
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); MAX_VERSION_SZ + ASN_TAG_SZ +
#endif MAX_LENGTH_SZ, &pkiMsg, &idx))
return ASN_PARSE_E; != 0) {
} return ret;
}
if (GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0) { pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz);
#ifdef WOLFSSL_SMALL_STACK #endif
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
#endif
return ASN_PARSE_E;
}
blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); /* remove EncryptedContentInfo */
if (blockKeySz < 0) { if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
#ifdef WOLFSSL_SMALL_STACK ret = ASN_PARSE_E;
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); }
#endif
return blockKeySz;
}
expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType,
if (expBlockSz < 0) { pkiMsgSz) < 0) {
#ifdef WOLFSSL_SMALL_STACK ret = ASN_PARSE_E;
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); }
#endif
return expBlockSz;
}
/* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType,
if (pkiMsg[idx++] != ASN_OCTET_STRING) { pkiMsgSz) < 0) {
#ifdef WOLFSSL_SMALL_STACK ret = ASN_PARSE_E;
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); }
#endif
return ASN_PARSE_E;
}
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) { blockKeySz = wc_PKCS7_GetOIDKeySize(encOID);
#ifdef WOLFSSL_SMALL_STACK if (ret == 0 && blockKeySz < 0) {
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); ret = blockKeySz;
#endif }
return ASN_PARSE_E;
}
if (length != expBlockSz) { expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID);
WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); if (ret == 0 && expBlockSz < 0) {
#ifdef WOLFSSL_SMALL_STACK ret = expBlockSz;
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); }
#endif
return ASN_PARSE_E;
}
XMEMCPY(tmpIv, &pkiMsg[idx], length); /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
idx += length; if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) {
ret = ASN_PARSE_E;
}
explicitOctet = pkiMsg[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0); if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
ret = ASN_PARSE_E;
}
/* read encryptedContent, cont[0] */ if (ret == 0 && length != expBlockSz) {
if (pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) && WOLFSSL_MSG("Incorrect IV length, must be of content alg block size");
pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { ret = ASN_PARSE_E;
#ifdef WOLFSSL_SMALL_STACK }
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
#endif
return ASN_PARSE_E;
}
idx++;
if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { if (ret != 0)
#ifdef WOLFSSL_SMALL_STACK break;
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #ifndef NO_PKCS7_STREAM
#endif if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
return ASN_PARSE_E; break;
} }
wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, length);
pkcs7->stream->contentSz = blockKeySz;
pkcs7->stream->expected = length + MAX_LENGTH_SZ + MAX_LENGTH_SZ +
ASN_TAG_SZ + ASN_TAG_SZ;
#endif
wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_4);
FALL_THROUGH;
if (explicitOctet) { case WC_PKCS7_ENV_4:
if (pkiMsg[idx++] != ASN_OCTET_STRING) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
#endif
return ASN_PARSE_E;
}
if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { #ifndef NO_PKCS7_STREAM
#ifdef WOLFSSL_SMALL_STACK if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
#endif return ret;
return ASN_PARSE_E; }
}
}
encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz);
wc_PKCS7_StreamGetVar(pkcs7, 0, 0, &length);
tmpIv = pkcs7->stream->tmpIv;
#endif
XMEMCPY(tmpIv, &pkiMsg[idx], length);
idx += length;
explicitOctet = pkiMsg[idx] ==
(ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0);
/* read encryptedContent, cont[0] */
if (ret == 0 && pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) &&
pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) {
ret = ASN_PARSE_E;
}
idx++;
if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz,
pkiMsgSz) <= 0) {
ret = ASN_PARSE_E;
}
if (ret == 0 && explicitOctet) {
if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) {
ret = ASN_PARSE_E;
break;
}
if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz,
pkiMsgSz) <= 0) {
ret = ASN_PARSE_E;
break;
}
}
if (ret != 0)
break;
#ifndef NO_PKCS7_STREAM
if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
break;
}
pkcs7->stream->expected = encryptedContentSz;
wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, 0);
wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz,
encryptedContentSz);
#endif
wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_5);
FALL_THROUGH;
case WC_PKCS7_ENV_5:
#ifndef NO_PKCS7_STREAM
if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
return ret;
}
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz);
wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz,
&encryptedContentSz);
tmpIv = pkcs7->stream->tmpIv;
/* restore decrypted key */
decryptedKey = pkcs7->stream->aad;
decryptedKeySz = pkcs7->stream->aadSz;
blockKeySz = pkcs7->stream->contentSz;
#endif
encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap,
DYNAMIC_TYPE_PKCS7); DYNAMIC_TYPE_PKCS7);
if (encryptedContent == NULL) { if (ret == 0 && encryptedContent == NULL) {
#ifdef WOLFSSL_SMALL_STACK ret = MEMORY_E;
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); break;
#endif }
return MEMORY_E;
}
XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); if (ret == 0) {
XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
}
/* decrypt encryptedContent */ /* decrypt encryptedContent */
ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz,
tmpIv, expBlockSz, NULL, 0, NULL, 0, tmpIv, expBlockSz, NULL, 0, NULL, 0,
encryptedContent, encryptedContentSz, encryptedContent, encryptedContentSz,
encryptedContent); encryptedContent);
if (ret != 0) { if (ret != 0) {
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
#ifdef WOLFSSL_SMALL_STACK break;
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); }
#endif
return ret; padLen = encryptedContent[encryptedContentSz-1];
/* copy plaintext to output */
XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
/* free memory, zero out keys */
ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ);
ForceZero(encryptedContent, encryptedContentSz);
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
ret = encryptedContentSz - padLen;
#ifndef NO_PKCS7_STREAM
pkcs7->stream->aad = NULL;
pkcs7->stream->aadSz = 0;
wc_PKCS7_ResetStream(pkcs7);
#endif
wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
break;
default:
WOLFSSL_MSG("PKCS#7 unknown decode enveloped state");
ret = BAD_FUNC_ARG;
} }
padLen = encryptedContent[encryptedContentSz-1]; #ifndef NO_PKCS7_STREAM
if (ret < 0 && ret != WC_PKCS7_WANT_READ_E) {
/* copy plaintext to output */ wc_PKCS7_ResetStream(pkcs7);
XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
}
/* free memory, zero out keys */ #else
ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); if (decryptedKey != NULL && ret < 0) {
ForceZero(encryptedContent, encryptedContentSz); ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ);
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); }
#ifdef WOLFSSL_SMALL_STACK XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); }
#endif #endif
return ret;
return encryptedContentSz - padLen;
} }

View File

@@ -19380,7 +19380,6 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz,
decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, enveloped, envelopedSz, decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, enveloped, envelopedSz,
decoded, sizeof(decoded)); decoded, sizeof(decoded));
if (decodedSz <= 0) { if (decodedSz <= 0) {
printf("ret = %d\n", decodedSz);
wc_PKCS7_Free(pkcs7); wc_PKCS7_Free(pkcs7);
return -9325; return -9325;
} }
@@ -19391,6 +19390,25 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz,
return -9326; return -9326;
} }
#ifndef NO_PKCS7_STREAM
{ /* test reading byte by byte */
int z;
for (z = 0; z < envelopedSz; z++) {
decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, enveloped + z, 1,
decoded, sizeof(decoded));
if (decodedSz <= 0 && decodedSz != WC_PKCS7_WANT_READ_E) {
printf("unexpected error %d\n", decodedSz);
return -9325;
}
}
/* test decode result */
if (XMEMCMP(decoded, data, sizeof(data)) != 0) {
printf("stream read compare failed\n");
wc_PKCS7_Free(pkcs7);
return -9326;
}
}
#endif
#ifdef PKCS7_OUTPUT_TEST_BUNDLES #ifdef PKCS7_OUTPUT_TEST_BUNDLES
/* output pkcs7 envelopedData for external testing */ /* output pkcs7 envelopedData for external testing */
pkcs7File = fopen(testVectors[i].outFileName, "wb"); pkcs7File = fopen(testVectors[i].outFileName, "wb");

View File

@@ -109,6 +109,12 @@ enum PKCS7_STATE {
WC_PKCS7_INFOSET_STAGE2, WC_PKCS7_INFOSET_STAGE2,
WC_PKCS7_INFOSET_END, WC_PKCS7_INFOSET_END,
/* decode enveloped data */
WC_PKCS7_ENV_2,
WC_PKCS7_ENV_3,
WC_PKCS7_ENV_4,
WC_PKCS7_ENV_5,
/* decode auth enveloped */ /* decode auth enveloped */
WC_PKCS7_AUTHENV_2, WC_PKCS7_AUTHENV_2,
WC_PKCS7_AUTHENV_3, WC_PKCS7_AUTHENV_3,