Dependents:   HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL

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