mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-03 12:44:45 +02:00
add support for PKCS7/CMS EnvelopedData with fragmented encrypted content
This commit is contained in:
@@ -18416,7 +18416,7 @@ static void test_wc_PKCS7_BER(void)
|
||||
XFILE f;
|
||||
byte der[4096];
|
||||
#ifndef NO_DES3
|
||||
byte decoded[1024];
|
||||
byte decoded[2048];
|
||||
#endif
|
||||
word32 derSz;
|
||||
int ret;
|
||||
|
@@ -1172,6 +1172,11 @@ void wc_PKCS7_Free(PKCS7* pkcs7)
|
||||
pkcs7->pkcs7Digest = NULL;
|
||||
pkcs7->pkcs7DigestSz = 0;
|
||||
}
|
||||
if (pkcs7->cachedEncryptedContent != NULL) {
|
||||
XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
pkcs7->cachedEncryptedContent = NULL;
|
||||
pkcs7->cachedEncryptedContentSz = 0;
|
||||
}
|
||||
|
||||
if (pkcs7->isDynamic) {
|
||||
pkcs7->isDynamic = 0;
|
||||
@@ -9987,6 +9992,41 @@ WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz)
|
||||
}
|
||||
|
||||
|
||||
/* append data to encrypted content cache in PKCS7 structure
|
||||
* return 0 on success, negative on error */
|
||||
static int PKCS7_CacheEncryptedContent(PKCS7* pkcs7, byte* in, word32 inSz)
|
||||
{
|
||||
byte* oldCache;
|
||||
word32 oldCacheSz;
|
||||
|
||||
if (pkcs7 == NULL || in == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
/* save pointer to old cache */
|
||||
oldCache = pkcs7->cachedEncryptedContent;
|
||||
oldCacheSz = pkcs7->cachedEncryptedContentSz;
|
||||
|
||||
/* re-allocate new buffer to fit appended data */
|
||||
pkcs7->cachedEncryptedContent = (byte*)XMALLOC(oldCacheSz + inSz,
|
||||
pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
if (pkcs7->cachedEncryptedContent == NULL) {
|
||||
pkcs7->cachedEncryptedContentSz = 0;
|
||||
XFREE(oldCache, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
return MEMORY_E;
|
||||
}
|
||||
|
||||
if (oldCache != NULL) {
|
||||
XMEMCPY(pkcs7->cachedEncryptedContent, oldCache, oldCacheSz);
|
||||
}
|
||||
XMEMCPY(pkcs7->cachedEncryptedContent + oldCacheSz, in, inSz);
|
||||
pkcs7->cachedEncryptedContentSz += inSz;
|
||||
|
||||
XFREE(oldCache, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */
|
||||
WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in,
|
||||
word32 inSz, byte* output,
|
||||
@@ -10009,6 +10049,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in,
|
||||
byte* pkiMsg = in;
|
||||
word32 pkiMsgSz = inSz;
|
||||
byte* decryptedKey = NULL;
|
||||
int encryptedContentTotalSz = 0;
|
||||
int encryptedContentSz = 0;
|
||||
byte padLen;
|
||||
byte* encryptedContent = NULL;
|
||||
@@ -10223,27 +10264,51 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in,
|
||||
}
|
||||
idx++;
|
||||
|
||||
if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz,
|
||||
if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentTotalSz,
|
||||
pkiMsgSz) <= 0) {
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
|
||||
if (ret == 0 && explicitOctet) {
|
||||
if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) {
|
||||
ret = ASN_PARSE_E;
|
||||
break;
|
||||
}
|
||||
/* encrypted content may be fragmented into multiple
|
||||
* consecutive OCTET STRINGs, if so loop through
|
||||
* collecting and caching encrypted content bytes */
|
||||
localIdx = idx;
|
||||
while (idx < (localIdx + encryptedContentTotalSz)) {
|
||||
|
||||
if (tag != ASN_OCTET_STRING) {
|
||||
ret = ASN_PARSE_E;
|
||||
break;
|
||||
}
|
||||
if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) {
|
||||
ret = ASN_PARSE_E;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz,
|
||||
pkiMsgSz) <= 0) {
|
||||
ret = ASN_PARSE_E;
|
||||
if (tag != ASN_OCTET_STRING) {
|
||||
ret = ASN_PARSE_E;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == 0 && GetLength(pkiMsg, &idx,
|
||||
&encryptedContentSz, pkiMsgSz) <= 0) {
|
||||
ret = ASN_PARSE_E;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = PKCS7_CacheEncryptedContent(pkcs7, &pkiMsg[idx],
|
||||
encryptedContentSz);
|
||||
if (ret != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* advance idx past encrypted content */
|
||||
idx += encryptedContentSz;
|
||||
}
|
||||
} else {
|
||||
/* cache encrypted content, no OCTET STRING */
|
||||
ret = PKCS7_CacheEncryptedContent(pkcs7, &pkiMsg[idx],
|
||||
encryptedContentTotalSz);
|
||||
if (ret != 0) {
|
||||
break;
|
||||
}
|
||||
idx += encryptedContentTotalSz;
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
@@ -10253,10 +10318,9 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in,
|
||||
if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
|
||||
break;
|
||||
}
|
||||
pkcs7->stream->expected = encryptedContentSz;
|
||||
pkcs7->stream->expected = 0;
|
||||
wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, 0);
|
||||
wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz,
|
||||
encryptedContentSz);
|
||||
wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, 0);
|
||||
#endif
|
||||
wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_5);
|
||||
FALL_THROUGH;
|
||||
@@ -10269,8 +10333,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in,
|
||||
return ret;
|
||||
}
|
||||
|
||||
wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz,
|
||||
&encryptedContentSz);
|
||||
wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, NULL);
|
||||
tmpIv = pkcs7->stream->tmpIv;
|
||||
|
||||
/* restore decrypted key */
|
||||
@@ -10280,23 +10343,16 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in,
|
||||
#else
|
||||
ret = 0;
|
||||
#endif
|
||||
encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap,
|
||||
DYNAMIC_TYPE_PKCS7);
|
||||
if (encryptedContent == NULL) {
|
||||
ret = MEMORY_E;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
|
||||
}
|
||||
/* use cached content */
|
||||
encryptedContent = pkcs7->cachedEncryptedContent;
|
||||
encryptedContentSz = pkcs7->cachedEncryptedContentSz;
|
||||
|
||||
/* decrypt encryptedContent */
|
||||
ret = wc_PKCS7_DecryptContent(pkcs7, encOID, decryptedKey,
|
||||
blockKeySz, tmpIv, expBlockSz, NULL, 0, NULL, 0,
|
||||
encryptedContent, encryptedContentSz, encryptedContent);
|
||||
if (ret != 0) {
|
||||
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -10305,7 +10361,6 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in,
|
||||
/* copy plaintext to output */
|
||||
if (padLen > encryptedContentSz ||
|
||||
(word32)(encryptedContentSz - padLen) > outputSz) {
|
||||
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
ret = BUFFER_E;
|
||||
break;
|
||||
}
|
||||
@@ -10313,9 +10368,13 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in,
|
||||
|
||||
/* 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);
|
||||
if (pkcs7->cachedEncryptedContent != NULL) {
|
||||
XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap,
|
||||
DYNAMIC_TYPE_PKCS7);
|
||||
pkcs7->cachedEncryptedContent = NULL;
|
||||
pkcs7->cachedEncryptedContentSz = 0;
|
||||
}
|
||||
|
||||
ret = encryptedContentSz - padLen;
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
@@ -10335,12 +10394,23 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in,
|
||||
if (ret < 0 && ret != WC_PKCS7_WANT_READ_E) {
|
||||
wc_PKCS7_ResetStream(pkcs7);
|
||||
wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
|
||||
if (pkcs7->cachedEncryptedContent != NULL) {
|
||||
XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap,
|
||||
DYNAMIC_TYPE_PKCS7);
|
||||
pkcs7->cachedEncryptedContent = NULL;
|
||||
pkcs7->cachedEncryptedContentSz = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (decryptedKey != NULL && ret < 0) {
|
||||
ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ);
|
||||
XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
}
|
||||
if (pkcs7->cachedEncryptedContent != NULL && ret < 0) {
|
||||
XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
pkcs7->cachedEncryptedContent = NULL;
|
||||
pkcs7->cachedEncryptedContentSz = 0;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
@@ -330,6 +330,10 @@ struct PKCS7 {
|
||||
#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)
|
||||
CallbackRsaSignRawDigest rsaSignRawDigestCb;
|
||||
#endif
|
||||
|
||||
/* used by DecodeEnvelopedData with multiple encrypted contents */
|
||||
byte* cachedEncryptedContent;
|
||||
word32 cachedEncryptedContentSz;
|
||||
/* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user