Renesas / SecureDweet
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pkcs7.c Source File

pkcs7.c

00001 /* pkcs7.c
00002  *
00003  * Copyright (C) 2006-2016 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 #include <wolfssl/wolfcrypt/settings.h>
00028 
00029 #ifdef HAVE_PKCS7
00030 
00031 #include <wolfssl/wolfcrypt/pkcs7.h>
00032 #include <wolfssl/wolfcrypt/error-crypt.h>
00033 #include <wolfssl/wolfcrypt/logging.h>
00034 #ifdef NO_INLINE
00035     #include <wolfssl/wolfcrypt/misc.h>
00036 #else
00037     #include <wolfcrypt/src/misc.c>
00038 #endif
00039 
00040 #ifndef WOLFSSL_HAVE_MIN
00041 #define WOLFSSL_HAVE_MIN
00042 
00043     static INLINE word32 min(word32 a, word32 b)
00044     {
00045         return a > b ? b : a;
00046     }
00047 
00048 #endif /* WOLFSSL_HAVE_MIN */
00049 
00050 
00051 /* placed ASN.1 contentType OID into *output, return idx on success,
00052  * 0 upon failure */
00053 WOLFSSL_LOCAL int wc_SetContentType(int pkcs7TypeOID, byte* output)
00054 {
00055     /* PKCS#7 content types, RFC 2315, section 14 */
00056     const byte pkcs7[]              = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
00057                                                0x0D, 0x01, 0x07 };
00058     const byte data[]               = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
00059                                                0x0D, 0x01, 0x07, 0x01 };
00060     const byte signedData[]         = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
00061                                                0x0D, 0x01, 0x07, 0x02};
00062     const byte envelopedData[]      = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
00063                                                0x0D, 0x01, 0x07, 0x03 };
00064     const byte signedAndEnveloped[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
00065                                                0x0D, 0x01, 0x07, 0x04 };
00066     const byte digestedData[]       = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
00067                                                0x0D, 0x01, 0x07, 0x05 };
00068     const byte encryptedData[]      = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
00069                                                0x0D, 0x01, 0x07, 0x06 };
00070 
00071     int idSz;
00072     int typeSz = 0, idx = 0;
00073     const byte* typeName = 0;
00074     byte ID_Length[MAX_LENGTH_SZ];
00075 
00076     switch (pkcs7TypeOID) {
00077         case PKCS7_MSG:
00078             typeSz = sizeof(pkcs7);
00079             typeName = pkcs7;
00080             break;
00081 
00082         case DATA:
00083             typeSz = sizeof(data);
00084             typeName = data;
00085             break;
00086 
00087         case SIGNED_DATA:
00088             typeSz = sizeof(signedData);
00089             typeName = signedData;
00090             break;
00091         
00092         case ENVELOPED_DATA:
00093             typeSz = sizeof(envelopedData);
00094             typeName = envelopedData;
00095             break;
00096 
00097         case SIGNED_AND_ENVELOPED_DATA:
00098             typeSz = sizeof(signedAndEnveloped);
00099             typeName = signedAndEnveloped;
00100             break;
00101 
00102         case DIGESTED_DATA:
00103             typeSz = sizeof(digestedData);
00104             typeName = digestedData;
00105             break;
00106 
00107         case ENCRYPTED_DATA:
00108             typeSz = sizeof(encryptedData);
00109             typeName = encryptedData;
00110             break;
00111 
00112         default:
00113             WOLFSSL_MSG("Unknown PKCS#7 Type");
00114             return 0;
00115     };
00116 
00117     idSz  = SetLength(typeSz, ID_Length);
00118     output[idx++] = ASN_OBJECT_ID;
00119     XMEMCPY(output + idx, ID_Length, idSz);
00120     idx += idSz;
00121     XMEMCPY(output + idx, typeName, typeSz);
00122     idx += typeSz;
00123 
00124     return idx;
00125 
00126 }
00127 
00128 
00129 /* get ASN.1 contentType OID sum, return 0 on success, <0 on failure */
00130 int wc_GetContentType(const byte* input, word32* inOutIdx, word32* oid,
00131                    word32 maxIdx)
00132 {
00133     WOLFSSL_ENTER("wc_GetContentType");
00134     if (GetObjectId(input, inOutIdx, oid, ignoreType, maxIdx) < 0)
00135         return ASN_PARSE_E;
00136 
00137     return 0;
00138 }
00139 
00140 
00141 /* init PKCS7 struct with recipient cert, decode into DecodedCert */
00142 int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz)
00143 {
00144     int ret = 0;
00145 
00146     XMEMSET(pkcs7, 0, sizeof(PKCS7));
00147     if (cert != NULL && certSz > 0) {
00148 #ifdef WOLFSSL_SMALL_STACK
00149         DecodedCert* dCert;
00150 
00151         dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
00152                                                        DYNAMIC_TYPE_TMP_BUFFER);
00153         if (dCert == NULL)
00154             return MEMORY_E;
00155 #else
00156         DecodedCert stack_dCert;
00157         DecodedCert* dCert = &stack_dCert;
00158 #endif
00159 
00160         pkcs7->singleCert = cert;
00161         pkcs7->singleCertSz = certSz;
00162         InitDecodedCert(dCert, cert, certSz, 0);
00163 
00164         ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0);
00165         if (ret < 0) {
00166             FreeDecodedCert(dCert);
00167 #ifdef WOLFSSL_SMALL_STACK
00168             XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00169 #endif
00170             return ret;
00171         }
00172 
00173         XMEMCPY(pkcs7->publicKey, dCert->publicKey, dCert->pubKeySize);
00174         pkcs7->publicKeySz = dCert->pubKeySize;
00175         XMEMCPY(pkcs7->issuerHash, dCert->issuerHash, KEYID_SIZE);
00176         pkcs7->issuer = dCert->issuerRaw;
00177         pkcs7->issuerSz = dCert->issuerRawLen;
00178         XMEMCPY(pkcs7->issuerSn, dCert->serial, dCert->serialSz);
00179         pkcs7->issuerSnSz = dCert->serialSz;
00180         FreeDecodedCert(dCert);
00181 
00182 #ifdef WOLFSSL_SMALL_STACK
00183         XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00184 #endif
00185     }
00186 
00187     return ret;
00188 }
00189 
00190 
00191 /* releases any memory allocated by a PKCS7 initializer */
00192 void wc_PKCS7_Free(PKCS7* pkcs7)
00193 {
00194     (void)pkcs7;
00195 }
00196 
00197 
00198 /* build PKCS#7 data content type */
00199 int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz)
00200 {
00201     static const byte oid[] =
00202         { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
00203                          0x07, 0x01 };
00204     byte seq[MAX_SEQ_SZ];
00205     byte octetStr[MAX_OCTET_STR_SZ];
00206     word32 seqSz;
00207     word32 octetStrSz;
00208     word32 oidSz = (word32)sizeof(oid);
00209     int idx = 0;
00210 
00211     octetStrSz = SetOctetString(pkcs7->contentSz, octetStr);
00212     seqSz = SetSequence(pkcs7->contentSz + octetStrSz + oidSz, seq);
00213 
00214     if (outputSz < pkcs7->contentSz + octetStrSz + oidSz + seqSz)
00215         return BUFFER_E;
00216 
00217     XMEMCPY(output, seq, seqSz);
00218     idx += seqSz;
00219     XMEMCPY(output + idx, oid, oidSz);
00220     idx += oidSz;
00221     XMEMCPY(output + idx, octetStr, octetStrSz);
00222     idx += octetStrSz;
00223     XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
00224     idx += pkcs7->contentSz;
00225 
00226     return idx;
00227 }
00228 
00229 
00230 typedef struct EncodedAttrib {
00231     byte valueSeq[MAX_SEQ_SZ];
00232         const byte* oid;
00233         byte valueSet[MAX_SET_SZ];
00234         const byte* value;
00235     word32 valueSeqSz, oidSz, idSz, valueSetSz, valueSz, totalSz;
00236 } EncodedAttrib;
00237 
00238 
00239 typedef struct ESD {
00240     Sha sha;
00241     byte contentDigest[SHA_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */
00242     byte contentAttribsDigest[SHA_DIGEST_SIZE];
00243     byte encContentDigest[512];
00244 
00245     byte outerSeq[MAX_SEQ_SZ];
00246         byte outerContent[MAX_EXP_SZ];
00247             byte innerSeq[MAX_SEQ_SZ];
00248                 byte version[MAX_VERSION_SZ];
00249                 byte digAlgoIdSet[MAX_SET_SZ];
00250                     byte singleDigAlgoId[MAX_ALGO_SZ];
00251 
00252                 byte contentInfoSeq[MAX_SEQ_SZ];
00253                     byte innerContSeq[MAX_EXP_SZ];
00254                         byte innerOctets[MAX_OCTET_STR_SZ];
00255 
00256                 byte certsSet[MAX_SET_SZ];
00257 
00258                 byte signerInfoSet[MAX_SET_SZ];
00259                     byte signerInfoSeq[MAX_SEQ_SZ];
00260                         byte signerVersion[MAX_VERSION_SZ];
00261                         byte issuerSnSeq[MAX_SEQ_SZ];
00262                             byte issuerName[MAX_SEQ_SZ];
00263                             byte issuerSn[MAX_SN_SZ];
00264                         byte signerDigAlgoId[MAX_ALGO_SZ];
00265                         byte digEncAlgoId[MAX_ALGO_SZ];
00266                         byte signedAttribSet[MAX_SET_SZ];
00267                             EncodedAttrib signedAttribs[6];
00268                         byte signerDigest[MAX_OCTET_STR_SZ];
00269     word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz;
00270     word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz,
00271            singleDigAlgoIdSz, certsSetSz;
00272     word32 signerInfoSetSz, signerInfoSeqSz, signerVersionSz,
00273            issuerSnSeqSz, issuerNameSz, issuerSnSz,
00274            signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz;
00275     word32 encContentDigestSz, signedAttribsSz, signedAttribsCount,
00276            signedAttribSetSz;
00277 } ESD;
00278 
00279 
00280 static int EncodeAttributes(EncodedAttrib* ea, int eaSz,
00281                                             PKCS7Attrib* attribs, int attribsSz)
00282 {
00283     int i;
00284     int maxSz = min(eaSz, attribsSz);
00285     int allAttribsSz = 0;
00286 
00287     for (i = 0; i < maxSz; i++)
00288     {
00289         int attribSz = 0;
00290 
00291         ea[i].value = attribs[i].value;
00292         ea[i].valueSz = attribs[i].valueSz;
00293         attribSz += ea[i].valueSz;
00294         ea[i].valueSetSz = SetSet(attribSz, ea[i].valueSet);
00295         attribSz += ea[i].valueSetSz;
00296         ea[i].oid = attribs[i].oid;
00297         ea[i].oidSz = attribs[i].oidSz;
00298         attribSz += ea[i].oidSz;
00299         ea[i].valueSeqSz = SetSequence(attribSz, ea[i].valueSeq);
00300         attribSz += ea[i].valueSeqSz;
00301         ea[i].totalSz = attribSz;
00302 
00303         allAttribsSz += attribSz;
00304     }
00305     return allAttribsSz;
00306 }
00307 
00308 
00309 static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz)
00310 {
00311     int i, idx;
00312 
00313     idx = 0;
00314     for (i = 0; i < eaSz; i++) {
00315         XMEMCPY(output + idx, ea[i].valueSeq, ea[i].valueSeqSz);
00316         idx += ea[i].valueSeqSz;
00317         XMEMCPY(output + idx, ea[i].oid, ea[i].oidSz);
00318         idx += ea[i].oidSz;
00319         XMEMCPY(output + idx, ea[i].valueSet, ea[i].valueSetSz);
00320         idx += ea[i].valueSetSz;
00321         XMEMCPY(output + idx, ea[i].value, ea[i].valueSz);
00322         idx += ea[i].valueSz;
00323     }
00324     return 0;
00325 }
00326 
00327 
00328 /* build PKCS#7 signedData content type */
00329 int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz)
00330 {
00331     static const byte outerOid[] =
00332         { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
00333                          0x07, 0x02 };
00334     static const byte innerOid[] =
00335         { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
00336                          0x07, 0x01 };
00337 
00338 #ifdef WOLFSSL_SMALL_STACK
00339     ESD* esd = NULL;
00340 #else
00341     ESD stack_esd;
00342     ESD* esd = &stack_esd;
00343 #endif
00344 
00345     word32 signerInfoSz = 0;
00346     word32 totalSz = 0;
00347     int idx = 0, ret = 0;
00348     byte* flatSignedAttribs = NULL;
00349     word32 flatSignedAttribsSz = 0;
00350     word32 innerOidSz = sizeof(innerOid);
00351     word32 outerOidSz = sizeof(outerOid);
00352 
00353     if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
00354         pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 ||
00355         pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0 ||
00356         pkcs7->privateKey == NULL || pkcs7->privateKeySz == 0 ||
00357         output == NULL || outputSz == 0)
00358         return BAD_FUNC_ARG;
00359 
00360 #ifdef WOLFSSL_SMALL_STACK
00361     esd = (ESD*)XMALLOC(sizeof(ESD), NULL, DYNAMIC_TYPE_TMP_BUFFER);
00362     if (esd == NULL)
00363         return MEMORY_E;
00364 #endif
00365 
00366     XMEMSET(esd, 0, sizeof(ESD));
00367     ret = wc_InitSha(&esd->sha);
00368     if (ret != 0) {
00369 #ifdef WOLFSSL_SMALL_STACK
00370         XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00371 #endif
00372         return ret;
00373     }
00374 
00375     if (pkcs7->contentSz != 0)
00376     {
00377         wc_ShaUpdate(&esd->sha, pkcs7->content, pkcs7->contentSz);
00378         esd->contentDigest[0] = ASN_OCTET_STRING;
00379         esd->contentDigest[1] = SHA_DIGEST_SIZE;
00380         wc_ShaFinal(&esd->sha, &esd->contentDigest[2]);
00381     }
00382 
00383     esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets);
00384     esd->innerContSeqSz = SetExplicit(0, esd->innerOctetsSz + pkcs7->contentSz,
00385                                 esd->innerContSeq);
00386     esd->contentInfoSeqSz = SetSequence(pkcs7->contentSz + esd->innerOctetsSz +
00387                                     innerOidSz + esd->innerContSeqSz,
00388                                     esd->contentInfoSeq);
00389 
00390     esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz,
00391                                      esd->issuerSn);
00392     signerInfoSz += esd->issuerSnSz;
00393     esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName);
00394     signerInfoSz += esd->issuerNameSz + pkcs7->issuerSz;
00395     esd->issuerSnSeqSz = SetSequence(signerInfoSz, esd->issuerSnSeq);
00396     signerInfoSz += esd->issuerSnSeqSz;
00397     esd->signerVersionSz = SetMyVersion(1, esd->signerVersion, 0);
00398     signerInfoSz += esd->signerVersionSz;
00399     esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId,
00400                                       hashType, 0);
00401     signerInfoSz += esd->signerDigAlgoIdSz;
00402     esd->digEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, esd->digEncAlgoId,
00403                                    keyType, 0);
00404     signerInfoSz += esd->digEncAlgoIdSz;
00405 
00406     if (pkcs7->signedAttribsSz != 0) {
00407         byte contentTypeOid[] =
00408                 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01,
00409                                  0x09, 0x03 };
00410         byte contentType[] =
00411                 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
00412                                  0x07, 0x01 };
00413         byte messageDigestOid[] =
00414                 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
00415                                  0x09, 0x04 };
00416 
00417         PKCS7Attrib cannedAttribs[2] ;
00418 
00419         word32 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib);
00420                 cannedAttribs[0].oid =  contentTypeOid ;
00421                 cannedAttribs[0].oidSz =  sizeof(contentTypeOid) ;
00422                 cannedAttribs[0].value = contentType ;
00423                 cannedAttribs[0].valueSz = sizeof(contentType) ;
00424                 cannedAttribs[1].oid = messageDigestOid ;
00425                 cannedAttribs[1].oidSz = sizeof(messageDigestOid) ;
00426         cannedAttribs[1].value = esd->contentDigest ;
00427         cannedAttribs[1].valueSz = sizeof(esd->contentDigest) ;
00428 
00429         esd->signedAttribsCount += cannedAttribsCount;
00430         esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2,
00431                                              cannedAttribs, cannedAttribsCount);
00432 
00433         esd->signedAttribsCount += pkcs7->signedAttribsSz;
00434         esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4,
00435                                   pkcs7->signedAttribs, pkcs7->signedAttribsSz);
00436 
00437         flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, 0, NULL);
00438         flatSignedAttribsSz = esd->signedAttribsSz;
00439         if (flatSignedAttribs == NULL) {
00440 #ifdef WOLFSSL_SMALL_STACK
00441             XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00442 #endif   
00443             return MEMORY_E;
00444         }
00445         FlattenAttributes(flatSignedAttribs,
00446                                    esd->signedAttribs, esd->signedAttribsCount);
00447         esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz,
00448                                                           esd->signedAttribSet);
00449     }
00450     /* Calculate the final hash and encrypt it. */
00451     {
00452         int result;
00453         word32 scratch = 0;
00454 
00455 #ifdef WOLFSSL_SMALL_STACK
00456         byte* digestInfo;
00457         RsaKey* privKey;
00458 #else
00459         RsaKey stack_privKey;
00460         RsaKey* privKey = &stack_privKey;
00461         byte digestInfo[MAX_SEQ_SZ + MAX_ALGO_SZ +
00462                         MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE];
00463 #endif
00464         byte digestInfoSeq[MAX_SEQ_SZ];
00465         byte digestStr[MAX_OCTET_STR_SZ];
00466         word32 digestInfoSeqSz, digestStrSz;
00467         int digIdx = 0;
00468 
00469         if (pkcs7->signedAttribsSz != 0) {
00470             byte attribSet[MAX_SET_SZ];
00471             word32 attribSetSz;
00472 
00473             attribSetSz = SetSet(flatSignedAttribsSz, attribSet);
00474 
00475             ret = wc_InitSha(&esd->sha);
00476             if (ret < 0) {
00477                 XFREE(flatSignedAttribs, 0, NULL);
00478 #ifdef WOLFSSL_SMALL_STACK
00479                 XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00480 #endif
00481                 return ret;
00482             }
00483             wc_ShaUpdate(&esd->sha, attribSet, attribSetSz);
00484             wc_ShaUpdate(&esd->sha, flatSignedAttribs, flatSignedAttribsSz);
00485         }
00486         wc_ShaFinal(&esd->sha, esd->contentAttribsDigest);
00487 
00488         digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr);
00489         digestInfoSeqSz = SetSequence(esd->signerDigAlgoIdSz +
00490                                       digestStrSz + SHA_DIGEST_SIZE,
00491                                       digestInfoSeq);
00492 
00493 #ifdef WOLFSSL_SMALL_STACK
00494         digestInfo = (byte*)XMALLOC(MAX_SEQ_SZ + MAX_ALGO_SZ +
00495                                     MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE,
00496                                     NULL, DYNAMIC_TYPE_TMP_BUFFER);
00497         if (digestInfo == NULL) {
00498             if (pkcs7->signedAttribsSz != 0)
00499                 XFREE(flatSignedAttribs, 0, NULL);
00500             XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00501             return MEMORY_E;
00502         }
00503 #endif
00504 
00505         XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
00506         digIdx += digestInfoSeqSz;
00507         XMEMCPY(digestInfo + digIdx,
00508                                   esd->signerDigAlgoId, esd->signerDigAlgoIdSz);
00509         digIdx += esd->signerDigAlgoIdSz;
00510         XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
00511         digIdx += digestStrSz;
00512         XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest,
00513                                                                SHA_DIGEST_SIZE);
00514         digIdx += SHA_DIGEST_SIZE;
00515 
00516 #ifdef WOLFSSL_SMALL_STACK
00517         privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL,
00518                                                        DYNAMIC_TYPE_TMP_BUFFER);
00519         if (privKey == NULL) {
00520             if (pkcs7->signedAttribsSz != 0)
00521                 XFREE(flatSignedAttribs, 0, NULL);
00522             XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00523             XFREE(esd,        NULL, DYNAMIC_TYPE_TMP_BUFFER);
00524             return MEMORY_E;
00525         }
00526 #endif
00527 
00528         result = wc_InitRsaKey(privKey, NULL);
00529         if (result == 0)
00530             result = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, privKey,
00531                                          pkcs7->privateKeySz);
00532         if (result < 0) {
00533             if (pkcs7->signedAttribsSz != 0)
00534                 XFREE(flatSignedAttribs, 0, NULL);
00535 #ifdef WOLFSSL_SMALL_STACK
00536             XFREE(privKey,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
00537             XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00538             XFREE(esd,        NULL, DYNAMIC_TYPE_TMP_BUFFER);
00539 #endif
00540             return PUBLIC_KEY_E;
00541         }
00542 
00543         result = wc_RsaSSL_Sign(digestInfo, digIdx,
00544                              esd->encContentDigest,
00545                              sizeof(esd->encContentDigest),
00546                              privKey, pkcs7->rng);
00547 
00548         wc_FreeRsaKey(privKey);
00549 
00550 #ifdef WOLFSSL_SMALL_STACK
00551         XFREE(privKey,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
00552         XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00553 #endif
00554 
00555         if (result < 0) {
00556             if (pkcs7->signedAttribsSz != 0)
00557                 XFREE(flatSignedAttribs, 0, NULL);
00558 #ifdef WOLFSSL_SMALL_STACK
00559             XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00560 #endif
00561             return result;
00562         }
00563         esd->encContentDigestSz = (word32)result;
00564     }
00565     signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz;
00566 
00567     esd->signerDigestSz = SetOctetString(esd->encContentDigestSz,
00568                                                              esd->signerDigest);
00569     signerInfoSz += esd->signerDigestSz + esd->encContentDigestSz;
00570 
00571     esd->signerInfoSeqSz = SetSequence(signerInfoSz, esd->signerInfoSeq);
00572     signerInfoSz += esd->signerInfoSeqSz;
00573     esd->signerInfoSetSz = SetSet(signerInfoSz, esd->signerInfoSet);
00574     signerInfoSz += esd->signerInfoSetSz;
00575 
00576     esd->certsSetSz = SetImplicit(ASN_SET, 0, pkcs7->singleCertSz,
00577                                                                  esd->certsSet);
00578 
00579     esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId,
00580                                       hashType, 0);
00581     esd->digAlgoIdSetSz = SetSet(esd->singleDigAlgoIdSz, esd->digAlgoIdSet);
00582 
00583 
00584     esd->versionSz = SetMyVersion(1, esd->version, 0);
00585 
00586     totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz +
00587               esd->contentInfoSeqSz + esd->certsSetSz + pkcs7->singleCertSz +
00588               esd->innerOctetsSz + esd->innerContSeqSz +
00589               innerOidSz + pkcs7->contentSz +
00590               signerInfoSz;
00591     esd->innerSeqSz = SetSequence(totalSz, esd->innerSeq);
00592     totalSz += esd->innerSeqSz;
00593     esd->outerContentSz = SetExplicit(0, totalSz, esd->outerContent);
00594     totalSz += esd->outerContentSz + outerOidSz;
00595     esd->outerSeqSz = SetSequence(totalSz, esd->outerSeq);
00596     totalSz += esd->outerSeqSz;
00597 
00598     if (outputSz < totalSz) {
00599         if (pkcs7->signedAttribsSz != 0)
00600             XFREE(flatSignedAttribs, 0, NULL);
00601 #ifdef WOLFSSL_SMALL_STACK
00602         XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00603 #endif
00604         return BUFFER_E;
00605     }
00606 
00607     idx = 0;
00608     XMEMCPY(output + idx, esd->outerSeq, esd->outerSeqSz);
00609     idx += esd->outerSeqSz;
00610     XMEMCPY(output + idx, outerOid, outerOidSz);
00611     idx += outerOidSz;
00612     XMEMCPY(output + idx, esd->outerContent, esd->outerContentSz);
00613     idx += esd->outerContentSz;
00614     XMEMCPY(output + idx, esd->innerSeq, esd->innerSeqSz);
00615     idx += esd->innerSeqSz;
00616     XMEMCPY(output + idx, esd->version, esd->versionSz);
00617     idx += esd->versionSz;
00618     XMEMCPY(output + idx, esd->digAlgoIdSet, esd->digAlgoIdSetSz);
00619     idx += esd->digAlgoIdSetSz;
00620     XMEMCPY(output + idx, esd->singleDigAlgoId, esd->singleDigAlgoIdSz);
00621     idx += esd->singleDigAlgoIdSz;
00622     XMEMCPY(output + idx, esd->contentInfoSeq, esd->contentInfoSeqSz);
00623     idx += esd->contentInfoSeqSz;
00624     XMEMCPY(output + idx, innerOid, innerOidSz);
00625     idx += innerOidSz;
00626     XMEMCPY(output + idx, esd->innerContSeq, esd->innerContSeqSz);
00627     idx += esd->innerContSeqSz;
00628     XMEMCPY(output + idx, esd->innerOctets, esd->innerOctetsSz);
00629     idx += esd->innerOctetsSz;
00630     XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
00631     idx += pkcs7->contentSz;
00632     XMEMCPY(output + idx, esd->certsSet, esd->certsSetSz);
00633     idx += esd->certsSetSz;
00634     XMEMCPY(output + idx, pkcs7->singleCert, pkcs7->singleCertSz);
00635     idx += pkcs7->singleCertSz;
00636     XMEMCPY(output + idx, esd->signerInfoSet, esd->signerInfoSetSz);
00637     idx += esd->signerInfoSetSz;
00638     XMEMCPY(output + idx, esd->signerInfoSeq, esd->signerInfoSeqSz);
00639     idx += esd->signerInfoSeqSz;
00640     XMEMCPY(output + idx, esd->signerVersion, esd->signerVersionSz);
00641     idx += esd->signerVersionSz;
00642     XMEMCPY(output + idx, esd->issuerSnSeq, esd->issuerSnSeqSz);
00643     idx += esd->issuerSnSeqSz;
00644     XMEMCPY(output + idx, esd->issuerName, esd->issuerNameSz);
00645     idx += esd->issuerNameSz;
00646     XMEMCPY(output + idx, pkcs7->issuer, pkcs7->issuerSz);
00647     idx += pkcs7->issuerSz;
00648     XMEMCPY(output + idx, esd->issuerSn, esd->issuerSnSz);
00649     idx += esd->issuerSnSz;
00650     XMEMCPY(output + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz);
00651     idx += esd->signerDigAlgoIdSz;
00652 
00653     /* SignerInfo:Attributes */
00654     if (pkcs7->signedAttribsSz != 0) {
00655         XMEMCPY(output + idx, esd->signedAttribSet, esd->signedAttribSetSz);
00656         idx += esd->signedAttribSetSz;
00657         XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz);
00658         idx += flatSignedAttribsSz;
00659         XFREE(flatSignedAttribs, 0, NULL);
00660     }
00661 
00662     XMEMCPY(output + idx, esd->digEncAlgoId, esd->digEncAlgoIdSz);
00663     idx += esd->digEncAlgoIdSz;
00664     XMEMCPY(output + idx, esd->signerDigest, esd->signerDigestSz);
00665     idx += esd->signerDigestSz;
00666     XMEMCPY(output + idx, esd->encContentDigest, esd->encContentDigestSz);
00667     idx += esd->encContentDigestSz;
00668 
00669 #ifdef WOLFSSL_SMALL_STACK
00670     XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00671 #endif
00672 
00673     return idx;
00674 }
00675 
00676 
00677 /* Finds the certificates in the message and saves it. */
00678 int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
00679 {
00680     word32 idx, contentType;
00681     int length, version, ret;
00682     byte* content = NULL;
00683     byte* sig = NULL;
00684     byte* cert = NULL;
00685     int contentSz = 0, sigSz = 0, certSz = 0;
00686 
00687     if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0)
00688         return BAD_FUNC_ARG;
00689 
00690     idx = 0;
00691 
00692     /* Get the contentInfo sequence */
00693     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00694         return ASN_PARSE_E;
00695 
00696     /* Get the contentInfo contentType */
00697     if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
00698         return ASN_PARSE_E;
00699 
00700     if (contentType != SIGNED_DATA) {
00701         WOLFSSL_MSG("PKCS#7 input not of type SignedData");
00702         return PKCS7_OID_E;
00703     }
00704 
00705     /* get the ContentInfo content */
00706     if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
00707         return ASN_PARSE_E;
00708 
00709     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00710         return ASN_PARSE_E;
00711 
00712     /* Get the signedData sequence */
00713     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00714         return ASN_PARSE_E;
00715 
00716     /* Get the version */
00717     if (GetMyVersion(pkiMsg, &idx, &version) < 0)
00718         return ASN_PARSE_E;
00719 
00720     if (version != 1) {
00721         WOLFSSL_MSG("PKCS#7 signedData needs to be of version 1");
00722         return ASN_VERSION_E;
00723     }
00724 
00725     /* Get the set of DigestAlgorithmIdentifiers */
00726     if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00727         return ASN_PARSE_E;
00728 
00729     /* Skip the set. */
00730     idx += length;
00731 
00732     /* Get the inner ContentInfo sequence */
00733     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00734         return ASN_PARSE_E;
00735 
00736     /* Get the inner ContentInfo contentType */
00737     if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
00738         return ASN_PARSE_E;
00739 
00740     if (contentType != DATA) {
00741         WOLFSSL_MSG("PKCS#7 inner input not of type Data");
00742         return PKCS7_OID_E;
00743     }
00744 
00745     if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
00746         return ASN_PARSE_E;
00747 
00748     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00749         return ASN_PARSE_E;
00750 
00751     if (pkiMsg[idx++] != ASN_OCTET_STRING)
00752         return ASN_PARSE_E;
00753 
00754     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00755         return ASN_PARSE_E;
00756 
00757     /* Save the inner data as the content. */
00758     if (length > 0) {
00759         /* Local pointer for calculating hashes later */
00760         pkcs7->content = content = &pkiMsg[idx];
00761         pkcs7->contentSz = contentSz = length;
00762         idx += length;
00763     }
00764 
00765     /* Get the implicit[0] set of certificates */
00766     if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
00767         idx++;
00768         if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00769             return ASN_PARSE_E;
00770 
00771         if (length > 0) {
00772             /* At this point, idx is at the first certificate in
00773              * a set of certificates. There may be more than one,
00774              * or none, or they may be a PKCS 6 extended
00775              * certificate. We want to save the first cert if it
00776              * is X.509. */
00777 
00778             word32 certIdx = idx;
00779 
00780             if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
00781                 if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0)
00782                     return ASN_PARSE_E;
00783 
00784                 cert = &pkiMsg[idx];
00785                 certSz += (certIdx - idx);
00786             }
00787             wc_PKCS7_InitWithCert(pkcs7, cert, certSz);
00788         }
00789         idx += length;
00790     }
00791 
00792     /* Get the implicit[1] set of crls */
00793     if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
00794         idx++;
00795         if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00796             return ASN_PARSE_E;
00797 
00798         /* Skip the set */
00799         idx += length;
00800     }
00801 
00802     /* Get the set of signerInfos */
00803     if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00804         return ASN_PARSE_E;
00805 
00806     if (length > 0) {
00807         /* Get the sequence of the first signerInfo */
00808         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00809             return ASN_PARSE_E;
00810 
00811         /* Get the version */
00812         if (GetMyVersion(pkiMsg, &idx, &version) < 0)
00813             return ASN_PARSE_E;
00814 
00815         if (version != 1) {
00816             WOLFSSL_MSG("PKCS#7 signerInfo needs to be of version 1");
00817             return ASN_VERSION_E;
00818         }
00819 
00820         /* Get the sequence of IssuerAndSerialNumber */
00821         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00822             return ASN_PARSE_E;
00823 
00824         /* Skip it */
00825         idx += length;
00826 
00827         /* Get the sequence of digestAlgorithm */
00828         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00829             return ASN_PARSE_E;
00830 
00831         /* Skip it */
00832         idx += length;
00833 
00834         /* Get the IMPLICIT[0] SET OF signedAttributes */
00835         if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
00836             idx++;
00837 
00838             if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00839                 return ASN_PARSE_E;
00840 
00841             idx += length;
00842         }
00843 
00844         /* Get the sequence of digestEncryptionAlgorithm */
00845         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00846             return ASN_PARSE_E;
00847 
00848         /* Skip it */
00849         idx += length;
00850 
00851         /* Get the signature */
00852         if (pkiMsg[idx] == ASN_OCTET_STRING) {
00853             idx++;
00854 
00855             if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00856                 return ASN_PARSE_E;
00857 
00858             /* save pointer and length */
00859             sig = &pkiMsg[idx];
00860             sigSz = length;
00861 
00862             idx += length;
00863         }
00864 
00865         pkcs7->content = content;
00866         pkcs7->contentSz = contentSz;
00867 
00868         {
00869             word32 scratch = 0;
00870             int plainSz = 0;
00871             #define  MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ +\
00872                            MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE)
00873 
00874 #ifdef WOLFSSL_SMALL_STACK
00875             byte* digest;
00876             RsaKey* key;
00877 
00878             digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL,
00879                                     DYNAMIC_TYPE_TMP_BUFFER);
00880 
00881             if (digest == NULL)
00882                 return MEMORY_E;
00883 
00884             key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL,
00885                                                        DYNAMIC_TYPE_TMP_BUFFER);
00886             if (key == NULL) {
00887                 XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00888                 return MEMORY_E;
00889             }
00890 #else
00891             byte digest[MAX_PKCS7_DIGEST_SZ];
00892             RsaKey stack_key;
00893             RsaKey* key = &stack_key;
00894 #endif
00895 
00896             XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ);
00897 
00898             ret = wc_InitRsaKey(key, NULL);
00899             if (ret != 0) {
00900 #ifdef WOLFSSL_SMALL_STACK
00901                 XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00902                 XFREE(key,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
00903 #endif
00904                 return ret;
00905             }
00906             if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key,
00907                                    pkcs7->publicKeySz) < 0) {
00908                 WOLFSSL_MSG("ASN RSA key decode error");
00909 #ifdef WOLFSSL_SMALL_STACK
00910                 XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00911                 XFREE(key,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
00912 #endif
00913                 return PUBLIC_KEY_E;
00914             }
00915 
00916             plainSz = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ,
00917                                        key);
00918             wc_FreeRsaKey(key);
00919 
00920 #ifdef WOLFSSL_SMALL_STACK
00921             XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00922             XFREE(key,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
00923 #endif
00924 
00925             if (plainSz < 0)
00926                 return plainSz;
00927         }
00928     }
00929 
00930     return 0;
00931 }
00932 
00933 
00934 /* create ASN.1 formatted RecipientInfo structure, returns sequence size */
00935 WOLFSSL_LOCAL int wc_CreateRecipientInfo(const byte* cert, word32 certSz,
00936                                      int keyEncAlgo, int blockKeySz,
00937                                      WC_RNG* rng, byte* contentKeyPlain,
00938                                      byte* contentKeyEnc,
00939                                      int* keyEncSz, byte* out, word32 outSz)
00940 {
00941     word32 idx = 0;
00942     int ret = 0, totalSz = 0;
00943     int verSz, issuerSz, snSz, keyEncAlgSz;
00944     int issuerSeqSz, recipSeqSz, issuerSerialSeqSz;
00945     int encKeyOctetStrSz;
00946 
00947     byte ver[MAX_VERSION_SZ];
00948     byte issuerSerialSeq[MAX_SEQ_SZ];
00949     byte recipSeq[MAX_SEQ_SZ];
00950     byte issuerSeq[MAX_SEQ_SZ];
00951     byte encKeyOctetStr[MAX_OCTET_STR_SZ];
00952 
00953 #ifdef WOLFSSL_SMALL_STACK
00954     byte *serial;
00955     byte *keyAlgArray;
00956     
00957     RsaKey* pubKey;
00958     DecodedCert* decoded;
00959 
00960     serial = (byte*)XMALLOC(MAX_SN_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00961     keyAlgArray = (byte*)XMALLOC(MAX_SN_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00962     decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
00963                                                        DYNAMIC_TYPE_TMP_BUFFER);
00964 
00965     if (decoded == NULL || serial == NULL || keyAlgArray == NULL) {
00966         if (serial)      XFREE(serial,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
00967         if (keyAlgArray) XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00968         if (decoded)     XFREE(decoded,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
00969         return MEMORY_E;
00970     }
00971     
00972 #else
00973     byte serial[MAX_SN_SZ];
00974     byte keyAlgArray[MAX_ALGO_SZ];
00975     
00976     RsaKey stack_pubKey;
00977     RsaKey* pubKey = &stack_pubKey;
00978     DecodedCert stack_decoded;
00979     DecodedCert* decoded = &stack_decoded;
00980 #endif
00981 
00982     InitDecodedCert(decoded, (byte*)cert, certSz, 0);
00983     ret = ParseCert(decoded, CA_TYPE, NO_VERIFY, 0);
00984     if (ret < 0) {
00985         FreeDecodedCert(decoded);
00986 #ifdef WOLFSSL_SMALL_STACK
00987         XFREE(serial,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
00988         XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00989         XFREE(decoded,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
00990 #endif
00991         return ret;
00992     }
00993 
00994     /* version */
00995     verSz = SetMyVersion(0, ver, 0);
00996 
00997     /* IssuerAndSerialNumber */
00998     if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) {
00999         WOLFSSL_MSG("DecodedCert lacks raw issuer pointer and length");
01000         FreeDecodedCert(decoded);
01001 #ifdef WOLFSSL_SMALL_STACK
01002         XFREE(serial,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
01003         XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01004         XFREE(decoded,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
01005 #endif
01006         return -1;
01007     }
01008     issuerSz    = decoded->issuerRawLen;
01009     issuerSeqSz = SetSequence(issuerSz, issuerSeq);
01010 
01011     if (decoded->serialSz == 0) {
01012         WOLFSSL_MSG("DecodedCert missing serial number");
01013         FreeDecodedCert(decoded);
01014 #ifdef WOLFSSL_SMALL_STACK
01015         XFREE(serial,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
01016         XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01017         XFREE(decoded,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
01018 #endif
01019         return -1;
01020     }
01021     snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial);
01022 
01023     issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz,
01024                                     issuerSerialSeq);
01025 
01026     /* KeyEncryptionAlgorithmIdentifier, only support RSA now */
01027     if (keyEncAlgo != RSAk) {
01028         FreeDecodedCert(decoded);
01029 #ifdef WOLFSSL_SMALL_STACK
01030         XFREE(serial,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
01031         XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01032         XFREE(decoded,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
01033 #endif
01034         return ALGO_ID_E;
01035     }
01036 
01037     keyEncAlgSz = SetAlgoID(keyEncAlgo, keyAlgArray, keyType, 0);
01038     if (keyEncAlgSz == 0) {
01039         FreeDecodedCert(decoded);
01040 #ifdef WOLFSSL_SMALL_STACK
01041         XFREE(serial,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
01042         XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01043         XFREE(decoded,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
01044 #endif
01045         return BAD_FUNC_ARG;
01046     }
01047 
01048 #ifdef WOLFSSL_SMALL_STACK
01049     pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER);
01050     if (pubKey == NULL) {
01051         FreeDecodedCert(decoded);
01052         XFREE(serial,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
01053         XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01054         XFREE(decoded,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
01055         return MEMORY_E;
01056     }
01057 #endif
01058 
01059     /* EncryptedKey */
01060     ret = wc_InitRsaKey(pubKey, 0);
01061     if (ret != 0) {
01062         FreeDecodedCert(decoded);
01063 #ifdef WOLFSSL_SMALL_STACK
01064         XFREE(pubKey,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
01065         XFREE(serial,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
01066         XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01067         XFREE(decoded,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
01068 #endif
01069         return ret;
01070     }
01071 
01072     if (wc_RsaPublicKeyDecode(decoded->publicKey, &idx, pubKey,
01073                            decoded->pubKeySize) < 0) {
01074         WOLFSSL_MSG("ASN RSA key decode error");
01075         wc_FreeRsaKey(pubKey);
01076         FreeDecodedCert(decoded);
01077 #ifdef WOLFSSL_SMALL_STACK
01078         XFREE(pubKey,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
01079         XFREE(serial,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
01080         XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01081         XFREE(decoded,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
01082 #endif
01083         return PUBLIC_KEY_E;
01084     }
01085 
01086     *keyEncSz = wc_RsaPublicEncrypt(contentKeyPlain, blockKeySz, contentKeyEnc,
01087                                  MAX_ENCRYPTED_KEY_SZ, pubKey, rng);
01088     wc_FreeRsaKey(pubKey);
01089 
01090 #ifdef WOLFSSL_SMALL_STACK
01091     XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01092 #endif
01093 
01094     if (*keyEncSz < 0) {
01095         WOLFSSL_MSG("RSA Public Encrypt failed");
01096         FreeDecodedCert(decoded);
01097 #ifdef WOLFSSL_SMALL_STACK
01098         XFREE(serial,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
01099         XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01100         XFREE(decoded,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
01101 #endif
01102         return *keyEncSz;
01103     }
01104 
01105     encKeyOctetStrSz = SetOctetString(*keyEncSz, encKeyOctetStr);
01106 
01107     /* RecipientInfo */
01108     recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz +
01109                              issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz +
01110                              *keyEncSz, recipSeq);
01111 
01112     if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz +
01113         keyEncAlgSz + encKeyOctetStrSz + *keyEncSz > (int)outSz) {
01114         WOLFSSL_MSG("RecipientInfo output buffer too small");
01115         FreeDecodedCert(decoded);
01116 #ifdef WOLFSSL_SMALL_STACK
01117         XFREE(serial,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
01118         XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01119         XFREE(decoded,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
01120 #endif
01121         return BUFFER_E;
01122     }
01123 
01124     XMEMCPY(out + totalSz, recipSeq, recipSeqSz);
01125     totalSz += recipSeqSz;
01126     XMEMCPY(out + totalSz, ver, verSz);
01127     totalSz += verSz;
01128     XMEMCPY(out + totalSz, issuerSerialSeq, issuerSerialSeqSz);
01129     totalSz += issuerSerialSeqSz;
01130     XMEMCPY(out + totalSz, issuerSeq, issuerSeqSz);
01131     totalSz += issuerSeqSz;
01132     XMEMCPY(out + totalSz, decoded->issuerRaw, issuerSz);
01133     totalSz += issuerSz;
01134     XMEMCPY(out + totalSz, serial, snSz);
01135     totalSz += snSz;
01136     XMEMCPY(out + totalSz, keyAlgArray, keyEncAlgSz);
01137     totalSz += keyEncAlgSz;
01138     XMEMCPY(out + totalSz, encKeyOctetStr, encKeyOctetStrSz);
01139     totalSz += encKeyOctetStrSz;
01140     XMEMCPY(out + totalSz, contentKeyEnc, *keyEncSz);
01141     totalSz += *keyEncSz;
01142 
01143     FreeDecodedCert(decoded);
01144 
01145 #ifdef WOLFSSL_SMALL_STACK
01146     XFREE(serial,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
01147     XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01148     XFREE(decoded,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
01149 #endif
01150 
01151     return totalSz;
01152 }
01153 
01154 
01155 /* build PKCS#7 envelopedData content type, return enveloped size */
01156 int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
01157 {
01158     int i, ret, idx = 0;
01159     int totalSz, padSz, desOutSz;
01160 
01161     int contentInfoSeqSz, outerContentTypeSz, outerContentSz;
01162     byte contentInfoSeq[MAX_SEQ_SZ];
01163     byte outerContentType[MAX_ALGO_SZ];
01164     byte outerContent[MAX_SEQ_SZ];
01165 
01166     int envDataSeqSz, verSz;
01167     byte envDataSeq[MAX_SEQ_SZ];
01168     byte ver[MAX_VERSION_SZ];
01169 
01170     WC_RNG rng;
01171     int contentKeyEncSz, blockKeySz;
01172     byte contentKeyPlain[MAX_CONTENT_KEY_LEN];
01173 #ifdef WOLFSSL_SMALL_STACK
01174     byte* contentKeyEnc;
01175 #else
01176     byte contentKeyEnc[MAX_ENCRYPTED_KEY_SZ];
01177 #endif
01178     byte* plain;
01179     byte* encryptedContent;
01180 
01181     int recipSz, recipSetSz;
01182 #ifdef WOLFSSL_SMALL_STACK
01183     byte* recip;
01184 #else
01185     byte recip[MAX_RECIP_SZ];
01186 #endif
01187     byte recipSet[MAX_SET_SZ];
01188 
01189     int encContentOctetSz, encContentSeqSz, contentTypeSz;
01190     int contentEncAlgoSz, ivOctetStringSz;
01191     byte encContentSeq[MAX_SEQ_SZ];
01192     byte contentType[MAX_ALGO_SZ];
01193     byte contentEncAlgo[MAX_ALGO_SZ];
01194     byte tmpIv[DES_BLOCK_SIZE];
01195     byte ivOctetString[MAX_OCTET_STR_SZ];
01196     byte encContentOctet[MAX_OCTET_STR_SZ];
01197 
01198     if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
01199         pkcs7->encryptOID == 0 || pkcs7->singleCert == NULL)
01200         return BAD_FUNC_ARG;
01201 
01202     if (output == NULL || outputSz == 0)
01203         return BAD_FUNC_ARG;
01204 
01205     /* PKCS#7 only supports DES, 3DES for now */
01206     switch (pkcs7->encryptOID) {
01207         case DESb:
01208             blockKeySz = DES_KEYLEN;
01209             break;
01210 
01211         case DES3b:
01212             blockKeySz = DES3_KEYLEN;
01213             break;
01214 
01215         default:
01216             WOLFSSL_MSG("Unsupported content cipher type");
01217             return ALGO_ID_E;
01218     };
01219 
01220     /* outer content type */
01221     outerContentTypeSz = wc_SetContentType(ENVELOPED_DATA, outerContentType);
01222 
01223     /* version, defined as 0 in RFC 2315 */
01224     verSz = SetMyVersion(0, ver, 0);
01225 
01226     /* generate random content encryption key */
01227     ret = wc_InitRng(&rng);
01228     if (ret != 0)
01229         return ret;
01230 
01231     ret = wc_RNG_GenerateBlock(&rng, contentKeyPlain, blockKeySz);
01232     if (ret != 0) {
01233         wc_FreeRng(&rng);
01234         return ret;
01235     }
01236 
01237 #ifdef WOLFSSL_SMALL_STACK
01238     recip         = (byte*)XMALLOC(MAX_RECIP_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01239     contentKeyEnc = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, NULL, 
01240                                                        DYNAMIC_TYPE_TMP_BUFFER);
01241     if (contentKeyEnc == NULL || recip == NULL) {
01242         if (recip)         XFREE(recip,         NULL, DYNAMIC_TYPE_TMP_BUFFER);
01243         if (contentKeyEnc) XFREE(contentKeyEnc, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01244         wc_FreeRng(&rng);
01245         return MEMORY_E;
01246     }
01247     
01248 #endif
01249 
01250     /* build RecipientInfo, only handle 1 for now */
01251     recipSz = wc_CreateRecipientInfo(pkcs7->singleCert, pkcs7->singleCertSz, RSAk,
01252                                   blockKeySz, &rng, contentKeyPlain,
01253                                   contentKeyEnc, &contentKeyEncSz, recip,
01254                                   MAX_RECIP_SZ);
01255                                                                       
01256     ForceZero(contentKeyEnc, MAX_ENCRYPTED_KEY_SZ);
01257     
01258 #ifdef WOLFSSL_SMALL_STACK
01259     XFREE(contentKeyEnc, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01260 #endif
01261 
01262     if (recipSz < 0) {
01263         WOLFSSL_MSG("Failed to create RecipientInfo");
01264         wc_FreeRng(&rng);
01265 #ifdef WOLFSSL_SMALL_STACK
01266         XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
01267 #endif
01268         return recipSz;
01269     }
01270     recipSetSz = SetSet(recipSz, recipSet);
01271 
01272     /* generate IV for block cipher */
01273     ret = wc_RNG_GenerateBlock(&rng, tmpIv, DES_BLOCK_SIZE);
01274     wc_FreeRng(&rng);
01275     if (ret != 0) {
01276 #ifdef WOLFSSL_SMALL_STACK
01277         XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
01278 #endif
01279         return ret;
01280     }
01281 
01282     /* EncryptedContentInfo */
01283     contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType);
01284     if (contentTypeSz == 0) {
01285 #ifdef WOLFSSL_SMALL_STACK
01286         XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
01287 #endif
01288         return BAD_FUNC_ARG;
01289     }
01290 
01291     /* allocate encrypted content buffer and PKCS#7 padding */
01292     padSz = DES_BLOCK_SIZE - (pkcs7->contentSz % DES_BLOCK_SIZE);
01293     desOutSz = pkcs7->contentSz + padSz;
01294 
01295     plain = (byte*)XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01296     if (plain == NULL) {
01297 #ifdef WOLFSSL_SMALL_STACK
01298         XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
01299 #endif
01300         return MEMORY_E;
01301     }
01302     XMEMCPY(plain, pkcs7->content, pkcs7->contentSz);
01303 
01304     for (i = 0; i < padSz; i++) {
01305         plain[pkcs7->contentSz + i] = (byte)padSz;
01306     }
01307 
01308     encryptedContent = (byte*)XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01309     if (encryptedContent == NULL) {
01310         XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01311 #ifdef WOLFSSL_SMALL_STACK
01312         XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
01313 #endif
01314         return MEMORY_E;
01315     }
01316 
01317     /* put together IV OCTET STRING */
01318     ivOctetStringSz = SetOctetString(DES_BLOCK_SIZE, ivOctetString);
01319 
01320     /* build up our ContentEncryptionAlgorithmIdentifier sequence,
01321      * adding (ivOctetStringSz + DES_BLOCK_SIZE) for IV OCTET STRING */
01322     contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
01323                                  blkType, ivOctetStringSz + DES_BLOCK_SIZE);
01324 
01325     if (contentEncAlgoSz == 0) {
01326         XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01327         XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01328 #ifdef WOLFSSL_SMALL_STACK
01329         XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
01330 #endif
01331         return BAD_FUNC_ARG;
01332     }
01333 
01334     /* encrypt content */
01335     if (pkcs7->encryptOID == DESb) {
01336         Des des;
01337 
01338         ret = wc_Des_SetKey(&des, contentKeyPlain, tmpIv, DES_ENCRYPTION);
01339 
01340         if (ret == 0)
01341             wc_Des_CbcEncrypt(&des, encryptedContent, plain, desOutSz);
01342 
01343         if (ret != 0) {
01344             XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01345             XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01346 #ifdef WOLFSSL_SMALL_STACK
01347             XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
01348 #endif
01349             return ret;
01350         }
01351     }
01352     else if (pkcs7->encryptOID == DES3b) {
01353         Des3 des3;
01354 
01355         ret = wc_Des3_SetKey(&des3, contentKeyPlain, tmpIv, DES_ENCRYPTION);
01356 
01357         if (ret == 0)
01358             ret = wc_Des3_CbcEncrypt(&des3, encryptedContent, plain, desOutSz);
01359 
01360         if (ret != 0) {
01361             XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01362             XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01363 #ifdef WOLFSSL_SMALL_STACK
01364             XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
01365 #endif
01366             return ret;
01367         }
01368     }
01369 
01370     encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0,
01371                                     desOutSz, encContentOctet);
01372 
01373     encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
01374                                   ivOctetStringSz + DES_BLOCK_SIZE +
01375                                   encContentOctetSz + desOutSz, encContentSeq);
01376 
01377     /* keep track of sizes for outer wrapper layering */
01378     totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz +
01379               contentEncAlgoSz + ivOctetStringSz + DES_BLOCK_SIZE +
01380               encContentOctetSz + desOutSz;
01381 
01382     /* EnvelopedData */
01383     envDataSeqSz = SetSequence(totalSz, envDataSeq);
01384     totalSz += envDataSeqSz;
01385 
01386     /* outer content */
01387     outerContentSz = SetExplicit(0, totalSz, outerContent);
01388     totalSz += outerContentTypeSz;
01389     totalSz += outerContentSz;
01390 
01391     /* ContentInfo */
01392     contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
01393     totalSz += contentInfoSeqSz;
01394 
01395     if (totalSz > (int)outputSz) {
01396         WOLFSSL_MSG("Pkcs7_encrypt output buffer too small");
01397         XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01398         XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01399 #ifdef WOLFSSL_SMALL_STACK
01400         XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
01401 #endif
01402         return BUFFER_E;
01403     }
01404 
01405     XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz);
01406     idx += contentInfoSeqSz;
01407     XMEMCPY(output + idx, outerContentType, outerContentTypeSz);
01408     idx += outerContentTypeSz;
01409     XMEMCPY(output + idx, outerContent, outerContentSz);
01410     idx += outerContentSz;
01411     XMEMCPY(output + idx, envDataSeq, envDataSeqSz);
01412     idx += envDataSeqSz;
01413     XMEMCPY(output + idx, ver, verSz);
01414     idx += verSz;
01415     XMEMCPY(output + idx, recipSet, recipSetSz);
01416     idx += recipSetSz;
01417     XMEMCPY(output + idx, recip, recipSz);
01418     idx += recipSz;
01419     XMEMCPY(output + idx, encContentSeq, encContentSeqSz);
01420     idx += encContentSeqSz;
01421     XMEMCPY(output + idx, contentType, contentTypeSz);
01422     idx += contentTypeSz;
01423     XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz);
01424     idx += contentEncAlgoSz;
01425     XMEMCPY(output + idx, ivOctetString, ivOctetStringSz);
01426     idx += ivOctetStringSz;
01427     XMEMCPY(output + idx, tmpIv, DES_BLOCK_SIZE);
01428     idx += DES_BLOCK_SIZE;
01429     XMEMCPY(output + idx, encContentOctet, encContentOctetSz);
01430     idx += encContentOctetSz;
01431     XMEMCPY(output + idx, encryptedContent, desOutSz);
01432     idx += desOutSz;
01433 
01434     ForceZero(contentKeyPlain, MAX_CONTENT_KEY_LEN);
01435 
01436     XFREE(plain, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
01437     XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01438     
01439 #ifdef WOLFSSL_SMALL_STACK
01440     XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
01441 #endif
01442 
01443     return idx;
01444 }
01445 
01446 /* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */
01447 WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
01448                                          word32 pkiMsgSz, byte* output,
01449                                          word32 outputSz)
01450 {
01451     int recipFound = 0;
01452     int ret, version, length;
01453     word32 savedIdx = 0, idx = 0;
01454     word32 contentType, encOID;
01455     byte   issuerHash[SHA_DIGEST_SIZE];
01456 
01457     int encryptedKeySz, keySz;
01458     byte tmpIv[DES_BLOCK_SIZE];
01459     byte* decryptedKey = NULL;
01460 
01461 #ifdef WOLFSSL_SMALL_STACK
01462     mp_int* serialNum;
01463     byte* encryptedKey;
01464     RsaKey* privKey;
01465 #else
01466     mp_int stack_serialNum;
01467     mp_int* serialNum = &stack_serialNum;
01468     byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
01469     
01470     RsaKey stack_privKey;
01471     RsaKey* privKey = &stack_privKey;
01472 #endif
01473     int encryptedContentSz;
01474     byte padLen;
01475     byte* encryptedContent = NULL;
01476 
01477     if (pkcs7 == NULL || pkcs7->singleCert == NULL ||
01478         pkcs7->singleCertSz == 0 || pkcs7->privateKey == NULL ||
01479         pkcs7->privateKeySz == 0)
01480         return BAD_FUNC_ARG;
01481 
01482     if (pkiMsg == NULL || pkiMsgSz == 0 ||
01483         output == NULL || outputSz == 0)
01484         return BAD_FUNC_ARG;
01485 
01486     /* read past ContentInfo, verify type is envelopedData */
01487     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01488         return ASN_PARSE_E;
01489 
01490     if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
01491         return ASN_PARSE_E;
01492 
01493     if (contentType != ENVELOPED_DATA) {
01494         WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData");
01495         return PKCS7_OID_E;
01496     }
01497 
01498     if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
01499         return ASN_PARSE_E;
01500 
01501     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01502         return ASN_PARSE_E;
01503 
01504     /* remove EnvelopedData and version */
01505     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01506         return ASN_PARSE_E;
01507 
01508     if (GetMyVersion(pkiMsg, &idx, &version) < 0)
01509         return ASN_PARSE_E;
01510 
01511     if (version != 0) {
01512         WOLFSSL_MSG("PKCS#7 envelopedData needs to be of version 0");
01513         return ASN_VERSION_E;
01514     }
01515 
01516     /* walk through RecipientInfo set, find correct recipient */
01517     if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01518         return ASN_PARSE_E;
01519     
01520 #ifdef WOLFSSL_SMALL_STACK
01521     encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, NULL,
01522                                                        DYNAMIC_TYPE_TMP_BUFFER);
01523     if (encryptedKey == NULL)
01524         return MEMORY_E;
01525 #endif
01526     
01527     savedIdx = idx;
01528     recipFound = 0;
01529 
01530     /* when looking for next recipient, use first sequence and version to
01531      * indicate there is another, if not, move on */
01532     while(recipFound == 0) {
01533 
01534         /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to
01535          * last good saved one */
01536         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
01537             idx = savedIdx;
01538             break;
01539         }
01540 
01541         if (GetMyVersion(pkiMsg, &idx, &version) < 0) {
01542             idx = savedIdx;
01543             break;
01544         }
01545 
01546         if (version != 0) {
01547 #ifdef WOLFSSL_SMALL_STACK
01548             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01549 #endif
01550             return ASN_VERSION_E;
01551         }
01552         
01553         /* remove IssuerAndSerialNumber */
01554         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
01555 #ifdef WOLFSSL_SMALL_STACK
01556             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01557 #endif
01558             return ASN_PARSE_E;
01559         }
01560         
01561         if (GetNameHash(pkiMsg, &idx, issuerHash, pkiMsgSz) < 0) {
01562 #ifdef WOLFSSL_SMALL_STACK
01563             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01564 #endif
01565             return ASN_PARSE_E;
01566         }
01567         
01568         /* if we found correct recipient, issuer hashes will match */
01569         if (XMEMCMP(issuerHash, pkcs7->issuerHash, SHA_DIGEST_SIZE) == 0) {
01570             recipFound = 1;
01571         }
01572         
01573 #ifdef WOLFSSL_SMALL_STACK
01574         serialNum = (mp_int*)XMALLOC(sizeof(mp_int), NULL,
01575                                                        DYNAMIC_TYPE_TMP_BUFFER);
01576         if (serialNum == NULL) {
01577             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01578             return MEMORY_E;
01579         }
01580 #endif
01581         
01582         if (GetInt(serialNum, pkiMsg, &idx, pkiMsgSz) < 0) {
01583 #ifdef WOLFSSL_SMALL_STACK
01584             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01585             XFREE(serialNum,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
01586 #endif
01587             return ASN_PARSE_E;
01588         }
01589         
01590         mp_clear(serialNum);
01591         
01592 #ifdef WOLFSSL_SMALL_STACK
01593         XFREE(serialNum, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01594 #endif
01595         
01596         if (GetAlgoId(pkiMsg, &idx, &encOID, keyType, pkiMsgSz) < 0) {
01597 #ifdef WOLFSSL_SMALL_STACK
01598             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01599 #endif
01600             return ASN_PARSE_E;
01601         }
01602         
01603         /* key encryption algorithm must be RSA for now */
01604         if (encOID != RSAk) {
01605 #ifdef WOLFSSL_SMALL_STACK
01606             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01607 #endif
01608             return ALGO_ID_E;
01609         }
01610         
01611         /* read encryptedKey */
01612         if (pkiMsg[idx++] != ASN_OCTET_STRING) {
01613 #ifdef WOLFSSL_SMALL_STACK
01614             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01615 #endif
01616             return ASN_PARSE_E;
01617         }
01618         
01619         if (GetLength(pkiMsg, &idx, &encryptedKeySz, pkiMsgSz) < 0) {
01620 #ifdef WOLFSSL_SMALL_STACK
01621             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01622 #endif
01623             return ASN_PARSE_E;
01624         }
01625           
01626         if (recipFound == 1)
01627             XMEMCPY(encryptedKey, &pkiMsg[idx], encryptedKeySz);
01628         idx += encryptedKeySz;
01629 
01630         /* update good idx */
01631         savedIdx = idx;
01632     }
01633 
01634     if (recipFound == 0) {
01635         WOLFSSL_MSG("No recipient found in envelopedData that matches input");
01636 #ifdef WOLFSSL_SMALL_STACK
01637         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01638 #endif
01639         return PKCS7_RECIP_E;
01640     }
01641 
01642     /* remove EncryptedContentInfo */
01643     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
01644 #ifdef WOLFSSL_SMALL_STACK
01645         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01646 #endif
01647         return ASN_PARSE_E;
01648     }
01649     
01650     if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) {
01651 #ifdef WOLFSSL_SMALL_STACK
01652         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01653 #endif
01654         return ASN_PARSE_E;
01655     }
01656 
01657     if (GetAlgoId(pkiMsg, &idx, &encOID, blkType, pkiMsgSz) < 0) {
01658 #ifdef WOLFSSL_SMALL_STACK
01659         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01660 #endif
01661         return ASN_PARSE_E;
01662     }
01663     
01664     /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
01665     if (pkiMsg[idx++] != ASN_OCTET_STRING) {
01666 #ifdef WOLFSSL_SMALL_STACK
01667         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01668 #endif
01669         return ASN_PARSE_E;
01670     }
01671     
01672     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
01673 #ifdef WOLFSSL_SMALL_STACK
01674         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01675 #endif
01676         return ASN_PARSE_E;
01677     }
01678     
01679     if (length != DES_BLOCK_SIZE) {
01680         WOLFSSL_MSG("Incorrect IV length, must be of DES_BLOCK_SIZE");
01681 #ifdef WOLFSSL_SMALL_STACK
01682         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01683 #endif
01684         return ASN_PARSE_E;
01685     }
01686 
01687     XMEMCPY(tmpIv, &pkiMsg[idx], length);
01688     idx += length;
01689 
01690     /* read encryptedContent, cont[0] */
01691     if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) {
01692 #ifdef WOLFSSL_SMALL_STACK
01693         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01694 #endif
01695         return ASN_PARSE_E;
01696     }
01697 
01698     if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0) {
01699 #ifdef WOLFSSL_SMALL_STACK
01700         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01701 #endif
01702         return ASN_PARSE_E;
01703     }
01704     
01705     encryptedContent = (byte*)XMALLOC(encryptedContentSz, NULL,
01706                                                        DYNAMIC_TYPE_TMP_BUFFER);
01707     if (encryptedContent == NULL) {
01708 #ifdef WOLFSSL_SMALL_STACK
01709         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01710 #endif
01711         return MEMORY_E;
01712     }
01713 
01714     XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
01715 
01716     /* load private key */
01717 #ifdef WOLFSSL_SMALL_STACK
01718     privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER);
01719     if (privKey == NULL) {
01720         XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01721         XFREE(encryptedKey,     NULL, DYNAMIC_TYPE_TMP_BUFFER);        return MEMORY_E;
01722     }
01723 #endif
01724 
01725     ret = wc_InitRsaKey(privKey, 0);
01726     if (ret != 0) {
01727         XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01728 #ifdef WOLFSSL_SMALL_STACK
01729         XFREE(privKey,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
01730         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01731 #endif
01732         return ret;
01733     }
01734 
01735     idx = 0;
01736 
01737     ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey,
01738                               pkcs7->privateKeySz);
01739     if (ret != 0) {
01740         WOLFSSL_MSG("Failed to decode RSA private key");
01741         XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01742 #ifdef WOLFSSL_SMALL_STACK
01743         XFREE(privKey,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
01744         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01745 #endif
01746         return ret;
01747     }
01748 
01749     /* decrypt encryptedKey */
01750     keySz = wc_RsaPrivateDecryptInline(encryptedKey, encryptedKeySz,
01751                                     &decryptedKey, privKey);
01752     wc_FreeRsaKey(privKey);
01753 
01754 #ifdef WOLFSSL_SMALL_STACK
01755     XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01756 #endif
01757 
01758     if (keySz <= 0) {
01759         XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01760 #ifdef WOLFSSL_SMALL_STACK
01761         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01762 #endif
01763         return keySz;
01764     }
01765 
01766     /* decrypt encryptedContent */
01767     if (encOID == DESb) {
01768         Des des;
01769         ret = wc_Des_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION);
01770 
01771         if (ret == 0)
01772             wc_Des_CbcDecrypt(&des, encryptedContent, encryptedContent,
01773                                  encryptedContentSz);
01774 
01775         if (ret != 0) {
01776             XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01777 #ifdef WOLFSSL_SMALL_STACK
01778             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01779 #endif
01780             return ret;
01781         }
01782     }
01783     else if (encOID == DES3b) {
01784         Des3 des;
01785         ret = wc_Des3_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION);
01786         if (ret == 0)
01787             ret = wc_Des3_CbcDecrypt(&des, encryptedContent, encryptedContent,
01788                                   encryptedContentSz);
01789 
01790         if (ret != 0) {
01791             XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01792 #ifdef WOLFSSL_SMALL_STACK
01793             XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01794 #endif
01795             return ret;
01796         }
01797     } else {
01798         WOLFSSL_MSG("Unsupported content encryption OID type");
01799         XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01800 #ifdef WOLFSSL_SMALL_STACK
01801         XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01802 #endif
01803         return ALGO_ID_E;
01804     }
01805 
01806     padLen = encryptedContent[encryptedContentSz-1];
01807 
01808     /* copy plaintext to output */
01809     XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
01810 
01811     /* free memory, zero out keys */
01812     ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ);
01813     ForceZero(encryptedContent, encryptedContentSz);
01814     XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01815 #ifdef WOLFSSL_SMALL_STACK
01816     XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01817 #endif
01818     
01819     return encryptedContentSz - padLen;
01820 }
01821 
01822 
01823 #else  /* HAVE_PKCS7 */
01824 
01825 
01826 #ifdef _MSC_VER
01827     /* 4206 warning for blank file */
01828     #pragma warning(disable: 4206)
01829 #endif
01830 
01831 
01832 #endif /* HAVE_PKCS7 */
01833 
01834