]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/CyaSSL/ctaocrypt/src/pkcs7.c
Update CyaSSL to latest version.
[freertos] / FreeRTOS-Plus / Source / CyaSSL / ctaocrypt / src / pkcs7.c
1 /* pkcs7.c
2  *
3  * Copyright (C) 2006-2014 wolfSSL Inc.
4  *
5  * This file is part of CyaSSL.
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25
26 #include <cyassl/ctaocrypt/settings.h>
27
28 #ifdef HAVE_PKCS7
29
30 #include <cyassl/ctaocrypt/pkcs7.h>
31 #include <cyassl/ctaocrypt/error-crypt.h>
32 #include <cyassl/ctaocrypt/logging.h>
33
34 #ifndef min
35     static INLINE word32 min(word32 a, word32 b)
36     {
37         return a > b ? b : a;
38     }
39 #endif
40
41
42 /* placed ASN.1 contentType OID into *output, return idx on success,
43  * 0 upon failure */
44 CYASSL_LOCAL int SetContentType(int pkcs7TypeOID, byte* output)
45 {
46     /* PKCS#7 content types, RFC 2315, section 14 */
47     static const byte pkcs7[]              = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
48                                                0x0D, 0x01, 0x07 };
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 };
61
62     int idSz;
63     int typeSz = 0, idx = 0;
64     const byte* typeName = 0;
65     byte ID_Length[MAX_LENGTH_SZ];
66
67     switch (pkcs7TypeOID) {
68         case PKCS7_MSG:
69             typeSz = sizeof(pkcs7);
70             typeName = pkcs7;
71             break;
72
73         case DATA:
74             typeSz = sizeof(data);
75             typeName = data;
76             break;
77
78         case SIGNED_DATA:
79             typeSz = sizeof(signedData);
80             typeName = signedData;
81             break;
82         
83         case ENVELOPED_DATA:
84             typeSz = sizeof(envelopedData);
85             typeName = envelopedData;
86             break;
87
88         case SIGNED_AND_ENVELOPED_DATA:
89             typeSz = sizeof(signedAndEnveloped);
90             typeName = signedAndEnveloped;
91             break;
92
93         case DIGESTED_DATA:
94             typeSz = sizeof(digestedData);
95             typeName = digestedData;
96             break;
97
98         case ENCRYPTED_DATA:
99             typeSz = sizeof(encryptedData);
100             typeName = encryptedData;
101             break;
102
103         default:
104             CYASSL_MSG("Unknown PKCS#7 Type");
105             return 0;
106     };
107
108     idSz  = SetLength(typeSz, ID_Length);
109     output[idx++] = ASN_OBJECT_ID;
110     XMEMCPY(output + idx, ID_Length, idSz);
111     idx += idSz;
112     XMEMCPY(output + idx, typeName, typeSz);
113     idx += typeSz;
114
115     return idx;
116
117 }
118
119
120 /* get ASN.1 contentType OID sum, return 0 on success, <0 on failure */
121 int GetContentType(const byte* input, word32* inOutIdx, word32* oid,
122                    word32 maxIdx)
123 {
124     int length;
125     word32 i = *inOutIdx;
126     byte b;
127     *oid = 0;
128
129     CYASSL_ENTER("GetContentType");
130
131     b = input[i++];
132     if (b != ASN_OBJECT_ID)
133         return ASN_OBJECT_ID_E;
134
135     if (GetLength(input, &i, &length, maxIdx) < 0)
136         return ASN_PARSE_E;
137
138     while(length--) {
139         *oid += input[i];
140         i++;
141     }
142
143     *inOutIdx = i;
144
145     return 0;
146 }
147
148
149 /* init PKCS7 struct with recipient cert, decode into DecodedCert */
150 int PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz)
151 {
152     int ret = 0;
153
154     XMEMSET(pkcs7, 0, sizeof(PKCS7));
155     if (cert != NULL && certSz > 0) {
156 #ifdef CYASSL_SMALL_STACK
157         DecodedCert* dCert;
158
159         dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
160                                                        DYNAMIC_TYPE_TMP_BUFFER);
161         if (dCert == NULL)
162             return MEMORY_E;
163 #else
164         DecodedCert stack_dCert;
165         DecodedCert* dCert = &stack_dCert;
166 #endif
167
168         pkcs7->singleCert = cert;
169         pkcs7->singleCertSz = certSz;
170         InitDecodedCert(dCert, cert, certSz, 0);
171
172         ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0);
173         if (ret < 0) {
174             FreeDecodedCert(dCert);
175 #ifdef CYASSL_SMALL_STACK
176             XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
177 #endif
178             return ret;
179         }
180
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);
189
190 #ifdef CYASSL_SMALL_STACK
191         XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
192 #endif
193     }
194
195     return ret;
196 }
197
198
199 /* releases any memory allocated by a PKCS7 initializer */
200 void PKCS7_Free(PKCS7* pkcs7)
201 {
202     (void)pkcs7;
203 }
204
205
206 /* build PKCS#7 data content type */
207 int PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz)
208 {
209     static const byte oid[] =
210         { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
211                          0x07, 0x01 };
212     byte seq[MAX_SEQ_SZ];
213     byte octetStr[MAX_OCTET_STR_SZ];
214     word32 seqSz;
215     word32 octetStrSz;
216     word32 oidSz = (word32)sizeof(oid);
217     int idx = 0;
218
219     octetStrSz = SetOctetString(pkcs7->contentSz, octetStr);
220     seqSz = SetSequence(pkcs7->contentSz + octetStrSz + oidSz, seq);
221
222     if (outputSz < pkcs7->contentSz + octetStrSz + oidSz + seqSz)
223         return BUFFER_E;
224
225     XMEMCPY(output, seq, seqSz);
226     idx += seqSz;
227     XMEMCPY(output + idx, oid, oidSz);
228     idx += oidSz;
229     XMEMCPY(output + idx, octetStr, octetStrSz);
230     idx += octetStrSz;
231     XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
232     idx += pkcs7->contentSz;
233
234     return idx;
235 }
236
237
238 typedef struct EncodedAttrib {
239     byte valueSeq[MAX_SEQ_SZ];
240         const byte* oid;
241         byte valueSet[MAX_SET_SZ];
242         const byte* value;
243     word32 valueSeqSz, oidSz, idSz, valueSetSz, valueSz, totalSz;
244 } EncodedAttrib;
245
246
247 typedef struct ESD {
248     Sha sha;
249     byte contentDigest[SHA_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */
250     byte contentAttribsDigest[SHA_DIGEST_SIZE];
251     byte encContentDigest[512];
252
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];
259
260                 byte contentInfoSeq[MAX_SEQ_SZ];
261                     byte innerContSeq[MAX_EXP_SZ];
262                         byte innerOctets[MAX_OCTET_STR_SZ];
263
264                 byte certsSet[MAX_SET_SZ];
265
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,
284            signedAttribSetSz;
285 } ESD;
286
287
288 static int EncodeAttributes(EncodedAttrib* ea, int eaSz,
289                                             PKCS7Attrib* attribs, int attribsSz)
290 {
291     int i;
292     int maxSz = min(eaSz, attribsSz);
293     int allAttribsSz = 0;
294
295     for (i = 0; i < maxSz; i++)
296     {
297         int attribSz = 0;
298
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;
310
311         allAttribsSz += attribSz;
312     }
313     return allAttribsSz;
314 }
315
316
317 static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz)
318 {
319     int i, idx;
320
321     idx = 0;
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);
326         idx += 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;
331     }
332     return 0;
333 }
334
335
336 /* build PKCS#7 signedData content type */
337 int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz)
338 {
339     static const byte outerOid[] =
340         { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
341                          0x07, 0x02 };
342     static const byte innerOid[] =
343         { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
344                          0x07, 0x01 };
345
346 #ifdef CYASSL_SMALL_STACK
347     ESD* esd = NULL;
348 #else
349     ESD stack_esd;
350     ESD* esd = &stack_esd;
351 #endif
352
353     word32 signerInfoSz = 0;
354     word32 totalSz = 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);
360
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)
366         return BAD_FUNC_ARG;
367
368 #ifdef CYASSL_SMALL_STACK
369     esd = (ESD*)XMALLOC(sizeof(ESD), NULL, DYNAMIC_TYPE_TMP_BUFFER);
370     if (esd == NULL)
371         return MEMORY_E;
372 #endif
373
374     XMEMSET(esd, 0, sizeof(ESD));
375     ret = InitSha(&esd->sha);
376     if (ret != 0) {
377 #ifdef CYASSL_SMALL_STACK
378         XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
379 #endif
380         return ret;
381     }
382
383     if (pkcs7->contentSz != 0)
384     {
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]);
389     }
390
391     esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets);
392     esd->innerContSeqSz = SetExplicit(0, esd->innerOctetsSz + pkcs7->contentSz,
393                                 esd->innerContSeq);
394     esd->contentInfoSeqSz = SetSequence(pkcs7->contentSz + esd->innerOctetsSz +
395                                     innerOidSz + esd->innerContSeqSz,
396                                     esd->contentInfoSeq);
397
398     esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz,
399                                      esd->issuerSn);
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,
408                                       hashType, 0);
409     signerInfoSz += esd->signerDigAlgoIdSz;
410     esd->digEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, esd->digEncAlgoId,
411                                    keyType, 0);
412     signerInfoSz += esd->digEncAlgoIdSz;
413
414     if (pkcs7->signedAttribsSz != 0) {
415         byte contentTypeOid[] =
416                 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01,
417                                  0x09, 0x03 };
418         byte contentType[] =
419                 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
420                                  0x07, 0x01 };
421         byte messageDigestOid[] =
422                 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
423                                  0x09, 0x04 };
424
425         PKCS7Attrib cannedAttribs[2] =
426         {
427             { contentTypeOid, sizeof(contentTypeOid),
428                              contentType, sizeof(contentType) },
429             { messageDigestOid, sizeof(messageDigestOid),
430                              esd->contentDigest, sizeof(esd->contentDigest) }
431         };
432         word32 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib);
433
434         esd->signedAttribsCount += cannedAttribsCount;
435         esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2,
436                                              cannedAttribs, cannedAttribsCount);
437
438         esd->signedAttribsCount += pkcs7->signedAttribsSz;
439         esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4,
440                                   pkcs7->signedAttribs, pkcs7->signedAttribsSz);
441
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);
447 #endif   
448             return MEMORY_E;
449         }
450         FlattenAttributes(flatSignedAttribs,
451                                    esd->signedAttribs, esd->signedAttribsCount);
452         esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz,
453                                                           esd->signedAttribSet);
454     }
455     /* Calculate the final hash and encrypt it. */
456     {
457         int result;
458         word32 scratch = 0;
459
460 #ifdef CYASSL_SMALL_STACK
461         byte* digestInfo;
462         RsaKey* privKey;
463 #else
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];
468 #endif
469         byte digestInfoSeq[MAX_SEQ_SZ];
470         byte digestStr[MAX_OCTET_STR_SZ];
471         word32 digestInfoSeqSz, digestStrSz;
472         int digIdx = 0;
473
474         if (pkcs7->signedAttribsSz != 0) {
475             byte attribSet[MAX_SET_SZ];
476             word32 attribSetSz;
477
478             attribSetSz = SetSet(flatSignedAttribsSz, attribSet);
479
480             ret = InitSha(&esd->sha);
481             if (ret < 0) {
482                 XFREE(flatSignedAttribs, 0, NULL);
483 #ifdef CYASSL_SMALL_STACK
484                 XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
485 #endif
486                 return ret;
487             }
488             ShaUpdate(&esd->sha, attribSet, attribSetSz);
489             ShaUpdate(&esd->sha, flatSignedAttribs, flatSignedAttribsSz);
490         }
491         ShaFinal(&esd->sha, esd->contentAttribsDigest);
492
493         digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr);
494         digestInfoSeqSz = SetSequence(esd->signerDigAlgoIdSz +
495                                       digestStrSz + SHA_DIGEST_SIZE,
496                                       digestInfoSeq);
497
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);
506             return MEMORY_E;
507         }
508 #endif
509
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,
518                                                                SHA_DIGEST_SIZE);
519         digIdx += SHA_DIGEST_SIZE;
520
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);
529             return MEMORY_E;
530         }
531 #endif
532
533         result = InitRsaKey(privKey, NULL);
534         if (result == 0)
535             result = RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, privKey,
536                                          pkcs7->privateKeySz);
537         if (result < 0) {
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);
544 #endif
545             return PUBLIC_KEY_E;
546         }
547
548         result = RsaSSL_Sign(digestInfo, digIdx,
549                              esd->encContentDigest,
550                              sizeof(esd->encContentDigest),
551                              privKey, pkcs7->rng);
552
553         FreeRsaKey(privKey);
554
555 #ifdef CYASSL_SMALL_STACK
556         XFREE(privKey,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
557         XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
558 #endif
559
560         if (result < 0) {
561             if (pkcs7->signedAttribsSz != 0)
562                 XFREE(flatSignedAttribs, 0, NULL);
563 #ifdef CYASSL_SMALL_STACK
564             XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
565 #endif
566             return result;
567         }
568         esd->encContentDigestSz = (word32)result;
569     }
570     signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz;
571
572     esd->signerDigestSz = SetOctetString(esd->encContentDigestSz,
573                                                              esd->signerDigest);
574     signerInfoSz += esd->signerDigestSz + esd->encContentDigestSz;
575
576     esd->signerInfoSeqSz = SetSequence(signerInfoSz, esd->signerInfoSeq);
577     signerInfoSz += esd->signerInfoSeqSz;
578     esd->signerInfoSetSz = SetSet(signerInfoSz, esd->signerInfoSet);
579     signerInfoSz += esd->signerInfoSetSz;
580
581     esd->certsSetSz = SetImplicit(ASN_SET, 0, pkcs7->singleCertSz,
582                                                                  esd->certsSet);
583
584     esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId,
585                                       hashType, 0);
586     esd->digAlgoIdSetSz = SetSet(esd->singleDigAlgoIdSz, esd->digAlgoIdSet);
587
588
589     esd->versionSz = SetMyVersion(1, esd->version, 0);
590
591     totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz +
592               esd->contentInfoSeqSz + esd->certsSetSz + pkcs7->singleCertSz +
593               esd->innerOctetsSz + esd->innerContSeqSz +
594               innerOidSz + pkcs7->contentSz +
595               signerInfoSz;
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;
602
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);
608 #endif
609         return BUFFER_E;
610     }
611
612     idx = 0;
613     XMEMCPY(output + idx, esd->outerSeq, esd->outerSeqSz);
614     idx += esd->outerSeqSz;
615     XMEMCPY(output + idx, outerOid, outerOidSz);
616     idx += 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);
630     idx += 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;
657
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);
665     }
666
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;
673
674 #ifdef CYASSL_SMALL_STACK
675     XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
676 #endif
677
678     return idx;
679 }
680
681
682 /* Finds the certificates in the message and saves it. */
683 int PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
684 {
685     word32 idx, contentType;
686     int length, version, ret;
687     byte* content = NULL;
688     byte* sig = NULL;
689     byte* cert = NULL;
690     int contentSz = 0, sigSz = 0, certSz = 0;
691
692     if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0)
693         return BAD_FUNC_ARG;
694
695     idx = 0;
696
697     /* Get the contentInfo sequence */
698     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
699         return ASN_PARSE_E;
700
701     /* Get the contentInfo contentType */
702     if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
703         return ASN_PARSE_E;
704
705     if (contentType != SIGNED_DATA) {
706         CYASSL_MSG("PKCS#7 input not of type SignedData");
707         return PKCS7_OID_E;
708     }
709
710     /* get the ContentInfo content */
711     if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
712         return ASN_PARSE_E;
713
714     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
715         return ASN_PARSE_E;
716
717     /* Get the signedData sequence */
718     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
719         return ASN_PARSE_E;
720
721     /* Get the version */
722     if (GetMyVersion(pkiMsg, &idx, &version) < 0)
723         return ASN_PARSE_E;
724
725     if (version != 1) {
726         CYASSL_MSG("PKCS#7 signedData needs to be of version 1");
727         return ASN_VERSION_E;
728     }
729
730     /* Get the set of DigestAlgorithmIdentifiers */
731     if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
732         return ASN_PARSE_E;
733
734     /* Skip the set. */
735     idx += length;
736
737     /* Get the inner ContentInfo sequence */
738     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
739         return ASN_PARSE_E;
740
741     /* Get the inner ContentInfo contentType */
742     if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
743         return ASN_PARSE_E;
744
745     if (contentType != DATA) {
746         CYASSL_MSG("PKCS#7 inner input not of type Data");
747         return PKCS7_OID_E;
748     }
749
750     if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
751         return ASN_PARSE_E;
752
753     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
754         return ASN_PARSE_E;
755
756     if (pkiMsg[idx++] != ASN_OCTET_STRING)
757         return ASN_PARSE_E;
758
759     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
760         return ASN_PARSE_E;
761
762     /* Save the inner data as the content. */
763     if (length > 0) {
764         /* Local pointer for calculating hashes later */
765         pkcs7->content = content = &pkiMsg[idx];
766         pkcs7->contentSz = contentSz = length;
767         idx += length;
768     }
769
770     /* Get the implicit[0] set of certificates */
771     if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
772         idx++;
773         if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
774             return ASN_PARSE_E;
775
776         if (length > 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
781              * is X.509. */
782
783             word32 certIdx = idx;
784
785             if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
786                 if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0)
787                     return ASN_PARSE_E;
788
789                 cert = &pkiMsg[idx];
790                 certSz += (certIdx - idx);
791             }
792             PKCS7_InitWithCert(pkcs7, cert, certSz);
793         }
794         idx += length;
795     }
796
797     /* Get the implicit[1] set of crls */
798     if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
799         idx++;
800         if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
801             return ASN_PARSE_E;
802
803         /* Skip the set */
804         idx += length;
805     }
806
807     /* Get the set of signerInfos */
808     if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
809         return ASN_PARSE_E;
810
811     if (length > 0) {
812         /* Get the sequence of the first signerInfo */
813         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
814             return ASN_PARSE_E;
815
816         /* Get the version */
817         if (GetMyVersion(pkiMsg, &idx, &version) < 0)
818             return ASN_PARSE_E;
819
820         if (version != 1) {
821             CYASSL_MSG("PKCS#7 signerInfo needs to be of version 1");
822             return ASN_VERSION_E;
823         }
824
825         /* Get the sequence of IssuerAndSerialNumber */
826         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
827             return ASN_PARSE_E;
828
829         /* Skip it */
830         idx += length;
831
832         /* Get the sequence of digestAlgorithm */
833         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
834             return ASN_PARSE_E;
835
836         /* Skip it */
837         idx += length;
838
839         /* Get the IMPLICIT[0] SET OF signedAttributes */
840         if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
841             idx++;
842
843             if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
844                 return ASN_PARSE_E;
845
846             idx += length;
847         }
848
849         /* Get the sequence of digestEncryptionAlgorithm */
850         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
851             return ASN_PARSE_E;
852
853         /* Skip it */
854         idx += length;
855
856         /* Get the signature */
857         if (pkiMsg[idx] == ASN_OCTET_STRING) {
858             idx++;
859
860             if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
861                 return ASN_PARSE_E;
862
863             /* save pointer and length */
864             sig = &pkiMsg[idx];
865             sigSz = length;
866
867             idx += length;
868         }
869
870         pkcs7->content = content;
871         pkcs7->contentSz = contentSz;
872
873         {
874             word32 scratch = 0;
875             int plainSz = 0;
876             int digestSz = MAX_SEQ_SZ + MAX_ALGO_SZ +
877                            MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE;
878
879 #ifdef CYASSL_SMALL_STACK
880             byte* digest;
881             RsaKey* key;
882
883             digest = (byte*)XMALLOC(digestSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
884
885             if (digest == NULL)
886                 return MEMORY_E;
887
888             key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL,
889                                                        DYNAMIC_TYPE_TMP_BUFFER);
890             if (key == NULL) {
891                 XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
892                 return MEMORY_E;
893             }
894 #else
895             byte digest[digestSz];
896             RsaKey stack_key;
897             RsaKey* key = &stack_key;
898 #endif
899
900             XMEMSET(digest, 0, digestSz);
901
902             ret = InitRsaKey(key, NULL);
903             if (ret != 0) {
904 #ifdef CYASSL_SMALL_STACK
905                 XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
906                 XFREE(key,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
907 #endif
908                 return ret;
909             }       
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);
916 #endif
917                 return PUBLIC_KEY_E;
918             }
919
920             plainSz = RsaSSL_Verify(sig, sigSz, digest, digestSz, key);
921             FreeRsaKey(key);
922
923 #ifdef CYASSL_SMALL_STACK
924             XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
925             XFREE(key,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
926 #endif
927
928             if (plainSz < 0)
929                 return plainSz;
930         }
931     }
932
933     return 0;
934 }
935
936
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,
941                                      byte* contentKeyEnc,
942                                      int* keyEncSz, byte* out, word32 outSz)
943 {
944     word32 idx = 0;
945     int ret = 0, totalSz = 0;
946     int verSz, issuerSz, snSz, keyEncAlgSz;
947     int issuerSeqSz, recipSeqSz, issuerSerialSeqSz;
948     int encKeyOctetStrSz;
949
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];
955
956 #ifdef CYASSL_SMALL_STACK
957     byte *serial;
958     byte *keyAlgArray;
959     
960     RsaKey* pubKey;
961     DecodedCert* decoded;
962
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);
967
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);
972         return MEMORY_E;
973     }
974     
975 #else
976     byte serial[MAX_SN_SZ];
977     byte keyAlgArray[MAX_ALGO_SZ];
978     
979     RsaKey stack_pubKey;
980     RsaKey* pubKey = &stack_pubKey;
981     DecodedCert stack_decoded;
982     DecodedCert* decoded = &stack_decoded;
983 #endif
984
985     InitDecodedCert(decoded, (byte*)cert, certSz, 0);
986     ret = ParseCert(decoded, CA_TYPE, NO_VERIFY, 0);
987     if (ret < 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);
993 #endif
994         return ret;
995     }
996
997     /* version */
998     verSz = SetMyVersion(0, ver, 0);
999
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);
1008 #endif
1009         return -1;
1010     }
1011     issuerSz    = decoded->issuerRawLen;
1012     issuerSeqSz = SetSequence(issuerSz, issuerSeq);
1013
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);
1021 #endif
1022         return -1;
1023     }
1024     snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial);
1025
1026     issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz,
1027                                     issuerSerialSeq);
1028
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);
1036 #endif
1037         return ALGO_ID_E;
1038     }
1039
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);
1047 #endif
1048         return BAD_FUNC_ARG;
1049     }
1050
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);
1058         return MEMORY_E;
1059     }
1060 #endif
1061
1062     /* EncryptedKey */
1063     ret = InitRsaKey(pubKey, 0);
1064     if (ret != 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);
1071 #endif
1072         return ret;
1073     }
1074
1075     if (RsaPublicKeyDecode(decoded->publicKey, &idx, pubKey,
1076                            decoded->pubKeySize) < 0) {
1077         CYASSL_MSG("ASN RSA key decode error");
1078         FreeRsaKey(pubKey);
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);
1085 #endif
1086         return PUBLIC_KEY_E;
1087     }
1088
1089     *keyEncSz = RsaPublicEncrypt(contentKeyPlain, blockKeySz, contentKeyEnc,
1090                                  MAX_ENCRYPTED_KEY_SZ, pubKey, rng);
1091     FreeRsaKey(pubKey);
1092
1093 #ifdef CYASSL_SMALL_STACK
1094     XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1095 #endif
1096
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);
1104 #endif
1105         return *keyEncSz;
1106     }
1107
1108     encKeyOctetStrSz = SetOctetString(*keyEncSz, encKeyOctetStr);
1109
1110     /* RecipientInfo */
1111     recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz +
1112                              issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz +
1113                              *keyEncSz, recipSeq);
1114
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);
1123 #endif
1124         return BUFFER_E;
1125     }
1126
1127     XMEMCPY(out + totalSz, recipSeq, recipSeqSz);
1128     totalSz += recipSeqSz;
1129     XMEMCPY(out + totalSz, ver, verSz);
1130     totalSz += 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);
1138     totalSz += 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;
1145
1146     FreeDecodedCert(decoded);
1147
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);
1152 #endif
1153
1154     return totalSz;
1155 }
1156
1157
1158 /* build PKCS#7 envelopedData content type, return enveloped size */
1159 int PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
1160 {
1161     int i, ret = 0, idx = 0;
1162     int totalSz = 0, padSz = 0, desOutSz = 0;
1163
1164     int contentInfoSeqSz, outerContentTypeSz, outerContentSz;
1165     byte contentInfoSeq[MAX_SEQ_SZ];
1166     byte outerContentType[MAX_ALGO_SZ];
1167     byte outerContent[MAX_SEQ_SZ];
1168
1169     int envDataSeqSz, verSz;
1170     byte envDataSeq[MAX_SEQ_SZ];
1171     byte ver[MAX_VERSION_SZ];
1172
1173     RNG rng;
1174     int contentKeyEncSz, blockKeySz;
1175     int dynamicFlag = 0;
1176     byte contentKeyPlain[MAX_CONTENT_KEY_LEN];
1177 #ifdef CYASSL_SMALL_STACK
1178     byte* contentKeyEnc;
1179 #else
1180     byte contentKeyEnc[MAX_ENCRYPTED_KEY_SZ];
1181 #endif
1182     byte* plain;
1183     byte* encryptedContent;
1184
1185     int recipSz, recipSetSz;
1186 #ifdef CYASSL_SMALL_STACK
1187     byte* recip;
1188 #else
1189     byte recip[MAX_RECIP_SZ];
1190 #endif
1191     byte recipSet[MAX_SET_SZ];
1192
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];
1201
1202     if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
1203         pkcs7->encryptOID == 0 || pkcs7->singleCert == NULL)
1204         return BAD_FUNC_ARG;
1205
1206     if (output == NULL || outputSz == 0)
1207         return BAD_FUNC_ARG;
1208
1209     /* PKCS#7 only supports DES, 3DES for now */
1210     switch (pkcs7->encryptOID) {
1211         case DESb:
1212             blockKeySz = DES_KEYLEN;
1213             break;
1214
1215         case DES3b:
1216             blockKeySz = DES3_KEYLEN;
1217             break;
1218
1219         default:
1220             CYASSL_MSG("Unsupported content cipher type");
1221             return ALGO_ID_E;
1222     };
1223
1224     /* outer content type */
1225     outerContentTypeSz = SetContentType(ENVELOPED_DATA, outerContentType);
1226
1227     /* version, defined as 0 in RFC 2315 */
1228     verSz = SetMyVersion(0, ver, 0);
1229
1230     /* generate random content encryption key */
1231     ret = InitRng(&rng);
1232     if (ret != 0)
1233         return ret;
1234
1235     ret = RNG_GenerateBlock(&rng, contentKeyPlain, blockKeySz);
1236     if (ret != 0)
1237         return ret;
1238     
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);
1246         return MEMORY_E;
1247     }
1248     
1249 #endif
1250
1251     /* build RecipientInfo, only handle 1 for now */
1252     recipSz = CreateRecipientInfo(pkcs7->singleCert, pkcs7->singleCertSz, RSAk,
1253                                   blockKeySz, &rng, contentKeyPlain,
1254                                   contentKeyEnc, &contentKeyEncSz, recip,
1255                                   MAX_RECIP_SZ);
1256                                                                       
1257     XMEMSET(contentKeyEnc,   0, MAX_ENCRYPTED_KEY_SZ);
1258     
1259 #ifdef CYASSL_SMALL_STACK
1260     XFREE(contentKeyEnc, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1261 #endif
1262
1263     if (recipSz < 0) {
1264         CYASSL_MSG("Failed to create RecipientInfo");
1265 #ifdef CYASSL_SMALL_STACK
1266         XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1267 #endif
1268         return recipSz;
1269     }
1270     recipSetSz = SetSet(recipSz, recipSet);
1271
1272     /* generate IV for block cipher */
1273     ret = RNG_GenerateBlock(&rng, tmpIv, DES_BLOCK_SIZE);
1274     if (ret != 0) {
1275 #ifdef CYASSL_SMALL_STACK
1276         XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1277 #endif
1278         return ret;
1279     }
1280
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);
1286 #endif
1287         return BAD_FUNC_ARG;
1288     }
1289
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;
1293
1294     if (padSz != 0) {
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);
1299 #endif
1300             return MEMORY_E;
1301         }
1302         XMEMCPY(plain, pkcs7->content, pkcs7->contentSz);
1303         dynamicFlag = 1;
1304
1305         for (i = 0; i < padSz; i++) {
1306             plain[pkcs7->contentSz + i] = padSz;
1307         }
1308
1309     } else {
1310         plain = pkcs7->content;
1311         desOutSz = pkcs7->contentSz;
1312     }
1313
1314     encryptedContent = (byte*)XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1315     if (encryptedContent == NULL) {
1316         if (dynamicFlag)
1317             XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1318 #ifdef CYASSL_SMALL_STACK
1319         XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1320 #endif
1321         return MEMORY_E;
1322     }
1323
1324     /* put together IV OCTET STRING */
1325     ivOctetStringSz = SetOctetString(DES_BLOCK_SIZE, ivOctetString);
1326
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);
1331
1332     if (contentEncAlgoSz == 0) {
1333         XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1334         if (dynamicFlag)
1335             XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1336 #ifdef CYASSL_SMALL_STACK
1337         XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1338 #endif
1339         return BAD_FUNC_ARG;
1340     }
1341
1342     /* encrypt content */
1343     if (pkcs7->encryptOID == DESb) {
1344         Des des;
1345
1346         ret = Des_SetKey(&des, contentKeyPlain, tmpIv, DES_ENCRYPTION);
1347
1348         if (ret == 0)
1349             Des_CbcEncrypt(&des, encryptedContent, plain, desOutSz);
1350
1351         if (ret != 0) {
1352             XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1353             if (dynamicFlag)
1354                 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1355 #ifdef CYASSL_SMALL_STACK
1356             XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1357 #endif
1358             return ret;
1359         }
1360     }
1361     else if (pkcs7->encryptOID == DES3b) {
1362         Des3 des3;
1363
1364         ret = Des3_SetKey(&des3, contentKeyPlain, tmpIv, DES_ENCRYPTION);
1365
1366         if (ret == 0)
1367             ret = Des3_CbcEncrypt(&des3, encryptedContent, plain, desOutSz);
1368
1369         if (ret != 0) {
1370             XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1371             if (dynamicFlag)
1372                 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1373 #ifdef CYASSL_SMALL_STACK
1374             XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1375 #endif
1376             return ret;
1377         }
1378     }
1379
1380     encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0,
1381                                     desOutSz, encContentOctet);
1382
1383     encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
1384                                   ivOctetStringSz + DES_BLOCK_SIZE +
1385                                   encContentOctetSz + desOutSz, encContentSeq);
1386
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;
1391
1392     /* EnvelopedData */
1393     envDataSeqSz = SetSequence(totalSz, envDataSeq);
1394     totalSz += envDataSeqSz;
1395
1396     /* outer content */
1397     outerContentSz = SetExplicit(0, totalSz, outerContent);
1398     totalSz += outerContentTypeSz;
1399     totalSz += outerContentSz;
1400
1401     /* ContentInfo */
1402     contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
1403     totalSz += contentInfoSeqSz;
1404
1405     if (totalSz > (int)outputSz) {
1406         CYASSL_MSG("Pkcs7_encrypt output buffer too small");
1407         XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1408         if (dynamicFlag)
1409             XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1410 #ifdef CYASSL_SMALL_STACK
1411         XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1412 #endif
1413         return BUFFER_E;
1414     }
1415
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);
1425     idx += verSz;
1426     XMEMCPY(output + idx, recipSet, recipSetSz);
1427     idx += recipSetSz;
1428     XMEMCPY(output + idx, recip, recipSz);
1429     idx += 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);
1443     idx += desOutSz;
1444
1445 #ifdef NO_RC4
1446     FreeRng(&rng);
1447 #endif
1448
1449     XMEMSET(contentKeyPlain, 0, MAX_CONTENT_KEY_LEN);
1450
1451     if (dynamicFlag)
1452         XFREE(plain, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1453     XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1454     
1455 #ifdef CYASSL_SMALL_STACK
1456     XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
1457 #endif
1458
1459     return idx;
1460 }
1461
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,
1465                                          word32 outputSz)
1466 {
1467     int recipFound = 0;
1468     int ret, version, length;
1469     word32 savedIdx = 0, idx = 0;
1470     word32 contentType, encOID;
1471     byte   issuerHash[SHA_DIGEST_SIZE];
1472
1473     int encryptedKeySz, keySz;
1474     byte tmpIv[DES_BLOCK_SIZE];
1475     byte* decryptedKey = NULL;
1476
1477 #ifdef CYASSL_SMALL_STACK
1478     mp_int* serialNum;
1479     byte* encryptedKey;
1480     RsaKey* privKey;
1481 #else
1482     mp_int stack_serialNum;
1483     mp_int* serialNum = &stack_serialNum;
1484     byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
1485     
1486     RsaKey stack_privKey;
1487     RsaKey* privKey = &stack_privKey;
1488 #endif
1489     int encryptedContentSz;
1490     byte padLen;
1491     byte* encryptedContent = NULL;
1492
1493     if (pkcs7 == NULL || pkcs7->singleCert == NULL ||
1494         pkcs7->singleCertSz == 0 || pkcs7->privateKey == NULL ||
1495         pkcs7->privateKeySz == 0)
1496         return BAD_FUNC_ARG;
1497
1498     if (pkiMsg == NULL || pkiMsgSz == 0 ||
1499         output == NULL || outputSz == 0)
1500         return BAD_FUNC_ARG;
1501
1502     /* read past ContentInfo, verify type is envelopedData */
1503     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
1504         return ASN_PARSE_E;
1505
1506     if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
1507         return ASN_PARSE_E;
1508
1509     if (contentType != ENVELOPED_DATA) {
1510         CYASSL_MSG("PKCS#7 input not of type EnvelopedData");
1511         return PKCS7_OID_E;
1512     }
1513
1514     if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
1515         return ASN_PARSE_E;
1516
1517     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
1518         return ASN_PARSE_E;
1519
1520     /* remove EnvelopedData and version */
1521     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
1522         return ASN_PARSE_E;
1523
1524     if (GetMyVersion(pkiMsg, &idx, &version) < 0)
1525         return ASN_PARSE_E;
1526
1527     if (version != 0) {
1528         CYASSL_MSG("PKCS#7 envelopedData needs to be of version 0");
1529         return ASN_VERSION_E;
1530     }
1531
1532     /* walk through RecipientInfo set, find correct recipient */
1533     if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
1534         return ASN_PARSE_E;
1535     
1536 #ifdef CYASSL_SMALL_STACK
1537     encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, NULL,
1538                                                        DYNAMIC_TYPE_TMP_BUFFER);
1539     if (encryptedKey == NULL)
1540         return MEMORY_E;
1541 #endif
1542     
1543     savedIdx = idx;
1544     recipFound = 0;
1545
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) {
1549
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) {
1553             idx = savedIdx;
1554             break;
1555         }
1556
1557         if (GetMyVersion(pkiMsg, &idx, &version) < 0) {
1558             idx = savedIdx;
1559             break;
1560         }
1561
1562         if (version != 0) {
1563 #ifdef CYASSL_SMALL_STACK
1564             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1565 #endif
1566             return ASN_VERSION_E;
1567         }
1568         
1569         /* remove IssuerAndSerialNumber */
1570         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
1571 #ifdef CYASSL_SMALL_STACK
1572             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1573 #endif
1574             return ASN_PARSE_E;
1575         }
1576         
1577         if (GetNameHash(pkiMsg, &idx, issuerHash, pkiMsgSz) < 0) {
1578 #ifdef CYASSL_SMALL_STACK
1579             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1580 #endif
1581             return ASN_PARSE_E;
1582         }
1583         
1584         /* if we found correct recipient, issuer hashes will match */
1585         if (XMEMCMP(issuerHash, pkcs7->issuerHash, SHA_DIGEST_SIZE) == 0) {
1586             recipFound = 1;
1587         }
1588         
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);
1594             return MEMORY_E;
1595         }
1596 #endif
1597         
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);
1602 #endif
1603             return ASN_PARSE_E;
1604         }
1605         
1606         mp_clear(serialNum);
1607         
1608 #ifdef CYASSL_SMALL_STACK
1609         XFREE(serialNum, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1610 #endif
1611         
1612         if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0) {
1613 #ifdef CYASSL_SMALL_STACK
1614             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1615 #endif
1616             return ASN_PARSE_E;
1617         }
1618         
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);
1623 #endif
1624             return ALGO_ID_E;
1625         }
1626         
1627         /* read encryptedKey */
1628         if (pkiMsg[idx++] != ASN_OCTET_STRING) {
1629 #ifdef CYASSL_SMALL_STACK
1630             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1631 #endif
1632             return ASN_PARSE_E;
1633         }
1634         
1635         if (GetLength(pkiMsg, &idx, &encryptedKeySz, pkiMsgSz) < 0) {
1636 #ifdef CYASSL_SMALL_STACK
1637             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1638 #endif
1639             return ASN_PARSE_E;
1640         }
1641           
1642         if (recipFound == 1)
1643             XMEMCPY(encryptedKey, &pkiMsg[idx], encryptedKeySz);
1644         idx += encryptedKeySz;
1645
1646         /* update good idx */
1647         savedIdx = idx;
1648     }
1649
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);
1654 #endif
1655         return PKCS7_RECIP_E;
1656     }
1657
1658     /* remove EncryptedContentInfo */
1659     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
1660 #ifdef CYASSL_SMALL_STACK
1661         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1662 #endif
1663         return ASN_PARSE_E;
1664     }
1665     
1666     if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) {
1667 #ifdef CYASSL_SMALL_STACK
1668         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1669 #endif
1670         return ASN_PARSE_E;
1671     }
1672
1673     if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0) {
1674 #ifdef CYASSL_SMALL_STACK
1675         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1676 #endif
1677         return ASN_PARSE_E;
1678     }
1679     
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);
1684 #endif
1685         return ASN_PARSE_E;
1686     }
1687     
1688     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
1689 #ifdef CYASSL_SMALL_STACK
1690         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1691 #endif
1692         return ASN_PARSE_E;
1693     }
1694     
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);
1699 #endif
1700         return ASN_PARSE_E;
1701     }
1702
1703     XMEMCPY(tmpIv, &pkiMsg[idx], length);
1704     idx += length;
1705
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);
1710 #endif
1711         return ASN_PARSE_E;
1712     }
1713
1714     if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0) {
1715 #ifdef CYASSL_SMALL_STACK
1716         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1717 #endif
1718         return ASN_PARSE_E;
1719     }
1720     
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);
1726 #endif
1727         return MEMORY_E;
1728     }
1729
1730     XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
1731
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;
1738     }
1739 #endif
1740
1741     ret = InitRsaKey(privKey, 0);
1742     if (ret != 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);
1747 #endif
1748         return ret;
1749     }
1750
1751     idx = 0;
1752
1753     ret = RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey,
1754                               pkcs7->privateKeySz);
1755     if (ret != 0) {
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);
1761 #endif
1762         return ret;
1763     }
1764
1765     /* decrypt encryptedKey */
1766     keySz = RsaPrivateDecryptInline(encryptedKey, encryptedKeySz,
1767                                     &decryptedKey, privKey);
1768     FreeRsaKey(privKey);
1769
1770 #ifdef CYASSL_SMALL_STACK
1771     XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1772 #endif
1773
1774     if (keySz <= 0) {
1775         XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1776 #ifdef CYASSL_SMALL_STACK
1777         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1778 #endif
1779         return keySz;
1780     }
1781
1782     /* decrypt encryptedContent */
1783     if (encOID == DESb) {
1784         Des des;
1785         ret = Des_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION);
1786
1787         if (ret == 0)
1788             Des_CbcDecrypt(&des, encryptedContent, encryptedContent,
1789                                  encryptedContentSz);
1790
1791         if (ret != 0) {
1792             XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1793 #ifdef CYASSL_SMALL_STACK
1794             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1795 #endif
1796             return ret;
1797         }
1798     }
1799     else if (encOID == DES3b) {
1800         Des3 des;
1801         ret = Des3_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION);
1802         if (ret == 0)
1803             ret = Des3_CbcDecrypt(&des, encryptedContent, encryptedContent,
1804                                   encryptedContentSz);
1805
1806         if (ret != 0) {
1807             XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1808 #ifdef CYASSL_SMALL_STACK
1809             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1810 #endif
1811             return ret;
1812         }
1813     } else {
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);
1818 #endif
1819         return ALGO_ID_E;
1820     }
1821
1822     padLen = encryptedContent[encryptedContentSz-1];
1823
1824     /* copy plaintext to output */
1825     XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
1826
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);
1833 #endif
1834     
1835     return encryptedContentSz - padLen;
1836 }
1837
1838
1839 #else  /* HAVE_PKCS7 */
1840
1841
1842 #ifdef _MSC_VER
1843     /* 4206 warning for blank file */
1844     #pragma warning(disable: 4206)
1845 #endif
1846
1847
1848 #endif /* HAVE_PKCS7 */
1849