Skip to content

Commit 7823acb

Browse files
authored
Merge pull request #7184 from JacobBarthelmeh/pkcs7-enc
PKCS7 streaming with encode/sign
2 parents d1e0b37 + 7592559 commit 7823acb

6 files changed

Lines changed: 467 additions & 85 deletions

File tree

tests/api.c

Lines changed: 90 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26916,13 +26916,56 @@ static int test_wc_PKCS7_EncodeSignedData(void)
2691626916
}
2691726917

2691826918
ExpectIntGT(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), 0);
26919-
2692026919
wc_PKCS7_Free(pkcs7);
2692126920
pkcs7 = NULL;
26921+
2692226922
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
2692326923
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0);
2692426924
ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, outputSz), 0);
2692526925

26926+
#ifdef ASN_BER_TO_DER
26927+
wc_PKCS7_Free(pkcs7);
26928+
26929+
/* reinitialize and test setting stream mode */
26930+
{
26931+
int signedSz;
26932+
26933+
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
26934+
ExpectIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0);
26935+
26936+
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0);
26937+
26938+
if (pkcs7 != NULL) {
26939+
pkcs7->content = data;
26940+
pkcs7->contentSz = (word32)sizeof(data);
26941+
pkcs7->privateKey = key;
26942+
pkcs7->privateKeySz = (word32)sizeof(key);
26943+
pkcs7->encryptOID = RSAk;
26944+
#ifdef NO_SHA
26945+
pkcs7->hashOID = SHA256h;
26946+
#else
26947+
pkcs7->hashOID = SHAh;
26948+
#endif
26949+
pkcs7->rng = &rng;
26950+
}
26951+
ExpectIntEQ(wc_PKCS7_GetStreamMode(pkcs7), 0);
26952+
ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1), 0);
26953+
ExpectIntEQ(wc_PKCS7_SetStreamMode(NULL, 1), BAD_FUNC_ARG);
26954+
ExpectIntEQ(wc_PKCS7_GetStreamMode(pkcs7), 1);
26955+
26956+
ExpectIntGT(signedSz = wc_PKCS7_EncodeSignedData(pkcs7, output,
26957+
outputSz), 0);
26958+
wc_PKCS7_Free(pkcs7);
26959+
pkcs7 = NULL;
26960+
26961+
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
26962+
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0);
26963+
26964+
/* use exact signed buffer size since BER encoded */
26965+
ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, signedSz), 0);
26966+
}
26967+
#endif
26968+
2692626969
/* Pass in bad args. */
2692726970
ExpectIntEQ(wc_PKCS7_EncodeSignedData(NULL, output, outputSz),
2692826971
BAD_FUNC_ARG);
@@ -27953,6 +27996,9 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void)
2795327996
EXPECT_DECLS;
2795427997
#if defined(HAVE_PKCS7)
2795527998
PKCS7* pkcs7 = NULL;
27999+
#ifdef ASN_BER_TO_DER
28000+
int encodedSz = 0;
28001+
#endif
2795628002
#ifdef ECC_TIMING_RESISTANT
2795728003
WC_RNG rng;
2795828004
#endif
@@ -28153,6 +28199,39 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void)
2815328199

2815428200
testSz = (int)sizeof(testVectors)/(int)sizeof(pkcs7EnvelopedVector);
2815528201
for (i = 0; i < testSz; i++) {
28202+
#ifdef ASN_BER_TO_DER
28203+
/* test setting stream mode */
28204+
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (testVectors + i)->cert,
28205+
(word32)(testVectors + i)->certSz), 0);
28206+
if (pkcs7 != NULL) {
28207+
#ifdef ECC_TIMING_RESISTANT
28208+
pkcs7->rng = &rng;
28209+
#endif
28210+
28211+
pkcs7->content = (byte*)(testVectors + i)->content;
28212+
pkcs7->contentSz = (testVectors + i)->contentSz;
28213+
pkcs7->contentOID = (testVectors + i)->contentOID;
28214+
pkcs7->encryptOID = (testVectors + i)->encryptOID;
28215+
pkcs7->keyWrapOID = (testVectors + i)->keyWrapOID;
28216+
pkcs7->keyAgreeOID = (testVectors + i)->keyAgreeOID;
28217+
pkcs7->privateKey = (testVectors + i)->privateKey;
28218+
pkcs7->privateKeySz = (testVectors + i)->privateKeySz;
28219+
}
28220+
ExpectIntEQ(wc_PKCS7_SetStreamMode(pkcs7, 1), 0);
28221+
28222+
ExpectIntGE(encodedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, output,
28223+
(word32)sizeof(output)), 0);
28224+
28225+
decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, output,
28226+
(word32)encodedSz, decoded, (word32)sizeof(decoded));
28227+
ExpectIntGE(decodedSz, 0);
28228+
/* Verify the size of each buffer. */
28229+
ExpectIntEQ((word32)sizeof(input)/sizeof(char), decodedSz);
28230+
wc_PKCS7_Free(pkcs7);
28231+
pkcs7 = NULL;
28232+
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
28233+
#endif
28234+
2815628235
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (testVectors + i)->cert,
2815728236
(word32)(testVectors + i)->certSz), 0);
2815828237
if (pkcs7 != NULL) {
@@ -28170,6 +28249,11 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void)
2817028249
pkcs7->privateKeySz = (testVectors + i)->privateKeySz;
2817128250
}
2817228251

28252+
#ifdef ASN_BER_TO_DER
28253+
/* test without setting stream mode */
28254+
ExpectIntEQ(wc_PKCS7_GetStreamMode(pkcs7), 0);
28255+
#endif
28256+
2817328257
ExpectIntGE(wc_PKCS7_EncodeEnvelopedData(pkcs7, output,
2817428258
(word32)sizeof(output)), 0);
2817528259

@@ -28178,6 +28262,7 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void)
2817828262
ExpectIntGE(decodedSz, 0);
2817928263
/* Verify the size of each buffer. */
2818028264
ExpectIntEQ((word32)sizeof(input)/sizeof(char), decodedSz);
28265+
2818128266
/* Don't free the last time through the loop. */
2818228267
if (i < testSz - 1) {
2818328268
wc_PKCS7_Free(pkcs7);
@@ -28871,7 +28956,6 @@ static int test_wc_PKCS7_signed_enveloped(void)
2887128956
#ifdef HAVE_AES_CBC
2887228957
PKCS7* inner = NULL;
2887328958
#endif
28874-
void* pt = NULL;
2887528959
WC_RNG rng;
2887628960
unsigned char key[FOURK_BUF/2];
2887728961
unsigned char cert[FOURK_BUF/2];
@@ -28958,17 +29042,13 @@ static int test_wc_PKCS7_signed_enveloped(void)
2895829042
pkcs7->rng = &rng;
2895929043
}
2896029044

28961-
/* Set no certs in bundle for this test. Hang on to the pointer though to
28962-
* free it later. */
29045+
/* Set no certs in bundle for this test. */
2896329046
if (pkcs7 != NULL) {
28964-
pt = (void*)pkcs7->certList;
28965-
pkcs7->certList = NULL; /* no certs in bundle */
29047+
ExpectIntEQ(wc_PKCS7_SetNoCerts(pkcs7, 1), 0);
29048+
ExpectIntEQ(wc_PKCS7_SetNoCerts(NULL, 1), BAD_FUNC_ARG);
29049+
ExpectIntEQ(wc_PKCS7_GetNoCerts(pkcs7), 1);
2896629050
}
2896729051
ExpectIntGT((sigSz = wc_PKCS7_EncodeSignedData(pkcs7, sig, sigSz)), 0);
28968-
if (pkcs7 != NULL) {
28969-
/* restore pointer for PKCS7 free call */
28970-
pkcs7->certList = (Pkcs7Cert*)pt;
28971-
}
2897229052
wc_PKCS7_Free(pkcs7);
2897329053
pkcs7 = NULL;
2897429054

wolfcrypt/src/asn.c

Lines changed: 118 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3460,6 +3460,70 @@ word32 SetBitString(word32 len, byte unusedBits, byte* output)
34603460
#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 || HAVE_ED448 */
34613461

34623462
#ifdef ASN_BER_TO_DER
3463+
3464+
#define BER_OCTET_LENGTH 4096
3465+
3466+
/* sets the terminating 0x00 0x00 at the end of an indefinite length
3467+
* returns the number of bytes written */
3468+
word32 SetIndefEnd(byte* output)
3469+
{
3470+
byte terminate[ASN_INDEF_END_SZ] = { 0x00, 0x00 };
3471+
3472+
if (output != NULL) {
3473+
XMEMCPY(output, terminate, ASN_INDEF_END_SZ);
3474+
}
3475+
3476+
return (word32)ASN_INDEF_END_SZ;
3477+
}
3478+
3479+
3480+
/* Breaks an octet string up into chunks for use with streaming
3481+
* returns 0 on success and updates idx */
3482+
int StreamOctetString(const byte* inBuf, word32 inBufSz, byte* out, word32* outSz,
3483+
word32* idx)
3484+
{
3485+
word32 i = 0;
3486+
word32 outIdx = *idx;
3487+
byte* tmp = out;
3488+
3489+
if (tmp) tmp += outIdx;
3490+
3491+
while (i < inBufSz) {
3492+
word32 ret, sz;
3493+
3494+
sz = BER_OCTET_LENGTH;
3495+
3496+
if ((sz + i) > inBufSz) {
3497+
sz = inBufSz - i;
3498+
}
3499+
3500+
ret = SetOctetString(sz, tmp);
3501+
if (ret > 0) {
3502+
outIdx += ret;
3503+
}
3504+
3505+
if (tmp) {
3506+
if ((word32)ret + sz + i + outIdx > *outSz) {
3507+
return BUFFER_E;
3508+
}
3509+
XMEMCPY(tmp + ret, inBuf + i, sz);
3510+
tmp += sz + ret;
3511+
}
3512+
outIdx += sz;
3513+
i += sz;
3514+
}
3515+
3516+
if (tmp) {
3517+
*idx = outIdx;
3518+
return 0;
3519+
}
3520+
else {
3521+
*outSz = outIdx;
3522+
return LENGTH_ONLY_E;
3523+
}
3524+
}
3525+
3526+
34633527
/* Convert BER to DER */
34643528

34653529
/* Pull informtation from the ASN.1 BER encoded item header */
@@ -15334,21 +15398,34 @@ word32 SetLength(word32 length, byte* output)
1533415398
return i;
1533515399
}
1533615400

15401+
word32 SetLengthEx(word32 length, byte* output, byte isIndef)
15402+
{
15403+
if (isIndef) {
15404+
if (output != NULL) {
15405+
output[0] = ASN_INDEF_LENGTH;
15406+
}
15407+
return 1;
15408+
}
15409+
else {
15410+
return SetLength(length, output);
15411+
}
15412+
}
1533715413
/* Encode a DER header - type/tag and length.
1533815414
*
1533915415
* @param [in] tag DER tag of ASN.1 item.
1534015416
* @param [in] len Length of data in ASN.1 item.
1534115417
* @param [out] output Buffer to encode into.
1534215418
* @return Number of bytes encoded.
1534315419
*/
15344-
static word32 SetHeader(byte tag, word32 len, byte* output)
15420+
static word32 SetHeader(byte tag, word32 len, byte* output, byte isIndef)
1534515421
{
1534615422
if (output) {
1534715423
/* Encode tag first. */
1534815424
output[0] = tag;
1534915425
}
1535015426
/* Encode the length. */
15351-
return SetLength(len, output ? output + ASN_TAG_SZ : NULL) + ASN_TAG_SZ;
15427+
return SetLengthEx(len, output ? output + ASN_TAG_SZ : NULL, isIndef) +
15428+
ASN_TAG_SZ;
1535215429
}
1535315430

1535415431
/* Encode a SEQUENCE header in DER.
@@ -15359,7 +15436,12 @@ static word32 SetHeader(byte tag, word32 len, byte* output)
1535915436
*/
1536015437
word32 SetSequence(word32 len, byte* output)
1536115438
{
15362-
return SetHeader(ASN_SEQUENCE | ASN_CONSTRUCTED, len, output);
15439+
return SetHeader(ASN_SEQUENCE | ASN_CONSTRUCTED, len, output, 0);
15440+
}
15441+
15442+
word32 SetSequenceEx(word32 len, byte* output, byte isIndef)
15443+
{
15444+
return SetHeader(ASN_SEQUENCE | ASN_CONSTRUCTED, len, output, isIndef);
1536315445
}
1536415446

1536515447
/* Encode an OCTET STRING header in DER.
@@ -15370,7 +15452,14 @@ word32 SetSequence(word32 len, byte* output)
1537015452
*/
1537115453
word32 SetOctetString(word32 len, byte* output)
1537215454
{
15373-
return SetHeader(ASN_OCTET_STRING, len, output);
15455+
return SetHeader(ASN_OCTET_STRING, len, output, 0);
15456+
}
15457+
15458+
word32 SetOctetStringEx(word32 len, byte* output, byte indef)
15459+
{
15460+
if (indef)
15461+
return SetHeader(ASN_OCTET_STRING | ASN_CONSTRUCTED, len, output, indef);
15462+
return SetOctetString(len, output);
1537415463
}
1537515464

1537615465
/* Encode a SET header in DER.
@@ -15381,7 +15470,7 @@ word32 SetOctetString(word32 len, byte* output)
1538115470
*/
1538215471
word32 SetSet(word32 len, byte* output)
1538315472
{
15384-
return SetHeader(ASN_SET | ASN_CONSTRUCTED, len, output);
15473+
return SetHeader(ASN_SET | ASN_CONSTRUCTED, len, output, 0);
1538515474
}
1538615475

1538715476
/* Encode an implicit context specific header in DER.
@@ -15394,11 +15483,23 @@ word32 SetSet(word32 len, byte* output)
1539415483
* @param [out] output Buffer to encode into.
1539515484
* @return Number of bytes encoded.
1539615485
*/
15397-
word32 SetImplicit(byte tag, byte number, word32 len, byte* output)
15486+
word32 SetImplicit(byte tag, byte number, word32 len, byte* output, byte isIndef)
1539815487
{
15399-
tag = (byte)(((tag == ASN_SEQUENCE || tag == ASN_SET) ? ASN_CONSTRUCTED : 0)
15400-
| ASN_CONTEXT_SPECIFIC | number);
15401-
return SetHeader(tag, len, output);
15488+
byte useIndef = 0;
15489+
15490+
if ((tag == ASN_OCTET_STRING) && isIndef) {
15491+
tag = ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | number;
15492+
}
15493+
else {
15494+
tag = (byte)(((tag == ASN_SEQUENCE || tag == ASN_SET) ?
15495+
ASN_CONSTRUCTED : 0) | ASN_CONTEXT_SPECIFIC | number);
15496+
}
15497+
15498+
if (isIndef && (tag & ASN_CONSTRUCTED)) {
15499+
useIndef = 1;
15500+
}
15501+
15502+
return SetHeader(tag, len, output, useIndef);
1540215503
}
1540315504

1540415505
/* Encode an explicit context specific header in DER.
@@ -15410,10 +15511,10 @@ word32 SetImplicit(byte tag, byte number, word32 len, byte* output)
1541015511
* @param [out] output Buffer to encode into.
1541115512
* @return Number of bytes encoded.
1541215513
*/
15413-
word32 SetExplicit(byte number, word32 len, byte* output)
15514+
word32 SetExplicit(byte number, word32 len, byte* output, byte isIndef)
1541415515
{
1541515516
return SetHeader((byte)(ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | number),
15416-
len, output);
15517+
len, output, isIndef);
1541715518
}
1541815519

1541915520
#if defined(OPENSSL_EXTRA)
@@ -15439,18 +15540,18 @@ word32 SetOthername(void *name, byte *output)
1543915540
nameSz = (word32)nm->value->value.utf8string->length;
1544015541

1544115542
len = nm->type_id->objSz +
15442-
SetHeader(ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC, nameSz + 2, NULL) +
15443-
SetHeader(CTC_UTF8, nameSz, NULL) + nameSz;
15543+
SetHeader(ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC, nameSz + 2, NULL, 0) +
15544+
SetHeader(CTC_UTF8, nameSz, NULL, 0) + nameSz;
1544415545

1544515546
if (output != NULL) {
1544615547
/* otherName OID */
1544715548
XMEMCPY(output, nm->type_id->obj, nm->type_id->objSz);
1544815549
output += nm->type_id->objSz;
1544915550

1545015551
output += SetHeader(ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC, nameSz + 2,
15451-
output);
15552+
output, 0);
1545215553

15453-
output += SetHeader(CTC_UTF8, nameSz, output);
15554+
output += SetHeader(CTC_UTF8, nameSz, output, 0);
1545415555

1545515556
XMEMCPY(output, nameStr, nameSz);
1545615557
}
@@ -34454,7 +34555,7 @@ int SetAsymKeyDer(const byte* privKey, word32 privKeyLen,
3445434555
/* pubKey */
3445534556
if (pubKey) {
3445634557
idx += SetHeader(ASN_CONTEXT_SPECIFIC | ASN_ASYMKEY_PUBKEY |
34457-
1, pubKeyLen, output + idx);
34558+
1, pubKeyLen, output + idx, 0);
3445834559
XMEMCPY(output + idx, pubKey, pubKeyLen);
3445934560
idx += pubKeyLen;
3446034561
}
@@ -36355,7 +36456,7 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size)
3635536456
*/
3635636457
extSz = EncodeOcspRequestExtensions(req, extArray + 2,
3635736458
OCSP_NONCE_EXT_SZ);
36358-
extSz += SetExplicit(2, extSz, extArray);
36459+
extSz += SetExplicit(2, extSz, extArray, 0);
3635936460
}
3636036461

3636136462
totalSz = algoSz + issuerSz + issuerKeySz + snSz;

wolfcrypt/src/pkcs12.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1836,7 +1836,7 @@ static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng,
18361836

18371837
/* rewind index and set tag and length */
18381838
tmpIdx -= MAX_LENGTH_SZ + 1;
1839-
sz = (word32)SetExplicit(0, (word32)ret, out + tmpIdx);
1839+
sz = (word32)SetExplicit(0, (word32)ret, out + tmpIdx, 0);
18401840
tmpIdx += sz; totalSz += sz;
18411841
XMEMMOVE(out + tmpIdx, out + MAX_LENGTH_SZ + 1, (size_t)ret);
18421842

0 commit comments

Comments
 (0)