Skip to content

Commit 92a4782

Browse files
authored
Merge pull request #8674 from JacobBarthelmeh/pkcs7_stream
Fix to advance past multiple recipients
2 parents d4242fa + 7128932 commit 92a4782

File tree

6 files changed

+145
-11
lines changed

6 files changed

+145
-11
lines changed

certs/include.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ EXTRA_DIST += \
5353
certs/server-revoked-key.pem \
5454
certs/wolfssl-website-ca.pem \
5555
certs/test-degenerate.p7b \
56+
certs/test-multiple-recipients.p7b \
5657
certs/test-stream-sign.p7b \
5758
certs/test-stream-dec.p7b \
5859
certs/test-ber-exp02-05-2022.p7b \

certs/renewcerts.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,11 @@ run_renewcerts(){
888888
openssl cms -encrypt -in ca-cert.pem -recip client-cert.pem -out test-stream-dec.p7b -outform DER -stream
889889
check_result $? ""
890890

891+
echo "Creating test-multiple-recipients.p7b..."
892+
echo ""
893+
openssl smime -encrypt -binary -aes-256-cbc -in ./client-key.pem -out ./test-multiple-recipients.p7b -outform DER ./client-cert.pem ./server-cert.pem
894+
check_result $? ""
895+
891896
echo "End of section"
892897
echo "---------------------------------------------------------------------"
893898

certs/test-multiple-recipients.p7b

6.29 KB
Binary file not shown.

tests/api/test_pkcs7.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2145,6 +2145,91 @@ int test_wc_PKCS7_DecodeEnvelopedData_stream(void)
21452145
#endif
21462146
} /* END test_wc_PKCS7_DecodeEnvelopedData_stream() */
21472147

2148+
2149+
/*
2150+
* Testing wc_PKCS7_DecodeEnvelopedData with streaming
2151+
*/
2152+
int test_wc_PKCS7_DecodeEnvelopedData_multiple_recipients(void)
2153+
{
2154+
#if defined(HAVE_PKCS7)
2155+
EXPECT_DECLS;
2156+
PKCS7* pkcs7 = NULL;
2157+
int ret = 0;
2158+
XFILE f = XBADFILE;
2159+
const char* testFile = "./certs/test-multiple-recipients.p7b";
2160+
byte testDerBuffer[8192]; /* test-multiple-recipients is currently 6433
2161+
bytes */
2162+
size_t testDerBufferSz = 0;
2163+
byte decodedData[8192];
2164+
2165+
ExpectTrue((f = XFOPEN(testFile, "rb")) != XBADFILE);
2166+
testDerBufferSz = XFREAD(testDerBuffer, 1,
2167+
sizeof(testDerBuffer), f);
2168+
ExpectIntNE(testDerBufferSz, 0);
2169+
if (f != XBADFILE) {
2170+
XFCLOSE(f);
2171+
f = XBADFILE;
2172+
}
2173+
2174+
/* test with server cert recipient */
2175+
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
2176+
if (pkcs7) {
2177+
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)server_cert_der_2048,
2178+
sizeof_server_cert_der_2048), 0);
2179+
2180+
ExpectIntEQ(wc_PKCS7_SetKey(pkcs7, (byte*)server_key_der_2048,
2181+
sizeof_server_key_der_2048), 0);
2182+
2183+
ret = wc_PKCS7_DecodeEnvelopedData(pkcs7, testDerBuffer,
2184+
(word32)testDerBufferSz, decodedData, sizeof(decodedData));
2185+
#if defined(NO_AES) || defined(NO_AES_256)
2186+
ExpectIntEQ(ret, ALGO_ID_E);
2187+
#else
2188+
ExpectIntGT(ret, 0);
2189+
#endif
2190+
wc_PKCS7_Free(pkcs7);
2191+
}
2192+
2193+
/* test with client cert recipient */
2194+
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
2195+
if (pkcs7) {
2196+
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)client_cert_der_2048,
2197+
sizeof_client_cert_der_2048), 0);
2198+
2199+
ExpectIntEQ(wc_PKCS7_SetKey(pkcs7, (byte*)client_key_der_2048,
2200+
sizeof_client_key_der_2048), 0);
2201+
2202+
ret = wc_PKCS7_DecodeEnvelopedData(pkcs7, testDerBuffer,
2203+
(word32)testDerBufferSz, decodedData, sizeof(decodedData));
2204+
#if defined(NO_AES) || defined(NO_AES_256)
2205+
ExpectIntEQ(ret, ALGO_ID_E);
2206+
#else
2207+
ExpectIntGT(ret, 0);
2208+
#endif
2209+
wc_PKCS7_Free(pkcs7);
2210+
}
2211+
2212+
/* test with ca cert recipient (which should fail) */
2213+
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
2214+
if (pkcs7) {
2215+
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)ca_cert_der_2048,
2216+
sizeof_ca_cert_der_2048), 0);
2217+
2218+
ExpectIntEQ(wc_PKCS7_SetKey(pkcs7, (byte*)ca_key_der_2048,
2219+
sizeof_ca_key_der_2048), 0);
2220+
2221+
ret = wc_PKCS7_DecodeEnvelopedData(pkcs7, testDerBuffer,
2222+
(word32)testDerBufferSz, decodedData, sizeof(decodedData));
2223+
ExpectIntLT(ret, 0);
2224+
wc_PKCS7_Free(pkcs7);
2225+
}
2226+
2227+
return EXPECT_RESULT();
2228+
#else
2229+
return TEST_SKIPPED;
2230+
#endif
2231+
} /* END test_wc_PKCS7_DecodeEnvelopedData_multiple_recipients() */
2232+
21482233
/*
21492234
* Testing wc_PKCS7_EncodeEnvelopedData(), wc_PKCS7_DecodeEnvelopedData()
21502235
*/

tests/api/test_pkcs7.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ int test_wc_PKCS7_NoDefaultSignedAttribs(void);
4747
int test_wc_PKCS7_SetOriEncryptCtx(void);
4848
int test_wc_PKCS7_SetOriDecryptCtx(void);
4949
int test_wc_PKCS7_DecodeCompressedData(void);
50+
int test_wc_PKCS7_DecodeEnvelopedData_multiple_recipients(void);
5051

5152

5253
#define TEST_PKCS7_DECLS \
@@ -74,7 +75,8 @@ int test_wc_PKCS7_DecodeCompressedData(void);
7475
TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_DecodeSymmetricKeyPackage), \
7576
TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_DecodeOneSymmetricKey), \
7677
TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_SetOriEncryptCtx), \
77-
TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_SetOriDecryptCtx)
78+
TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_SetOriDecryptCtx), \
79+
TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_DecodeEnvelopedData_multiple_recipients)
7880

7981
#define TEST_PKCS7_SIGNED_ENCRYPTED_DATA_DECLS \
8082
TEST_DECL_GROUP("pkcs7_sed", test_wc_PKCS7_signed_enveloped)

wolfcrypt/src/pkcs7.c

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ struct PKCS7State {
106106
word32 currContSz; /* size of current content */
107107
word32 currContRmnSz; /* remaining size of current content */
108108
word32 accumContSz; /* size of accumulated content size */
109+
int recipientSz; /* size of recipient set */
109110
byte tmpIv[MAX_CONTENT_IV_SIZE]; /* store IV if needed */
110111
#ifdef WC_PKCS7_STREAM_DEBUG
111112
word32 peakUsed; /* most bytes used for struct at any one time */
@@ -10487,6 +10488,14 @@ static int wc_PKCS7_DecryptKtri(wc_PKCS7* pkcs7, byte* in, word32 inSz,
1048710488
XMEMCPY(encryptedKey, &pkiMsg[*idx], (word32)encryptedKeySz);
1048810489
*idx += (word32)encryptedKeySz;
1048910490

10491+
/* If this is not the correct recipient then do not try to decode
10492+
* the encrypted key */
10493+
if (*recipFound == 0) {
10494+
XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
10495+
ret = PKCS7_RECIP_E;
10496+
break;
10497+
}
10498+
1049010499
/* load private key */
1049110500
#ifdef WOLFSSL_SMALL_STACK
1049210501
privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap,
@@ -11973,8 +11982,15 @@ static int wc_PKCS7_DecryptRecipientInfos(wc_PKCS7* pkcs7, byte* in,
1197311982
ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx,
1197411983
decryptedKey, decryptedKeySz,
1197511984
recipFound);
11976-
if (ret != 0)
11977-
return ret;
11985+
if (ret != 0) {
11986+
if (ret != WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E) &&
11987+
*recipFound == 0) {
11988+
continue; /* try next recipient */
11989+
}
11990+
else {
11991+
return ret; /* found recipient and failed decrypt */
11992+
}
11993+
}
1197811994
#else
1197911995
return NOT_COMPILED_IN;
1198011996
#endif
@@ -12095,8 +12111,8 @@ static int wc_PKCS7_DecryptRecipientInfos(wc_PKCS7* pkcs7, byte* in,
1209512111
recipFound);
1209612112
if (ret != 0)
1209712113
return ret;
12098-
12099-
} else {
12114+
}
12115+
else {
1210012116
/* failed to find RecipientInfo, restore idx and continue */
1210112117
*idx = savedIdx;
1210212118
break;
@@ -12315,9 +12331,17 @@ static int wc_PKCS7_ParseToRecipientInfoSet(wc_PKCS7* pkcs7, byte* in,
1231512331

1231612332
#ifndef NO_PKCS7_STREAM
1231712333
pkcs7->stream->expected = (word32)length;
12334+
1231812335
if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
1231912336
break;
1232012337
}
12338+
12339+
/* update the stored max length */
12340+
if (pkcs7->stream->totalRd + pkcs7->stream->expected >
12341+
pkcs7->stream->maxLen) {
12342+
pkcs7->stream->maxLen = pkcs7->stream->totalRd +
12343+
pkcs7->stream->expected;
12344+
}
1232112345
#endif
1232212346

1232312347
if (ret == 0)
@@ -12396,9 +12420,8 @@ int wc_PKCS7_DecodeEnvelopedData(wc_PKCS7* pkcs7, byte* in,
1239612420
int recipFound = 0;
1239712421
int ret, length = 0;
1239812422
word32 idx = 0;
12399-
#ifndef NO_PKCS7_STREAM
1240012423
word32 tmpIdx = 0;
12401-
#endif
12424+
word32 recipientSetSz = 0;
1240212425
word32 contentType = 0, encOID = 0;
1240312426
word32 decryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
1240412427

@@ -12457,17 +12480,21 @@ int wc_PKCS7_DecodeEnvelopedData(wc_PKCS7* pkcs7, byte* in,
1245712480
if (decryptedKey == NULL)
1245812481
return MEMORY_E;
1245912482
wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_2);
12460-
#ifndef NO_PKCS7_STREAM
1246112483
tmpIdx = idx;
12484+
recipientSetSz = (word32)ret;
12485+
#ifndef NO_PKCS7_STREAM
1246212486
pkcs7->stream->aad = decryptedKey;
12487+
/* get the full recipient set */
12488+
pkcs7->stream->expected = recipientSetSz;
12489+
pkcs7->stream->recipientSz = ret;
1246312490
#endif
1246412491
FALL_THROUGH;
1246512492

1246612493
case WC_PKCS7_ENV_2:
1246712494
#ifndef NO_PKCS7_STREAM
1246812495
/* store up enough buffer for initial info set decode */
12469-
if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ +
12470-
MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) {
12496+
if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
12497+
pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
1247112498
return ret;
1247212499
}
1247312500
#endif
@@ -12483,8 +12510,8 @@ int wc_PKCS7_DecodeEnvelopedData(wc_PKCS7* pkcs7, byte* in,
1248312510
#ifndef NO_PKCS7_STREAM
1248412511
decryptedKey = pkcs7->stream->aad;
1248512512
decryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
12513+
tmpIdx = idx;
1248612514
#endif
12487-
1248812515
ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx,
1248912516
decryptedKey, &decryptedKeySz,
1249012517
&recipFound);
@@ -12497,10 +12524,24 @@ int wc_PKCS7_DecodeEnvelopedData(wc_PKCS7* pkcs7, byte* in,
1249712524
if (ret != 0)
1249812525
break;
1249912526
#ifndef NO_PKCS7_STREAM
12527+
/* advance idx past recipient info set if not all recipients
12528+
* parsed */
12529+
if (pkcs7->stream->totalRd < ((word32)pkcs7->stream->recipientSz +
12530+
tmpIdx)) {
12531+
idx = tmpIdx + (word32)pkcs7->stream->recipientSz;
12532+
12533+
/* process additional recipients as read */
12534+
if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
12535+
break;
12536+
}
12537+
}
12538+
1250012539
tmpIdx = idx;
1250112540
pkcs7->stream->aadSz = decryptedKeySz;
1250212541
pkcs7->stream->expected = MAX_LENGTH_SZ + MAX_VERSION_SZ +
1250312542
ASN_TAG_SZ + MAX_LENGTH_SZ;
12543+
#else
12544+
idx = tmpIdx + recipientSetSz;
1250412545
#endif
1250512546
wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_3);
1250612547
FALL_THROUGH;

0 commit comments

Comments
 (0)