Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions certs/include.am
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ EXTRA_DIST += \
certs/server-revoked-key.pem \
certs/wolfssl-website-ca.pem \
certs/test-degenerate.p7b \
certs/test-multiple-recipients.p7b \
certs/test-stream-sign.p7b \
certs/test-stream-dec.p7b \
certs/test-ber-exp02-05-2022.p7b \
Expand Down
5 changes: 5 additions & 0 deletions certs/renewcerts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,11 @@ run_renewcerts(){
openssl cms -encrypt -in ca-cert.pem -recip client-cert.pem -out test-stream-dec.p7b -outform DER -stream
check_result $? ""

echo "Creating test-multiple-recipients.p7b..."
echo ""
openssl smime -encrypt -binary -aes-256-cbc -in ./client-key.pem -out ./test-multiple-recipients.p7b -outform DER ./client-cert.pem ./server-cert.pem
check_result $? ""

echo "End of section"
echo "---------------------------------------------------------------------"

Expand Down
Binary file added certs/test-multiple-recipients.p7b
Binary file not shown.
85 changes: 85 additions & 0 deletions tests/api/test_pkcs7.c
Original file line number Diff line number Diff line change
Expand Up @@ -2145,6 +2145,91 @@ int test_wc_PKCS7_DecodeEnvelopedData_stream(void)
#endif
} /* END test_wc_PKCS7_DecodeEnvelopedData_stream() */


/*
* Testing wc_PKCS7_DecodeEnvelopedData with streaming
*/
int test_wc_PKCS7_DecodeEnvelopedData_multiple_recipients(void)
{
#if defined(HAVE_PKCS7)
EXPECT_DECLS;
PKCS7* pkcs7 = NULL;
int ret = 0;
XFILE f = XBADFILE;
const char* testFile = "./certs/test-multiple-recipients.p7b";
byte testDerBuffer[8192]; /* test-multiple-recipients is currently 6433
bytes */
size_t testDerBufferSz = 0;
byte decodedData[8192];

ExpectTrue((f = XFOPEN(testFile, "rb")) != XBADFILE);
testDerBufferSz = XFREAD(testDerBuffer, 1,
sizeof(testDerBuffer), f);
ExpectIntNE(testDerBufferSz, 0);
if (f != XBADFILE) {
XFCLOSE(f);
f = XBADFILE;
}

/* test with server cert recipient */
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
if (pkcs7) {
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)server_cert_der_2048,
sizeof_server_cert_der_2048), 0);

ExpectIntEQ(wc_PKCS7_SetKey(pkcs7, (byte*)server_key_der_2048,
sizeof_server_key_der_2048), 0);

ret = wc_PKCS7_DecodeEnvelopedData(pkcs7, testDerBuffer,
(word32)testDerBufferSz, decodedData, sizeof(decodedData));
#if defined(NO_AES) || defined(NO_AES_256)
ExpectIntEQ(ret, ALGO_ID_E);
#else
ExpectIntGT(ret, 0);
#endif
wc_PKCS7_Free(pkcs7);
}

/* test with client cert recipient */
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
if (pkcs7) {
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)client_cert_der_2048,
sizeof_client_cert_der_2048), 0);

ExpectIntEQ(wc_PKCS7_SetKey(pkcs7, (byte*)client_key_der_2048,
sizeof_client_key_der_2048), 0);

ret = wc_PKCS7_DecodeEnvelopedData(pkcs7, testDerBuffer,
(word32)testDerBufferSz, decodedData, sizeof(decodedData));
#if defined(NO_AES) || defined(NO_AES_256)
ExpectIntEQ(ret, ALGO_ID_E);
#else
ExpectIntGT(ret, 0);
#endif
wc_PKCS7_Free(pkcs7);
}

/* test with ca cert recipient (which should fail) */
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
if (pkcs7) {
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)ca_cert_der_2048,
sizeof_ca_cert_der_2048), 0);

ExpectIntEQ(wc_PKCS7_SetKey(pkcs7, (byte*)ca_key_der_2048,
sizeof_ca_key_der_2048), 0);

ret = wc_PKCS7_DecodeEnvelopedData(pkcs7, testDerBuffer,
(word32)testDerBufferSz, decodedData, sizeof(decodedData));
ExpectIntLT(ret, 0);
wc_PKCS7_Free(pkcs7);
}

return EXPECT_RESULT();
#else
return TEST_SKIPPED;
#endif
} /* END test_wc_PKCS7_DecodeEnvelopedData_multiple_recipients() */

/*
* Testing wc_PKCS7_EncodeEnvelopedData(), wc_PKCS7_DecodeEnvelopedData()
*/
Expand Down
4 changes: 3 additions & 1 deletion tests/api/test_pkcs7.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ int test_wc_PKCS7_NoDefaultSignedAttribs(void);
int test_wc_PKCS7_SetOriEncryptCtx(void);
int test_wc_PKCS7_SetOriDecryptCtx(void);
int test_wc_PKCS7_DecodeCompressedData(void);
int test_wc_PKCS7_DecodeEnvelopedData_multiple_recipients(void);


#define TEST_PKCS7_DECLS \
Expand Down Expand Up @@ -74,7 +75,8 @@ int test_wc_PKCS7_DecodeCompressedData(void);
TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_DecodeSymmetricKeyPackage), \
TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_DecodeOneSymmetricKey), \
TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_SetOriEncryptCtx), \
TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_SetOriDecryptCtx)
TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_SetOriDecryptCtx), \
TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_DecodeEnvelopedData_multiple_recipients)

#define TEST_PKCS7_SIGNED_ENCRYPTED_DATA_DECLS \
TEST_DECL_GROUP("pkcs7_sed", test_wc_PKCS7_signed_enveloped)
Expand Down
61 changes: 51 additions & 10 deletions wolfcrypt/src/pkcs7.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ struct PKCS7State {
word32 currContSz; /* size of current content */
word32 currContRmnSz; /* remaining size of current content */
word32 accumContSz; /* size of accumulated content size */
int recipientSz; /* size of recipient set */
byte tmpIv[MAX_CONTENT_IV_SIZE]; /* store IV if needed */
#ifdef WC_PKCS7_STREAM_DEBUG
word32 peakUsed; /* most bytes used for struct at any one time */
Expand Down Expand Up @@ -10487,6 +10488,14 @@ static int wc_PKCS7_DecryptKtri(wc_PKCS7* pkcs7, byte* in, word32 inSz,
XMEMCPY(encryptedKey, &pkiMsg[*idx], (word32)encryptedKeySz);
*idx += (word32)encryptedKeySz;

/* If this is not the correct recipient then do not try to decode
* the encrypted key */
if (*recipFound == 0) {
XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
ret = PKCS7_RECIP_E;
break;
}

/* load private key */
#ifdef WOLFSSL_SMALL_STACK
privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap,
Expand Down Expand Up @@ -11973,8 +11982,15 @@ static int wc_PKCS7_DecryptRecipientInfos(wc_PKCS7* pkcs7, byte* in,
ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx,
decryptedKey, decryptedKeySz,
recipFound);
if (ret != 0)
return ret;
if (ret != 0) {
if (ret != WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E) &&
*recipFound == 0) {
continue; /* try next recipient */
}
else {
return ret; /* found recipient and failed decrypt */
}
}
#else
return NOT_COMPILED_IN;
#endif
Expand Down Expand Up @@ -12095,8 +12111,8 @@ static int wc_PKCS7_DecryptRecipientInfos(wc_PKCS7* pkcs7, byte* in,
recipFound);
if (ret != 0)
return ret;

} else {
}
else {
/* failed to find RecipientInfo, restore idx and continue */
*idx = savedIdx;
break;
Expand Down Expand Up @@ -12315,9 +12331,17 @@ static int wc_PKCS7_ParseToRecipientInfoSet(wc_PKCS7* pkcs7, byte* in,

#ifndef NO_PKCS7_STREAM
pkcs7->stream->expected = (word32)length;

if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
break;
}

/* update the stored max length */
if (pkcs7->stream->totalRd + pkcs7->stream->expected >
pkcs7->stream->maxLen) {
pkcs7->stream->maxLen = pkcs7->stream->totalRd +
pkcs7->stream->expected;
}
#endif

if (ret == 0)
Expand Down Expand Up @@ -12396,9 +12420,8 @@ int wc_PKCS7_DecodeEnvelopedData(wc_PKCS7* pkcs7, byte* in,
int recipFound = 0;
int ret, length = 0;
word32 idx = 0;
#ifndef NO_PKCS7_STREAM
word32 tmpIdx = 0;
#endif
word32 recipientSetSz = 0;
word32 contentType = 0, encOID = 0;
word32 decryptedKeySz = MAX_ENCRYPTED_KEY_SZ;

Expand Down Expand Up @@ -12457,17 +12480,21 @@ int wc_PKCS7_DecodeEnvelopedData(wc_PKCS7* pkcs7, byte* in,
if (decryptedKey == NULL)
return MEMORY_E;
wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_2);
#ifndef NO_PKCS7_STREAM
tmpIdx = idx;
recipientSetSz = (word32)ret;
#ifndef NO_PKCS7_STREAM
pkcs7->stream->aad = decryptedKey;
/* get the full recipient set */
pkcs7->stream->expected = recipientSetSz;
pkcs7->stream->recipientSz = ret;
#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) {
if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
return ret;
}
#endif
Expand All @@ -12483,8 +12510,8 @@ int wc_PKCS7_DecodeEnvelopedData(wc_PKCS7* pkcs7, byte* in,
#ifndef NO_PKCS7_STREAM
decryptedKey = pkcs7->stream->aad;
decryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
tmpIdx = idx;
#endif

ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx,
decryptedKey, &decryptedKeySz,
&recipFound);
Expand All @@ -12497,10 +12524,24 @@ int wc_PKCS7_DecodeEnvelopedData(wc_PKCS7* pkcs7, byte* in,
if (ret != 0)
break;
#ifndef NO_PKCS7_STREAM
/* advance idx past recipient info set if not all recipients
* parsed */
if (pkcs7->stream->totalRd < ((word32)pkcs7->stream->recipientSz +
tmpIdx)) {
idx = tmpIdx + (word32)pkcs7->stream->recipientSz;

/* process additional recipients as read */
if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
break;
}
}

tmpIdx = idx;
pkcs7->stream->aadSz = decryptedKeySz;
pkcs7->stream->expected = MAX_LENGTH_SZ + MAX_VERSION_SZ +
ASN_TAG_SZ + MAX_LENGTH_SZ;
#else
idx = tmpIdx + recipientSetSz;
#endif
wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_3);
FALL_THROUGH;
Expand Down