3 * Copyright (C) 2006-2014 wolfSSL Inc.
5 * This file is part of CyaSSL.
7 * CyaSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * CyaSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 #include <cyassl/ctaocrypt/settings.h>
30 #include <cyassl/ctaocrypt/pkcs7.h>
31 #include <cyassl/ctaocrypt/error-crypt.h>
32 #include <cyassl/ctaocrypt/logging.h>
35 static INLINE word32 min(word32 a, word32 b)
42 /* placed ASN.1 contentType OID into *output, return idx on success,
44 CYASSL_LOCAL int SetContentType(int pkcs7TypeOID, byte* output)
46 /* PKCS#7 content types, RFC 2315, section 14 */
47 static const byte pkcs7[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
49 static const byte data[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
50 0x0D, 0x01, 0x07, 0x01 };
51 static const byte signedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
52 0x0D, 0x01, 0x07, 0x02};
53 static const byte envelopedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
54 0x0D, 0x01, 0x07, 0x03 };
55 static const byte signedAndEnveloped[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
56 0x0D, 0x01, 0x07, 0x04 };
57 static const byte digestedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
58 0x0D, 0x01, 0x07, 0x05 };
59 static const byte encryptedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
60 0x0D, 0x01, 0x07, 0x06 };
63 int typeSz = 0, idx = 0;
64 const byte* typeName = 0;
65 byte ID_Length[MAX_LENGTH_SZ];
67 switch (pkcs7TypeOID) {
69 typeSz = sizeof(pkcs7);
74 typeSz = sizeof(data);
79 typeSz = sizeof(signedData);
80 typeName = signedData;
84 typeSz = sizeof(envelopedData);
85 typeName = envelopedData;
88 case SIGNED_AND_ENVELOPED_DATA:
89 typeSz = sizeof(signedAndEnveloped);
90 typeName = signedAndEnveloped;
94 typeSz = sizeof(digestedData);
95 typeName = digestedData;
99 typeSz = sizeof(encryptedData);
100 typeName = encryptedData;
104 CYASSL_MSG("Unknown PKCS#7 Type");
108 idSz = SetLength(typeSz, ID_Length);
109 output[idx++] = ASN_OBJECT_ID;
110 XMEMCPY(output + idx, ID_Length, idSz);
112 XMEMCPY(output + idx, typeName, typeSz);
120 /* get ASN.1 contentType OID sum, return 0 on success, <0 on failure */
121 int GetContentType(const byte* input, word32* inOutIdx, word32* oid,
125 word32 i = *inOutIdx;
129 CYASSL_ENTER("GetContentType");
132 if (b != ASN_OBJECT_ID)
133 return ASN_OBJECT_ID_E;
135 if (GetLength(input, &i, &length, maxIdx) < 0)
149 /* init PKCS7 struct with recipient cert, decode into DecodedCert */
150 int PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz)
154 XMEMSET(pkcs7, 0, sizeof(PKCS7));
155 if (cert != NULL && certSz > 0) {
156 #ifdef CYASSL_SMALL_STACK
159 dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
160 DYNAMIC_TYPE_TMP_BUFFER);
164 DecodedCert stack_dCert;
165 DecodedCert* dCert = &stack_dCert;
168 pkcs7->singleCert = cert;
169 pkcs7->singleCertSz = certSz;
170 InitDecodedCert(dCert, cert, certSz, 0);
172 ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0);
174 FreeDecodedCert(dCert);
175 #ifdef CYASSL_SMALL_STACK
176 XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
181 XMEMCPY(pkcs7->publicKey, dCert->publicKey, dCert->pubKeySize);
182 pkcs7->publicKeySz = dCert->pubKeySize;
183 XMEMCPY(pkcs7->issuerHash, dCert->issuerHash, SHA_SIZE);
184 pkcs7->issuer = dCert->issuerRaw;
185 pkcs7->issuerSz = dCert->issuerRawLen;
186 XMEMCPY(pkcs7->issuerSn, dCert->serial, dCert->serialSz);
187 pkcs7->issuerSnSz = dCert->serialSz;
188 FreeDecodedCert(dCert);
190 #ifdef CYASSL_SMALL_STACK
191 XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
199 /* releases any memory allocated by a PKCS7 initializer */
200 void PKCS7_Free(PKCS7* pkcs7)
206 /* build PKCS#7 data content type */
207 int PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz)
209 static const byte oid[] =
210 { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
212 byte seq[MAX_SEQ_SZ];
213 byte octetStr[MAX_OCTET_STR_SZ];
216 word32 oidSz = (word32)sizeof(oid);
219 octetStrSz = SetOctetString(pkcs7->contentSz, octetStr);
220 seqSz = SetSequence(pkcs7->contentSz + octetStrSz + oidSz, seq);
222 if (outputSz < pkcs7->contentSz + octetStrSz + oidSz + seqSz)
225 XMEMCPY(output, seq, seqSz);
227 XMEMCPY(output + idx, oid, oidSz);
229 XMEMCPY(output + idx, octetStr, octetStrSz);
231 XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
232 idx += pkcs7->contentSz;
238 typedef struct EncodedAttrib {
239 byte valueSeq[MAX_SEQ_SZ];
241 byte valueSet[MAX_SET_SZ];
243 word32 valueSeqSz, oidSz, idSz, valueSetSz, valueSz, totalSz;
249 byte contentDigest[SHA_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */
250 byte contentAttribsDigest[SHA_DIGEST_SIZE];
251 byte encContentDigest[512];
253 byte outerSeq[MAX_SEQ_SZ];
254 byte outerContent[MAX_EXP_SZ];
255 byte innerSeq[MAX_SEQ_SZ];
256 byte version[MAX_VERSION_SZ];
257 byte digAlgoIdSet[MAX_SET_SZ];
258 byte singleDigAlgoId[MAX_ALGO_SZ];
260 byte contentInfoSeq[MAX_SEQ_SZ];
261 byte innerContSeq[MAX_EXP_SZ];
262 byte innerOctets[MAX_OCTET_STR_SZ];
264 byte certsSet[MAX_SET_SZ];
266 byte signerInfoSet[MAX_SET_SZ];
267 byte signerInfoSeq[MAX_SEQ_SZ];
268 byte signerVersion[MAX_VERSION_SZ];
269 byte issuerSnSeq[MAX_SEQ_SZ];
270 byte issuerName[MAX_SEQ_SZ];
271 byte issuerSn[MAX_SN_SZ];
272 byte signerDigAlgoId[MAX_ALGO_SZ];
273 byte digEncAlgoId[MAX_ALGO_SZ];
274 byte signedAttribSet[MAX_SET_SZ];
275 EncodedAttrib signedAttribs[6];
276 byte signerDigest[MAX_OCTET_STR_SZ];
277 word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz;
278 word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz,
279 singleDigAlgoIdSz, certsSetSz;
280 word32 signerInfoSetSz, signerInfoSeqSz, signerVersionSz,
281 issuerSnSeqSz, issuerNameSz, issuerSnSz,
282 signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz;
283 word32 encContentDigestSz, signedAttribsSz, signedAttribsCount,
288 static int EncodeAttributes(EncodedAttrib* ea, int eaSz,
289 PKCS7Attrib* attribs, int attribsSz)
292 int maxSz = min(eaSz, attribsSz);
293 int allAttribsSz = 0;
295 for (i = 0; i < maxSz; i++)
299 ea[i].value = attribs[i].value;
300 ea[i].valueSz = attribs[i].valueSz;
301 attribSz += ea[i].valueSz;
302 ea[i].valueSetSz = SetSet(attribSz, ea[i].valueSet);
303 attribSz += ea[i].valueSetSz;
304 ea[i].oid = attribs[i].oid;
305 ea[i].oidSz = attribs[i].oidSz;
306 attribSz += ea[i].oidSz;
307 ea[i].valueSeqSz = SetSequence(attribSz, ea[i].valueSeq);
308 attribSz += ea[i].valueSeqSz;
309 ea[i].totalSz = attribSz;
311 allAttribsSz += attribSz;
317 static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz)
322 for (i = 0; i < eaSz; i++) {
323 XMEMCPY(output + idx, ea[i].valueSeq, ea[i].valueSeqSz);
324 idx += ea[i].valueSeqSz;
325 XMEMCPY(output + idx, ea[i].oid, ea[i].oidSz);
327 XMEMCPY(output + idx, ea[i].valueSet, ea[i].valueSetSz);
328 idx += ea[i].valueSetSz;
329 XMEMCPY(output + idx, ea[i].value, ea[i].valueSz);
330 idx += ea[i].valueSz;
336 /* build PKCS#7 signedData content type */
337 int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz)
339 static const byte outerOid[] =
340 { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
342 static const byte innerOid[] =
343 { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
346 #ifdef CYASSL_SMALL_STACK
350 ESD* esd = &stack_esd;
353 word32 signerInfoSz = 0;
355 int idx = 0, ret = 0;
356 byte* flatSignedAttribs = NULL;
357 word32 flatSignedAttribsSz = 0;
358 word32 innerOidSz = sizeof(innerOid);
359 word32 outerOidSz = sizeof(outerOid);
361 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
362 pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 ||
363 pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0 ||
364 pkcs7->privateKey == NULL || pkcs7->privateKeySz == 0 ||
365 output == NULL || outputSz == 0)
368 #ifdef CYASSL_SMALL_STACK
369 esd = (ESD*)XMALLOC(sizeof(ESD), NULL, DYNAMIC_TYPE_TMP_BUFFER);
374 XMEMSET(esd, 0, sizeof(ESD));
375 ret = InitSha(&esd->sha);
377 #ifdef CYASSL_SMALL_STACK
378 XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
383 if (pkcs7->contentSz != 0)
385 ShaUpdate(&esd->sha, pkcs7->content, pkcs7->contentSz);
386 esd->contentDigest[0] = ASN_OCTET_STRING;
387 esd->contentDigest[1] = SHA_DIGEST_SIZE;
388 ShaFinal(&esd->sha, &esd->contentDigest[2]);
391 esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets);
392 esd->innerContSeqSz = SetExplicit(0, esd->innerOctetsSz + pkcs7->contentSz,
394 esd->contentInfoSeqSz = SetSequence(pkcs7->contentSz + esd->innerOctetsSz +
395 innerOidSz + esd->innerContSeqSz,
396 esd->contentInfoSeq);
398 esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz,
400 signerInfoSz += esd->issuerSnSz;
401 esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName);
402 signerInfoSz += esd->issuerNameSz + pkcs7->issuerSz;
403 esd->issuerSnSeqSz = SetSequence(signerInfoSz, esd->issuerSnSeq);
404 signerInfoSz += esd->issuerSnSeqSz;
405 esd->signerVersionSz = SetMyVersion(1, esd->signerVersion, 0);
406 signerInfoSz += esd->signerVersionSz;
407 esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId,
409 signerInfoSz += esd->signerDigAlgoIdSz;
410 esd->digEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, esd->digEncAlgoId,
412 signerInfoSz += esd->digEncAlgoIdSz;
414 if (pkcs7->signedAttribsSz != 0) {
415 byte contentTypeOid[] =
416 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01,
419 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
421 byte messageDigestOid[] =
422 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
425 PKCS7Attrib cannedAttribs[2] =
427 { contentTypeOid, sizeof(contentTypeOid),
428 contentType, sizeof(contentType) },
429 { messageDigestOid, sizeof(messageDigestOid),
430 esd->contentDigest, sizeof(esd->contentDigest) }
432 word32 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib);
434 esd->signedAttribsCount += cannedAttribsCount;
435 esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2,
436 cannedAttribs, cannedAttribsCount);
438 esd->signedAttribsCount += pkcs7->signedAttribsSz;
439 esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4,
440 pkcs7->signedAttribs, pkcs7->signedAttribsSz);
442 flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, 0, NULL);
443 flatSignedAttribsSz = esd->signedAttribsSz;
444 if (flatSignedAttribs == NULL) {
445 #ifdef CYASSL_SMALL_STACK
446 XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
450 FlattenAttributes(flatSignedAttribs,
451 esd->signedAttribs, esd->signedAttribsCount);
452 esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz,
453 esd->signedAttribSet);
455 /* Calculate the final hash and encrypt it. */
460 #ifdef CYASSL_SMALL_STACK
464 RsaKey stack_privKey;
465 RsaKey* privKey = &stack_privKey;
466 byte digestInfo[MAX_SEQ_SZ + MAX_ALGO_SZ +
467 MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE];
469 byte digestInfoSeq[MAX_SEQ_SZ];
470 byte digestStr[MAX_OCTET_STR_SZ];
471 word32 digestInfoSeqSz, digestStrSz;
474 if (pkcs7->signedAttribsSz != 0) {
475 byte attribSet[MAX_SET_SZ];
478 attribSetSz = SetSet(flatSignedAttribsSz, attribSet);
480 ret = InitSha(&esd->sha);
482 XFREE(flatSignedAttribs, 0, NULL);
483 #ifdef CYASSL_SMALL_STACK
484 XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
488 ShaUpdate(&esd->sha, attribSet, attribSetSz);
489 ShaUpdate(&esd->sha, flatSignedAttribs, flatSignedAttribsSz);
491 ShaFinal(&esd->sha, esd->contentAttribsDigest);
493 digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr);
494 digestInfoSeqSz = SetSequence(esd->signerDigAlgoIdSz +
495 digestStrSz + SHA_DIGEST_SIZE,
498 #ifdef CYASSL_SMALL_STACK
499 digestInfo = (byte*)XMALLOC(MAX_SEQ_SZ + MAX_ALGO_SZ +
500 MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE,
501 NULL, DYNAMIC_TYPE_TMP_BUFFER);
502 if (digestInfo == NULL) {
503 if (pkcs7->signedAttribsSz != 0)
504 XFREE(flatSignedAttribs, 0, NULL);
505 XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
510 XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
511 digIdx += digestInfoSeqSz;
512 XMEMCPY(digestInfo + digIdx,
513 esd->signerDigAlgoId, esd->signerDigAlgoIdSz);
514 digIdx += esd->signerDigAlgoIdSz;
515 XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
516 digIdx += digestStrSz;
517 XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest,
519 digIdx += SHA_DIGEST_SIZE;
521 #ifdef CYASSL_SMALL_STACK
522 privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL,
523 DYNAMIC_TYPE_TMP_BUFFER);
524 if (privKey == NULL) {
525 if (pkcs7->signedAttribsSz != 0)
526 XFREE(flatSignedAttribs, 0, NULL);
527 XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
528 XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
533 result = InitRsaKey(privKey, NULL);
535 result = RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, privKey,
536 pkcs7->privateKeySz);
538 if (pkcs7->signedAttribsSz != 0)
539 XFREE(flatSignedAttribs, 0, NULL);
540 #ifdef CYASSL_SMALL_STACK
541 XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
542 XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
543 XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
548 result = RsaSSL_Sign(digestInfo, digIdx,
549 esd->encContentDigest,
550 sizeof(esd->encContentDigest),
551 privKey, pkcs7->rng);
555 #ifdef CYASSL_SMALL_STACK
556 XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
557 XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
561 if (pkcs7->signedAttribsSz != 0)
562 XFREE(flatSignedAttribs, 0, NULL);
563 #ifdef CYASSL_SMALL_STACK
564 XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
568 esd->encContentDigestSz = (word32)result;
570 signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz;
572 esd->signerDigestSz = SetOctetString(esd->encContentDigestSz,
574 signerInfoSz += esd->signerDigestSz + esd->encContentDigestSz;
576 esd->signerInfoSeqSz = SetSequence(signerInfoSz, esd->signerInfoSeq);
577 signerInfoSz += esd->signerInfoSeqSz;
578 esd->signerInfoSetSz = SetSet(signerInfoSz, esd->signerInfoSet);
579 signerInfoSz += esd->signerInfoSetSz;
581 esd->certsSetSz = SetImplicit(ASN_SET, 0, pkcs7->singleCertSz,
584 esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId,
586 esd->digAlgoIdSetSz = SetSet(esd->singleDigAlgoIdSz, esd->digAlgoIdSet);
589 esd->versionSz = SetMyVersion(1, esd->version, 0);
591 totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz +
592 esd->contentInfoSeqSz + esd->certsSetSz + pkcs7->singleCertSz +
593 esd->innerOctetsSz + esd->innerContSeqSz +
594 innerOidSz + pkcs7->contentSz +
596 esd->innerSeqSz = SetSequence(totalSz, esd->innerSeq);
597 totalSz += esd->innerSeqSz;
598 esd->outerContentSz = SetExplicit(0, totalSz, esd->outerContent);
599 totalSz += esd->outerContentSz + outerOidSz;
600 esd->outerSeqSz = SetSequence(totalSz, esd->outerSeq);
601 totalSz += esd->outerSeqSz;
603 if (outputSz < totalSz) {
604 if (pkcs7->signedAttribsSz != 0)
605 XFREE(flatSignedAttribs, 0, NULL);
606 #ifdef CYASSL_SMALL_STACK
607 XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
613 XMEMCPY(output + idx, esd->outerSeq, esd->outerSeqSz);
614 idx += esd->outerSeqSz;
615 XMEMCPY(output + idx, outerOid, outerOidSz);
617 XMEMCPY(output + idx, esd->outerContent, esd->outerContentSz);
618 idx += esd->outerContentSz;
619 XMEMCPY(output + idx, esd->innerSeq, esd->innerSeqSz);
620 idx += esd->innerSeqSz;
621 XMEMCPY(output + idx, esd->version, esd->versionSz);
622 idx += esd->versionSz;
623 XMEMCPY(output + idx, esd->digAlgoIdSet, esd->digAlgoIdSetSz);
624 idx += esd->digAlgoIdSetSz;
625 XMEMCPY(output + idx, esd->singleDigAlgoId, esd->singleDigAlgoIdSz);
626 idx += esd->singleDigAlgoIdSz;
627 XMEMCPY(output + idx, esd->contentInfoSeq, esd->contentInfoSeqSz);
628 idx += esd->contentInfoSeqSz;
629 XMEMCPY(output + idx, innerOid, innerOidSz);
631 XMEMCPY(output + idx, esd->innerContSeq, esd->innerContSeqSz);
632 idx += esd->innerContSeqSz;
633 XMEMCPY(output + idx, esd->innerOctets, esd->innerOctetsSz);
634 idx += esd->innerOctetsSz;
635 XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
636 idx += pkcs7->contentSz;
637 XMEMCPY(output + idx, esd->certsSet, esd->certsSetSz);
638 idx += esd->certsSetSz;
639 XMEMCPY(output + idx, pkcs7->singleCert, pkcs7->singleCertSz);
640 idx += pkcs7->singleCertSz;
641 XMEMCPY(output + idx, esd->signerInfoSet, esd->signerInfoSetSz);
642 idx += esd->signerInfoSetSz;
643 XMEMCPY(output + idx, esd->signerInfoSeq, esd->signerInfoSeqSz);
644 idx += esd->signerInfoSeqSz;
645 XMEMCPY(output + idx, esd->signerVersion, esd->signerVersionSz);
646 idx += esd->signerVersionSz;
647 XMEMCPY(output + idx, esd->issuerSnSeq, esd->issuerSnSeqSz);
648 idx += esd->issuerSnSeqSz;
649 XMEMCPY(output + idx, esd->issuerName, esd->issuerNameSz);
650 idx += esd->issuerNameSz;
651 XMEMCPY(output + idx, pkcs7->issuer, pkcs7->issuerSz);
652 idx += pkcs7->issuerSz;
653 XMEMCPY(output + idx, esd->issuerSn, esd->issuerSnSz);
654 idx += esd->issuerSnSz;
655 XMEMCPY(output + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz);
656 idx += esd->signerDigAlgoIdSz;
658 /* SignerInfo:Attributes */
659 if (pkcs7->signedAttribsSz != 0) {
660 XMEMCPY(output + idx, esd->signedAttribSet, esd->signedAttribSetSz);
661 idx += esd->signedAttribSetSz;
662 XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz);
663 idx += flatSignedAttribsSz;
664 XFREE(flatSignedAttribs, 0, NULL);
667 XMEMCPY(output + idx, esd->digEncAlgoId, esd->digEncAlgoIdSz);
668 idx += esd->digEncAlgoIdSz;
669 XMEMCPY(output + idx, esd->signerDigest, esd->signerDigestSz);
670 idx += esd->signerDigestSz;
671 XMEMCPY(output + idx, esd->encContentDigest, esd->encContentDigestSz);
672 idx += esd->encContentDigestSz;
674 #ifdef CYASSL_SMALL_STACK
675 XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
682 /* Finds the certificates in the message and saves it. */
683 int PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
685 word32 idx, contentType;
686 int length, version, ret;
687 byte* content = NULL;
690 int contentSz = 0, sigSz = 0, certSz = 0;
692 if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0)
697 /* Get the contentInfo sequence */
698 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
701 /* Get the contentInfo contentType */
702 if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
705 if (contentType != SIGNED_DATA) {
706 CYASSL_MSG("PKCS#7 input not of type SignedData");
710 /* get the ContentInfo content */
711 if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
714 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
717 /* Get the signedData sequence */
718 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
721 /* Get the version */
722 if (GetMyVersion(pkiMsg, &idx, &version) < 0)
726 CYASSL_MSG("PKCS#7 signedData needs to be of version 1");
727 return ASN_VERSION_E;
730 /* Get the set of DigestAlgorithmIdentifiers */
731 if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
737 /* Get the inner ContentInfo sequence */
738 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
741 /* Get the inner ContentInfo contentType */
742 if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
745 if (contentType != DATA) {
746 CYASSL_MSG("PKCS#7 inner input not of type Data");
750 if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
753 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
756 if (pkiMsg[idx++] != ASN_OCTET_STRING)
759 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
762 /* Save the inner data as the content. */
764 /* Local pointer for calculating hashes later */
765 pkcs7->content = content = &pkiMsg[idx];
766 pkcs7->contentSz = contentSz = length;
770 /* Get the implicit[0] set of certificates */
771 if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
773 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
777 /* At this point, idx is at the first certificate in
778 * a set of certificates. There may be more than one,
779 * or none, or they may be a PKCS 6 extended
780 * certificate. We want to save the first cert if it
783 word32 certIdx = idx;
785 if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
786 if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0)
790 certSz += (certIdx - idx);
792 PKCS7_InitWithCert(pkcs7, cert, certSz);
797 /* Get the implicit[1] set of crls */
798 if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
800 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
807 /* Get the set of signerInfos */
808 if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
812 /* Get the sequence of the first signerInfo */
813 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
816 /* Get the version */
817 if (GetMyVersion(pkiMsg, &idx, &version) < 0)
821 CYASSL_MSG("PKCS#7 signerInfo needs to be of version 1");
822 return ASN_VERSION_E;
825 /* Get the sequence of IssuerAndSerialNumber */
826 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
832 /* Get the sequence of digestAlgorithm */
833 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
839 /* Get the IMPLICIT[0] SET OF signedAttributes */
840 if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
843 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
849 /* Get the sequence of digestEncryptionAlgorithm */
850 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
856 /* Get the signature */
857 if (pkiMsg[idx] == ASN_OCTET_STRING) {
860 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
863 /* save pointer and length */
870 pkcs7->content = content;
871 pkcs7->contentSz = contentSz;
876 int digestSz = MAX_SEQ_SZ + MAX_ALGO_SZ +
877 MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE;
879 #ifdef CYASSL_SMALL_STACK
883 digest = (byte*)XMALLOC(digestSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
888 key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL,
889 DYNAMIC_TYPE_TMP_BUFFER);
891 XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
895 byte digest[digestSz];
897 RsaKey* key = &stack_key;
900 XMEMSET(digest, 0, digestSz);
902 ret = InitRsaKey(key, NULL);
904 #ifdef CYASSL_SMALL_STACK
905 XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
906 XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
910 if (RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key,
911 pkcs7->publicKeySz) < 0) {
912 CYASSL_MSG("ASN RSA key decode error");
913 #ifdef CYASSL_SMALL_STACK
914 XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
915 XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
920 plainSz = RsaSSL_Verify(sig, sigSz, digest, digestSz, key);
923 #ifdef CYASSL_SMALL_STACK
924 XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
925 XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
937 /* create ASN.1 fomatted RecipientInfo structure, returns sequence size */
938 CYASSL_LOCAL int CreateRecipientInfo(const byte* cert, word32 certSz,
939 int keyEncAlgo, int blockKeySz,
940 RNG* rng, byte* contentKeyPlain,
942 int* keyEncSz, byte* out, word32 outSz)
945 int ret = 0, totalSz = 0;
946 int verSz, issuerSz, snSz, keyEncAlgSz;
947 int issuerSeqSz, recipSeqSz, issuerSerialSeqSz;
948 int encKeyOctetStrSz;
950 byte ver[MAX_VERSION_SZ];
951 byte issuerSerialSeq[MAX_SEQ_SZ];
952 byte recipSeq[MAX_SEQ_SZ];
953 byte issuerSeq[MAX_SEQ_SZ];
954 byte encKeyOctetStr[MAX_OCTET_STR_SZ];
956 #ifdef CYASSL_SMALL_STACK
961 DecodedCert* decoded;
963 serial = (byte*)XMALLOC(MAX_SN_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
964 keyAlgArray = (byte*)XMALLOC(MAX_SN_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
965 decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
966 DYNAMIC_TYPE_TMP_BUFFER);
968 if (decoded == NULL || serial == NULL || keyAlgArray == NULL) {
969 if (serial) XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER);
970 if (keyAlgArray) XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
971 if (decoded) XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
976 byte serial[MAX_SN_SZ];
977 byte keyAlgArray[MAX_ALGO_SZ];
980 RsaKey* pubKey = &stack_pubKey;
981 DecodedCert stack_decoded;
982 DecodedCert* decoded = &stack_decoded;
985 InitDecodedCert(decoded, (byte*)cert, certSz, 0);
986 ret = ParseCert(decoded, CA_TYPE, NO_VERIFY, 0);
988 FreeDecodedCert(decoded);
989 #ifdef CYASSL_SMALL_STACK
990 XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER);
991 XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
992 XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
998 verSz = SetMyVersion(0, ver, 0);
1000 /* IssuerAndSerialNumber */
1001 if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) {
1002 CYASSL_MSG("DecodedCert lacks raw issuer pointer and length");
1003 FreeDecodedCert(decoded);
1004 #ifdef CYASSL_SMALL_STACK
1005 XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1006 XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1007 XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1011 issuerSz = decoded->issuerRawLen;
1012 issuerSeqSz = SetSequence(issuerSz, issuerSeq);
1014 if (decoded->serial == NULL || decoded->serialSz == 0) {
1015 CYASSL_MSG("DecodedCert missing serial number");
1016 FreeDecodedCert(decoded);
1017 #ifdef CYASSL_SMALL_STACK
1018 XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1019 XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1020 XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1024 snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial);
1026 issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz,
1029 /* KeyEncryptionAlgorithmIdentifier, only support RSA now */
1030 if (keyEncAlgo != RSAk) {
1031 FreeDecodedCert(decoded);
1032 #ifdef CYASSL_SMALL_STACK
1033 XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1034 XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1035 XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1040 keyEncAlgSz = SetAlgoID(keyEncAlgo, keyAlgArray, keyType, 0);
1041 if (keyEncAlgSz == 0) {
1042 FreeDecodedCert(decoded);
1043 #ifdef CYASSL_SMALL_STACK
1044 XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1045 XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1046 XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1048 return BAD_FUNC_ARG;
1051 #ifdef CYASSL_SMALL_STACK
1052 pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER);
1053 if (pubKey == NULL) {
1054 FreeDecodedCert(decoded);
1055 XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1056 XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1057 XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1063 ret = InitRsaKey(pubKey, 0);
1065 FreeDecodedCert(decoded);
1066 #ifdef CYASSL_SMALL_STACK
1067 XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1068 XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1069 XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1070 XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1075 if (RsaPublicKeyDecode(decoded->publicKey, &idx, pubKey,
1076 decoded->pubKeySize) < 0) {
1077 CYASSL_MSG("ASN RSA key decode error");
1079 FreeDecodedCert(decoded);
1080 #ifdef CYASSL_SMALL_STACK
1081 XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1082 XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1083 XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1084 XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1086 return PUBLIC_KEY_E;
1089 *keyEncSz = RsaPublicEncrypt(contentKeyPlain, blockKeySz, contentKeyEnc,
1090 MAX_ENCRYPTED_KEY_SZ, pubKey, rng);
1093 #ifdef CYASSL_SMALL_STACK
1094 XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1097 if (*keyEncSz < 0) {
1098 CYASSL_MSG("RSA Public Encrypt failed");
1099 FreeDecodedCert(decoded);
1100 #ifdef CYASSL_SMALL_STACK
1101 XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1102 XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1103 XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1108 encKeyOctetStrSz = SetOctetString(*keyEncSz, encKeyOctetStr);
1111 recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz +
1112 issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz +
1113 *keyEncSz, recipSeq);
1115 if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz +
1116 keyEncAlgSz + encKeyOctetStrSz + *keyEncSz > (int)outSz) {
1117 CYASSL_MSG("RecipientInfo output buffer too small");
1118 FreeDecodedCert(decoded);
1119 #ifdef CYASSL_SMALL_STACK
1120 XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1121 XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1122 XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1127 XMEMCPY(out + totalSz, recipSeq, recipSeqSz);
1128 totalSz += recipSeqSz;
1129 XMEMCPY(out + totalSz, ver, verSz);
1131 XMEMCPY(out + totalSz, issuerSerialSeq, issuerSerialSeqSz);
1132 totalSz += issuerSerialSeqSz;
1133 XMEMCPY(out + totalSz, issuerSeq, issuerSeqSz);
1134 totalSz += issuerSeqSz;
1135 XMEMCPY(out + totalSz, decoded->issuerRaw, issuerSz);
1136 totalSz += issuerSz;
1137 XMEMCPY(out + totalSz, serial, snSz);
1139 XMEMCPY(out + totalSz, keyAlgArray, keyEncAlgSz);
1140 totalSz += keyEncAlgSz;
1141 XMEMCPY(out + totalSz, encKeyOctetStr, encKeyOctetStrSz);
1142 totalSz += encKeyOctetStrSz;
1143 XMEMCPY(out + totalSz, contentKeyEnc, *keyEncSz);
1144 totalSz += *keyEncSz;
1146 FreeDecodedCert(decoded);
1148 #ifdef CYASSL_SMALL_STACK
1149 XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1150 XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1151 XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1158 /* build PKCS#7 envelopedData content type, return enveloped size */
1159 int PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
1161 int i, ret = 0, idx = 0;
1162 int totalSz = 0, padSz = 0, desOutSz = 0;
1164 int contentInfoSeqSz, outerContentTypeSz, outerContentSz;
1165 byte contentInfoSeq[MAX_SEQ_SZ];
1166 byte outerContentType[MAX_ALGO_SZ];
1167 byte outerContent[MAX_SEQ_SZ];
1169 int envDataSeqSz, verSz;
1170 byte envDataSeq[MAX_SEQ_SZ];
1171 byte ver[MAX_VERSION_SZ];
1174 int contentKeyEncSz, blockKeySz;
1175 int dynamicFlag = 0;
1176 byte contentKeyPlain[MAX_CONTENT_KEY_LEN];
1177 #ifdef CYASSL_SMALL_STACK
1178 byte* contentKeyEnc;
1180 byte contentKeyEnc[MAX_ENCRYPTED_KEY_SZ];
1183 byte* encryptedContent;
1185 int recipSz, recipSetSz;
1186 #ifdef CYASSL_SMALL_STACK
1189 byte recip[MAX_RECIP_SZ];
1191 byte recipSet[MAX_SET_SZ];
1193 int encContentOctetSz, encContentSeqSz, contentTypeSz;
1194 int contentEncAlgoSz, ivOctetStringSz;
1195 byte encContentSeq[MAX_SEQ_SZ];
1196 byte contentType[MAX_ALGO_SZ];
1197 byte contentEncAlgo[MAX_ALGO_SZ];
1198 byte tmpIv[DES_BLOCK_SIZE];
1199 byte ivOctetString[MAX_OCTET_STR_SZ];
1200 byte encContentOctet[MAX_OCTET_STR_SZ];
1202 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
1203 pkcs7->encryptOID == 0 || pkcs7->singleCert == NULL)
1204 return BAD_FUNC_ARG;
1206 if (output == NULL || outputSz == 0)
1207 return BAD_FUNC_ARG;
1209 /* PKCS#7 only supports DES, 3DES for now */
1210 switch (pkcs7->encryptOID) {
1212 blockKeySz = DES_KEYLEN;
1216 blockKeySz = DES3_KEYLEN;
1220 CYASSL_MSG("Unsupported content cipher type");
1224 /* outer content type */
1225 outerContentTypeSz = SetContentType(ENVELOPED_DATA, outerContentType);
1227 /* version, defined as 0 in RFC 2315 */
1228 verSz = SetMyVersion(0, ver, 0);
1230 /* generate random content encryption key */
1231 ret = InitRng(&rng);
1235 ret = RNG_GenerateBlock(&rng, contentKeyPlain, blockKeySz);
1239 #ifdef CYASSL_SMALL_STACK
1240 recip = (byte*)XMALLOC(MAX_RECIP_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1241 contentKeyEnc = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, NULL,
1242 DYNAMIC_TYPE_TMP_BUFFER);
1243 if (contentKeyEnc == NULL || recip == NULL) {
1244 if (recip) XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1245 if (contentKeyEnc) XFREE(contentKeyEnc, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1251 /* build RecipientInfo, only handle 1 for now */
1252 recipSz = CreateRecipientInfo(pkcs7->singleCert, pkcs7->singleCertSz, RSAk,
1253 blockKeySz, &rng, contentKeyPlain,
1254 contentKeyEnc, &contentKeyEncSz, recip,
1257 XMEMSET(contentKeyEnc, 0, MAX_ENCRYPTED_KEY_SZ);
1259 #ifdef CYASSL_SMALL_STACK
1260 XFREE(contentKeyEnc, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1264 CYASSL_MSG("Failed to create RecipientInfo");
1265 #ifdef CYASSL_SMALL_STACK
1266 XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1270 recipSetSz = SetSet(recipSz, recipSet);
1272 /* generate IV for block cipher */
1273 ret = RNG_GenerateBlock(&rng, tmpIv, DES_BLOCK_SIZE);
1275 #ifdef CYASSL_SMALL_STACK
1276 XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1281 /* EncryptedContentInfo */
1282 contentTypeSz = SetContentType(pkcs7->contentOID, contentType);
1283 if (contentTypeSz == 0) {
1284 #ifdef CYASSL_SMALL_STACK
1285 XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1287 return BAD_FUNC_ARG;
1290 /* allocate encrypted content buffer, pad if necessary, PKCS#7 padding */
1291 padSz = DES_BLOCK_SIZE - (pkcs7->contentSz % DES_BLOCK_SIZE);
1292 desOutSz = pkcs7->contentSz + padSz;
1295 plain = (byte*)XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1296 if (plain == NULL) {
1297 #ifdef CYASSL_SMALL_STACK
1298 XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1302 XMEMCPY(plain, pkcs7->content, pkcs7->contentSz);
1305 for (i = 0; i < padSz; i++) {
1306 plain[pkcs7->contentSz + i] = padSz;
1310 plain = pkcs7->content;
1311 desOutSz = pkcs7->contentSz;
1314 encryptedContent = (byte*)XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1315 if (encryptedContent == NULL) {
1317 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1318 #ifdef CYASSL_SMALL_STACK
1319 XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1324 /* put together IV OCTET STRING */
1325 ivOctetStringSz = SetOctetString(DES_BLOCK_SIZE, ivOctetString);
1327 /* build up our ContentEncryptionAlgorithmIdentifier sequence,
1328 * adding (ivOctetStringSz + DES_BLOCK_SIZE) for IV OCTET STRING */
1329 contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
1330 blkType, ivOctetStringSz + DES_BLOCK_SIZE);
1332 if (contentEncAlgoSz == 0) {
1333 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1335 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1336 #ifdef CYASSL_SMALL_STACK
1337 XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1339 return BAD_FUNC_ARG;
1342 /* encrypt content */
1343 if (pkcs7->encryptOID == DESb) {
1346 ret = Des_SetKey(&des, contentKeyPlain, tmpIv, DES_ENCRYPTION);
1349 Des_CbcEncrypt(&des, encryptedContent, plain, desOutSz);
1352 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1354 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1355 #ifdef CYASSL_SMALL_STACK
1356 XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1361 else if (pkcs7->encryptOID == DES3b) {
1364 ret = Des3_SetKey(&des3, contentKeyPlain, tmpIv, DES_ENCRYPTION);
1367 ret = Des3_CbcEncrypt(&des3, encryptedContent, plain, desOutSz);
1370 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1372 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1373 #ifdef CYASSL_SMALL_STACK
1374 XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1380 encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0,
1381 desOutSz, encContentOctet);
1383 encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
1384 ivOctetStringSz + DES_BLOCK_SIZE +
1385 encContentOctetSz + desOutSz, encContentSeq);
1387 /* keep track of sizes for outer wrapper layering */
1388 totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz +
1389 contentEncAlgoSz + ivOctetStringSz + DES_BLOCK_SIZE +
1390 encContentOctetSz + desOutSz;
1393 envDataSeqSz = SetSequence(totalSz, envDataSeq);
1394 totalSz += envDataSeqSz;
1397 outerContentSz = SetExplicit(0, totalSz, outerContent);
1398 totalSz += outerContentTypeSz;
1399 totalSz += outerContentSz;
1402 contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
1403 totalSz += contentInfoSeqSz;
1405 if (totalSz > (int)outputSz) {
1406 CYASSL_MSG("Pkcs7_encrypt output buffer too small");
1407 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1409 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1410 #ifdef CYASSL_SMALL_STACK
1411 XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1416 XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz);
1417 idx += contentInfoSeqSz;
1418 XMEMCPY(output + idx, outerContentType, outerContentTypeSz);
1419 idx += outerContentTypeSz;
1420 XMEMCPY(output + idx, outerContent, outerContentSz);
1421 idx += outerContentSz;
1422 XMEMCPY(output + idx, envDataSeq, envDataSeqSz);
1423 idx += envDataSeqSz;
1424 XMEMCPY(output + idx, ver, verSz);
1426 XMEMCPY(output + idx, recipSet, recipSetSz);
1428 XMEMCPY(output + idx, recip, recipSz);
1430 XMEMCPY(output + idx, encContentSeq, encContentSeqSz);
1431 idx += encContentSeqSz;
1432 XMEMCPY(output + idx, contentType, contentTypeSz);
1433 idx += contentTypeSz;
1434 XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz);
1435 idx += contentEncAlgoSz;
1436 XMEMCPY(output + idx, ivOctetString, ivOctetStringSz);
1437 idx += ivOctetStringSz;
1438 XMEMCPY(output + idx, tmpIv, DES_BLOCK_SIZE);
1439 idx += DES_BLOCK_SIZE;
1440 XMEMCPY(output + idx, encContentOctet, encContentOctetSz);
1441 idx += encContentOctetSz;
1442 XMEMCPY(output + idx, encryptedContent, desOutSz);
1449 XMEMSET(contentKeyPlain, 0, MAX_CONTENT_KEY_LEN);
1452 XFREE(plain, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1453 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1455 #ifdef CYASSL_SMALL_STACK
1456 XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1462 /* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */
1463 CYASSL_API int PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
1464 word32 pkiMsgSz, byte* output,
1468 int ret, version, length;
1469 word32 savedIdx = 0, idx = 0;
1470 word32 contentType, encOID;
1471 byte issuerHash[SHA_DIGEST_SIZE];
1473 int encryptedKeySz, keySz;
1474 byte tmpIv[DES_BLOCK_SIZE];
1475 byte* decryptedKey = NULL;
1477 #ifdef CYASSL_SMALL_STACK
1482 mp_int stack_serialNum;
1483 mp_int* serialNum = &stack_serialNum;
1484 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
1486 RsaKey stack_privKey;
1487 RsaKey* privKey = &stack_privKey;
1489 int encryptedContentSz;
1491 byte* encryptedContent = NULL;
1493 if (pkcs7 == NULL || pkcs7->singleCert == NULL ||
1494 pkcs7->singleCertSz == 0 || pkcs7->privateKey == NULL ||
1495 pkcs7->privateKeySz == 0)
1496 return BAD_FUNC_ARG;
1498 if (pkiMsg == NULL || pkiMsgSz == 0 ||
1499 output == NULL || outputSz == 0)
1500 return BAD_FUNC_ARG;
1502 /* read past ContentInfo, verify type is envelopedData */
1503 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
1506 if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
1509 if (contentType != ENVELOPED_DATA) {
1510 CYASSL_MSG("PKCS#7 input not of type EnvelopedData");
1514 if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
1517 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
1520 /* remove EnvelopedData and version */
1521 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
1524 if (GetMyVersion(pkiMsg, &idx, &version) < 0)
1528 CYASSL_MSG("PKCS#7 envelopedData needs to be of version 0");
1529 return ASN_VERSION_E;
1532 /* walk through RecipientInfo set, find correct recipient */
1533 if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
1536 #ifdef CYASSL_SMALL_STACK
1537 encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, NULL,
1538 DYNAMIC_TYPE_TMP_BUFFER);
1539 if (encryptedKey == NULL)
1546 /* when looking for next recipient, use first sequence and version to
1547 * indicate there is another, if not, move on */
1548 while(recipFound == 0) {
1550 /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to
1551 * last good saved one */
1552 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
1557 if (GetMyVersion(pkiMsg, &idx, &version) < 0) {
1563 #ifdef CYASSL_SMALL_STACK
1564 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1566 return ASN_VERSION_E;
1569 /* remove IssuerAndSerialNumber */
1570 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
1571 #ifdef CYASSL_SMALL_STACK
1572 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1577 if (GetNameHash(pkiMsg, &idx, issuerHash, pkiMsgSz) < 0) {
1578 #ifdef CYASSL_SMALL_STACK
1579 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1584 /* if we found correct recipient, issuer hashes will match */
1585 if (XMEMCMP(issuerHash, pkcs7->issuerHash, SHA_DIGEST_SIZE) == 0) {
1589 #ifdef CYASSL_SMALL_STACK
1590 serialNum = (mp_int*)XMALLOC(sizeof(mp_int), NULL,
1591 DYNAMIC_TYPE_TMP_BUFFER);
1592 if (serialNum == NULL) {
1593 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1598 if (GetInt(serialNum, pkiMsg, &idx, pkiMsgSz) < 0) {
1599 #ifdef CYASSL_SMALL_STACK
1600 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1601 XFREE(serialNum, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1606 mp_clear(serialNum);
1608 #ifdef CYASSL_SMALL_STACK
1609 XFREE(serialNum, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1612 if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0) {
1613 #ifdef CYASSL_SMALL_STACK
1614 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1619 /* key encryption algorithm must be RSA for now */
1620 if (encOID != RSAk) {
1621 #ifdef CYASSL_SMALL_STACK
1622 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1627 /* read encryptedKey */
1628 if (pkiMsg[idx++] != ASN_OCTET_STRING) {
1629 #ifdef CYASSL_SMALL_STACK
1630 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1635 if (GetLength(pkiMsg, &idx, &encryptedKeySz, pkiMsgSz) < 0) {
1636 #ifdef CYASSL_SMALL_STACK
1637 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1642 if (recipFound == 1)
1643 XMEMCPY(encryptedKey, &pkiMsg[idx], encryptedKeySz);
1644 idx += encryptedKeySz;
1646 /* update good idx */
1650 if (recipFound == 0) {
1651 CYASSL_MSG("No recipient found in envelopedData that matches input");
1652 #ifdef CYASSL_SMALL_STACK
1653 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1655 return PKCS7_RECIP_E;
1658 /* remove EncryptedContentInfo */
1659 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
1660 #ifdef CYASSL_SMALL_STACK
1661 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1666 if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) {
1667 #ifdef CYASSL_SMALL_STACK
1668 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1673 if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0) {
1674 #ifdef CYASSL_SMALL_STACK
1675 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1680 /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
1681 if (pkiMsg[idx++] != ASN_OCTET_STRING) {
1682 #ifdef CYASSL_SMALL_STACK
1683 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1688 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
1689 #ifdef CYASSL_SMALL_STACK
1690 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1695 if (length != DES_BLOCK_SIZE) {
1696 CYASSL_MSG("Incorrect IV length, must be of DES_BLOCK_SIZE");
1697 #ifdef CYASSL_SMALL_STACK
1698 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1703 XMEMCPY(tmpIv, &pkiMsg[idx], length);
1706 /* read encryptedContent, cont[0] */
1707 if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) {
1708 #ifdef CYASSL_SMALL_STACK
1709 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1714 if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0) {
1715 #ifdef CYASSL_SMALL_STACK
1716 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1721 encryptedContent = (byte*)XMALLOC(encryptedContentSz, NULL,
1722 DYNAMIC_TYPE_TMP_BUFFER);
1723 if (encryptedContent == NULL) {
1724 #ifdef CYASSL_SMALL_STACK
1725 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1730 XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
1732 /* load private key */
1733 #ifdef CYASSL_SMALL_STACK
1734 privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER);
1735 if (privKey == NULL) {
1736 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1737 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E;
1741 ret = InitRsaKey(privKey, 0);
1743 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1744 #ifdef CYASSL_SMALL_STACK
1745 XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1746 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1753 ret = RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey,
1754 pkcs7->privateKeySz);
1756 CYASSL_MSG("Failed to decode RSA private key");
1757 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1758 #ifdef CYASSL_SMALL_STACK
1759 XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1760 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1765 /* decrypt encryptedKey */
1766 keySz = RsaPrivateDecryptInline(encryptedKey, encryptedKeySz,
1767 &decryptedKey, privKey);
1768 FreeRsaKey(privKey);
1770 #ifdef CYASSL_SMALL_STACK
1771 XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1775 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1776 #ifdef CYASSL_SMALL_STACK
1777 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1782 /* decrypt encryptedContent */
1783 if (encOID == DESb) {
1785 ret = Des_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION);
1788 Des_CbcDecrypt(&des, encryptedContent, encryptedContent,
1789 encryptedContentSz);
1792 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1793 #ifdef CYASSL_SMALL_STACK
1794 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1799 else if (encOID == DES3b) {
1801 ret = Des3_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION);
1803 ret = Des3_CbcDecrypt(&des, encryptedContent, encryptedContent,
1804 encryptedContentSz);
1807 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1808 #ifdef CYASSL_SMALL_STACK
1809 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1814 CYASSL_MSG("Unsupported content encryption OID type");
1815 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1816 #ifdef CYASSL_SMALL_STACK
1817 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1822 padLen = encryptedContent[encryptedContentSz-1];
1824 /* copy plaintext to output */
1825 XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
1827 /* free memory, zero out keys */
1828 XMEMSET(encryptedKey, 0, MAX_ENCRYPTED_KEY_SZ);
1829 XMEMSET(encryptedContent, 0, encryptedContentSz);
1830 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1831 #ifdef CYASSL_SMALL_STACK
1832 XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1835 return encryptedContentSz - padLen;
1839 #else /* HAVE_PKCS7 */
1843 /* 4206 warning for blank file */
1844 #pragma warning(disable: 4206)
1848 #endif /* HAVE_PKCS7 */