wolf SSL / CyaSSL-2.9.4

Dependents:  

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-2013 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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         DecodedCert dCert;
00157 
00158         pkcs7->singleCert = cert;
00159         pkcs7->singleCertSz = certSz;
00160         InitDecodedCert(&dCert, cert, certSz, 0);
00161 
00162         ret = ParseCert(&dCert, CA_TYPE, NO_VERIFY, 0);
00163         if (ret < 0) {
00164             FreeDecodedCert(&dCert);
00165             return ret;
00166         }
00167         XMEMCPY(pkcs7->publicKey, dCert.publicKey, dCert.pubKeySize);
00168         pkcs7->publicKeySz = dCert.pubKeySize;
00169         XMEMCPY(pkcs7->issuerHash, dCert.issuerHash, SHA_SIZE);
00170         pkcs7->issuer = dCert.issuerRaw;
00171         pkcs7->issuerSz = dCert.issuerRawLen;
00172         XMEMCPY(pkcs7->issuerSn, dCert.serial, dCert.serialSz);
00173         pkcs7->issuerSnSz = dCert.serialSz;
00174         FreeDecodedCert(&dCert);
00175     }
00176 
00177     return ret;
00178 }
00179 
00180 
00181 /* releases any memory allocated by a PKCS7 initializer */
00182 void PKCS7_Free(PKCS7* pkcs7)
00183 {
00184     (void)pkcs7;
00185 }
00186 
00187 
00188 /* build PKCS#7 data content type */
00189 int PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz)
00190 {
00191     static const byte oid[] =
00192         { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
00193                          0x07, 0x01 };
00194     byte seq[MAX_SEQ_SZ];
00195     byte octetStr[MAX_OCTET_STR_SZ];
00196     word32 seqSz;
00197     word32 octetStrSz;
00198     word32 oidSz = (word32)sizeof(oid);
00199     int idx = 0;
00200 
00201     octetStrSz = SetOctetString(pkcs7->contentSz, octetStr);
00202     seqSz = SetSequence(pkcs7->contentSz + octetStrSz + oidSz, seq);
00203 
00204     if (outputSz < pkcs7->contentSz + octetStrSz + oidSz + seqSz)
00205         return BUFFER_E;
00206 
00207     XMEMCPY(output, seq, seqSz);
00208     idx += seqSz;
00209     XMEMCPY(output + idx, oid, oidSz);
00210     idx += oidSz;
00211     XMEMCPY(output + idx, octetStr, octetStrSz);
00212     idx += octetStrSz;
00213     XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
00214     idx += pkcs7->contentSz;
00215 
00216     return idx;
00217 }
00218 
00219 
00220 typedef struct EncodedAttrib {
00221     byte valueSeq[MAX_SEQ_SZ];
00222         const byte* oid;
00223         byte valueSet[MAX_SET_SZ];
00224         const byte* value;
00225     word32 valueSeqSz, oidSz, idSz, valueSetSz, valueSz, totalSz;
00226 } EncodedAttrib;
00227 
00228 
00229 typedef struct ESD {
00230     Sha sha;
00231     byte contentDigest[SHA_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */
00232     byte contentAttribsDigest[SHA_DIGEST_SIZE];
00233     byte encContentDigest[512];
00234 
00235     byte outerSeq[MAX_SEQ_SZ];
00236         byte outerContent[MAX_EXP_SZ];
00237             byte innerSeq[MAX_SEQ_SZ];
00238                 byte version[MAX_VERSION_SZ];
00239                 byte digAlgoIdSet[MAX_SET_SZ];
00240                     byte singleDigAlgoId[MAX_ALGO_SZ];
00241 
00242                 byte contentInfoSeq[MAX_SEQ_SZ];
00243                     byte innerContSeq[MAX_EXP_SZ];
00244                         byte innerOctets[MAX_OCTET_STR_SZ];
00245 
00246                 byte certsSet[MAX_SET_SZ];
00247 
00248                 byte signerInfoSet[MAX_SET_SZ];
00249                     byte signerInfoSeq[MAX_SEQ_SZ];
00250                         byte signerVersion[MAX_VERSION_SZ];
00251                         byte issuerSnSeq[MAX_SEQ_SZ];
00252                             byte issuerName[MAX_SEQ_SZ];
00253                             byte issuerSn[MAX_SN_SZ];
00254                         byte signerDigAlgoId[MAX_ALGO_SZ];
00255                         byte digEncAlgoId[MAX_ALGO_SZ];
00256                         byte signedAttribSet[MAX_SET_SZ];
00257                             EncodedAttrib signedAttribs[6];
00258                         byte signerDigest[MAX_OCTET_STR_SZ];
00259     word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz;
00260     word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz,
00261            singleDigAlgoIdSz, certsSetSz;
00262     word32 signerInfoSetSz, signerInfoSeqSz, signerVersionSz,
00263            issuerSnSeqSz, issuerNameSz, issuerSnSz,
00264            signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz;
00265     word32 encContentDigestSz, signedAttribsSz, signedAttribsCount,
00266            signedAttribSetSz;
00267 } ESD;
00268 
00269 
00270 static int EncodeAttributes(EncodedAttrib* ea, int eaSz,
00271                                             PKCS7Attrib* attribs, int attribsSz)
00272 {
00273     int i;
00274     int maxSz = min(eaSz, attribsSz);
00275     int allAttribsSz = 0;
00276 
00277     for (i = 0; i < maxSz; i++)
00278     {
00279         int attribSz = 0;
00280 
00281         ea[i].value = attribs[i].value;
00282         ea[i].valueSz = attribs[i].valueSz;
00283         attribSz += ea[i].valueSz;
00284         ea[i].valueSetSz = SetSet(attribSz, ea[i].valueSet);
00285         attribSz += ea[i].valueSetSz;
00286         ea[i].oid = attribs[i].oid;
00287         ea[i].oidSz = attribs[i].oidSz;
00288         attribSz += ea[i].oidSz;
00289         ea[i].valueSeqSz = SetSequence(attribSz, ea[i].valueSeq);
00290         attribSz += ea[i].valueSeqSz;
00291         ea[i].totalSz = attribSz;
00292 
00293         allAttribsSz += attribSz;
00294     }
00295     return allAttribsSz;
00296 }
00297 
00298 
00299 static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz)
00300 {
00301     int i, idx;
00302 
00303     idx = 0;
00304     for (i = 0; i < eaSz; i++) {
00305         XMEMCPY(output + idx, ea[i].valueSeq, ea[i].valueSeqSz);
00306         idx += ea[i].valueSeqSz;
00307         XMEMCPY(output + idx, ea[i].oid, ea[i].oidSz);
00308         idx += ea[i].oidSz;
00309         XMEMCPY(output + idx, ea[i].valueSet, ea[i].valueSetSz);
00310         idx += ea[i].valueSetSz;
00311         XMEMCPY(output + idx, ea[i].value, ea[i].valueSz);
00312         idx += ea[i].valueSz;
00313     }
00314     return 0;
00315 }
00316 
00317 
00318 /* build PKCS#7 signedData content type */
00319 int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz)
00320 {
00321     static const byte outerOid[] =
00322         { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
00323                          0x07, 0x02 };
00324     static const byte innerOid[] =
00325         { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
00326                          0x07, 0x01 };
00327 
00328     ESD esd;
00329     word32 signerInfoSz = 0;
00330     word32 totalSz = 0;
00331     int idx = 0, ret = 0;
00332     byte* flatSignedAttribs = NULL;
00333     word32 flatSignedAttribsSz = 0;
00334     word32 innerOidSz = sizeof(innerOid);
00335     word32 outerOidSz = sizeof(outerOid);
00336 
00337     if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
00338         pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 ||
00339         pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0 ||
00340         pkcs7->privateKey == NULL || pkcs7->privateKeySz == 0 ||
00341         output == NULL || outputSz == 0)
00342         return BAD_FUNC_ARG;
00343 
00344     XMEMSET(&esd, 0, sizeof(esd));
00345     ret = InitSha(&esd.sha);
00346     if (ret != 0)
00347         return ret;
00348 
00349     if (pkcs7->contentSz != 0)
00350     {
00351         ShaUpdate(&esd.sha, pkcs7->content, pkcs7->contentSz);
00352         esd.contentDigest[0] = ASN_OCTET_STRING;
00353         esd.contentDigest[1] = SHA_DIGEST_SIZE;
00354         ShaFinal(&esd.sha, &esd.contentDigest[2]);
00355     }
00356 
00357     esd.innerOctetsSz = SetOctetString(pkcs7->contentSz, esd.innerOctets);
00358     esd.innerContSeqSz = SetExplicit(0, esd.innerOctetsSz + pkcs7->contentSz,
00359                                 esd.innerContSeq);
00360     esd.contentInfoSeqSz = SetSequence(pkcs7->contentSz + esd.innerOctetsSz +
00361                                     innerOidSz + esd.innerContSeqSz,
00362                                     esd.contentInfoSeq);
00363 
00364     esd.issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz,
00365                                      esd.issuerSn);
00366     signerInfoSz += esd.issuerSnSz;
00367     esd.issuerNameSz = SetSequence(pkcs7->issuerSz, esd.issuerName);
00368     signerInfoSz += esd.issuerNameSz + pkcs7->issuerSz;
00369     esd.issuerSnSeqSz = SetSequence(signerInfoSz, esd.issuerSnSeq);
00370     signerInfoSz += esd.issuerSnSeqSz;
00371     esd.signerVersionSz = SetMyVersion(1, esd.signerVersion, 0);
00372     signerInfoSz += esd.signerVersionSz;
00373     esd.signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd.signerDigAlgoId,
00374                                       hashType, 0);
00375     signerInfoSz += esd.signerDigAlgoIdSz;
00376     esd.digEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, esd.digEncAlgoId,
00377                                    keyType, 0);
00378     signerInfoSz += esd.digEncAlgoIdSz;
00379 
00380     if (pkcs7->signedAttribsSz != 0) {
00381         byte contentTypeOid[] =
00382                 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01,
00383                                  0x09, 0x03 };
00384         byte contentType[] =
00385                 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
00386                                  0x07, 0x01 };
00387         byte messageDigestOid[] =
00388                 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
00389                                  0x09, 0x04 };
00390 
00391         PKCS7Attrib cannedAttribs[2] =
00392         {
00393             { contentTypeOid, sizeof(contentTypeOid),
00394                              contentType, sizeof(contentType) },
00395             { messageDigestOid, sizeof(messageDigestOid),
00396                              esd.contentDigest, sizeof(esd.contentDigest) }
00397         };
00398         word32 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib);
00399 
00400         esd.signedAttribsCount += cannedAttribsCount;
00401         esd.signedAttribsSz += EncodeAttributes(&esd.signedAttribs[0], 2,
00402                                              cannedAttribs, cannedAttribsCount);
00403 
00404         esd.signedAttribsCount += pkcs7->signedAttribsSz;
00405         esd.signedAttribsSz += EncodeAttributes(&esd.signedAttribs[2], 4,
00406                                   pkcs7->signedAttribs, pkcs7->signedAttribsSz);
00407 
00408         flatSignedAttribs = (byte*)XMALLOC(esd.signedAttribsSz, 0, NULL);
00409         flatSignedAttribsSz = esd.signedAttribsSz;
00410         if (flatSignedAttribs == NULL)
00411             return MEMORY_E;
00412         FlattenAttributes(flatSignedAttribs,
00413                                      esd.signedAttribs, esd.signedAttribsCount);
00414         esd.signedAttribSetSz = SetImplicit(ASN_SET, 0, esd.signedAttribsSz,
00415                                                            esd.signedAttribSet);
00416     }
00417     /* Calculate the final hash and encrypt it. */
00418     {
00419         RsaKey privKey;
00420         int result;
00421         word32 scratch = 0;
00422 
00423         byte digestInfo[MAX_SEQ_SZ + MAX_ALGO_SZ +
00424                         MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE];
00425         byte digestInfoSeq[MAX_SEQ_SZ];
00426         byte digestStr[MAX_OCTET_STR_SZ];
00427         word32 digestInfoSeqSz, digestStrSz;
00428         int digIdx = 0;
00429 
00430         if (pkcs7->signedAttribsSz != 0) {
00431             byte attribSet[MAX_SET_SZ];
00432             word32 attribSetSz;
00433 
00434             attribSetSz = SetSet(flatSignedAttribsSz, attribSet);
00435 
00436             ret = InitSha(&esd.sha);
00437             if (ret < 0) {
00438                 XFREE(flatSignedAttribs, 0, NULL);
00439                 return ret;
00440             }
00441             ShaUpdate(&esd.sha, attribSet, attribSetSz);
00442             ShaUpdate(&esd.sha, flatSignedAttribs, flatSignedAttribsSz);
00443         }
00444         ShaFinal(&esd.sha, esd.contentAttribsDigest);
00445 
00446         digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr);
00447         digestInfoSeqSz = SetSequence(esd.signerDigAlgoIdSz +
00448                                       digestStrSz + SHA_DIGEST_SIZE,
00449                                       digestInfoSeq);
00450 
00451         XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
00452         digIdx += digestInfoSeqSz;
00453         XMEMCPY(digestInfo + digIdx,
00454                                     esd.signerDigAlgoId, esd.signerDigAlgoIdSz);
00455         digIdx += esd.signerDigAlgoIdSz;
00456         XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
00457         digIdx += digestStrSz;
00458         XMEMCPY(digestInfo + digIdx, esd.contentAttribsDigest, SHA_DIGEST_SIZE);
00459         digIdx += SHA_DIGEST_SIZE;
00460 
00461         result = InitRsaKey(&privKey, NULL);
00462         if (result == 0)
00463             result = RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, &privKey,
00464                                          pkcs7->privateKeySz);
00465         if (result < 0) {
00466             XFREE(flatSignedAttribs, 0, NULL);
00467             return PUBLIC_KEY_E;
00468         }
00469         result = RsaSSL_Sign(digestInfo, digIdx,
00470                              esd.encContentDigest, sizeof(esd.encContentDigest),
00471                              &privKey, pkcs7->rng);
00472         FreeRsaKey(&privKey);
00473         if (result < 0) {
00474             XFREE(flatSignedAttribs, 0, NULL);
00475             return result;
00476         }
00477         esd.encContentDigestSz = (word32)result;
00478     }
00479     signerInfoSz += flatSignedAttribsSz + esd.signedAttribSetSz;
00480 
00481     esd.signerDigestSz = SetOctetString(esd.encContentDigestSz,
00482                                                               esd.signerDigest);
00483     signerInfoSz += esd.signerDigestSz + esd.encContentDigestSz;
00484 
00485     esd.signerInfoSeqSz = SetSequence(signerInfoSz, esd.signerInfoSeq);
00486     signerInfoSz += esd.signerInfoSeqSz;
00487     esd.signerInfoSetSz = SetSet(signerInfoSz, esd.signerInfoSet);
00488     signerInfoSz += esd.signerInfoSetSz;
00489 
00490     esd.certsSetSz = SetImplicit(ASN_SET, 0, pkcs7->singleCertSz, esd.certsSet);
00491 
00492     esd.singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd.singleDigAlgoId,
00493                                       hashType, 0);
00494     esd.digAlgoIdSetSz = SetSet(esd.singleDigAlgoIdSz, esd.digAlgoIdSet);
00495 
00496 
00497     esd.versionSz = SetMyVersion(1, esd.version, 0);
00498 
00499     totalSz = esd.versionSz + esd.singleDigAlgoIdSz + esd.digAlgoIdSetSz +
00500               esd.contentInfoSeqSz + esd.certsSetSz + pkcs7->singleCertSz +
00501               esd.innerOctetsSz + esd.innerContSeqSz +
00502               innerOidSz + pkcs7->contentSz +
00503               signerInfoSz;
00504     esd.innerSeqSz = SetSequence(totalSz, esd.innerSeq);
00505     totalSz += esd.innerSeqSz;
00506     esd.outerContentSz = SetExplicit(0, totalSz, esd.outerContent);
00507     totalSz += esd.outerContentSz + outerOidSz;
00508     esd.outerSeqSz = SetSequence(totalSz, esd.outerSeq);
00509     totalSz += esd.outerSeqSz;
00510 
00511     if (outputSz < totalSz)
00512         return BUFFER_E;
00513 
00514     idx = 0;
00515     XMEMCPY(output + idx, esd.outerSeq, esd.outerSeqSz);
00516     idx += esd.outerSeqSz;
00517     XMEMCPY(output + idx, outerOid, outerOidSz);
00518     idx += outerOidSz;
00519     XMEMCPY(output + idx, esd.outerContent, esd.outerContentSz);
00520     idx += esd.outerContentSz;
00521     XMEMCPY(output + idx, esd.innerSeq, esd.innerSeqSz);
00522     idx += esd.innerSeqSz;
00523     XMEMCPY(output + idx, esd.version, esd.versionSz);
00524     idx += esd.versionSz;
00525     XMEMCPY(output + idx, esd.digAlgoIdSet, esd.digAlgoIdSetSz);
00526     idx += esd.digAlgoIdSetSz;
00527     XMEMCPY(output + idx, esd.singleDigAlgoId, esd.singleDigAlgoIdSz);
00528     idx += esd.singleDigAlgoIdSz;
00529     XMEMCPY(output + idx, esd.contentInfoSeq, esd.contentInfoSeqSz);
00530     idx += esd.contentInfoSeqSz;
00531     XMEMCPY(output + idx, innerOid, innerOidSz);
00532     idx += innerOidSz;
00533     XMEMCPY(output + idx, esd.innerContSeq, esd.innerContSeqSz);
00534     idx += esd.innerContSeqSz;
00535     XMEMCPY(output + idx, esd.innerOctets, esd.innerOctetsSz);
00536     idx += esd.innerOctetsSz;
00537     XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
00538     idx += pkcs7->contentSz;
00539     XMEMCPY(output + idx, esd.certsSet, esd.certsSetSz);
00540     idx += esd.certsSetSz;
00541     XMEMCPY(output + idx, pkcs7->singleCert, pkcs7->singleCertSz);
00542     idx += pkcs7->singleCertSz;
00543     XMEMCPY(output + idx, esd.signerInfoSet, esd.signerInfoSetSz);
00544     idx += esd.signerInfoSetSz;
00545     XMEMCPY(output + idx, esd.signerInfoSeq, esd.signerInfoSeqSz);
00546     idx += esd.signerInfoSeqSz;
00547     XMEMCPY(output + idx, esd.signerVersion, esd.signerVersionSz);
00548     idx += esd.signerVersionSz;
00549     XMEMCPY(output + idx, esd.issuerSnSeq, esd.issuerSnSeqSz);
00550     idx += esd.issuerSnSeqSz;
00551     XMEMCPY(output + idx, esd.issuerName, esd.issuerNameSz);
00552     idx += esd.issuerNameSz;
00553     XMEMCPY(output + idx, pkcs7->issuer, pkcs7->issuerSz);
00554     idx += pkcs7->issuerSz;
00555     XMEMCPY(output + idx, esd.issuerSn, esd.issuerSnSz);
00556     idx += esd.issuerSnSz;
00557     XMEMCPY(output + idx, esd.signerDigAlgoId, esd.signerDigAlgoIdSz);
00558     idx += esd.signerDigAlgoIdSz;
00559 
00560     /* SignerInfo:Attributes */
00561     if (pkcs7->signedAttribsSz != 0) {
00562         XMEMCPY(output + idx, esd.signedAttribSet, esd.signedAttribSetSz);
00563         idx += esd.signedAttribSetSz;
00564         XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz);
00565         idx += flatSignedAttribsSz;
00566         XFREE(flatSignedAttribs, 0, NULL);
00567     }
00568 
00569     XMEMCPY(output + idx, esd.digEncAlgoId, esd.digEncAlgoIdSz);
00570     idx += esd.digEncAlgoIdSz;
00571     XMEMCPY(output + idx, esd.signerDigest, esd.signerDigestSz);
00572     idx += esd.signerDigestSz;
00573     XMEMCPY(output + idx, esd.encContentDigest, esd.encContentDigestSz);
00574     idx += esd.encContentDigestSz;
00575 
00576     return idx;
00577 }
00578 
00579 
00580 /* Finds the certificates in the message and saves it. */
00581 int PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
00582 {
00583     word32 idx, contentType;
00584     int length, version, ret;
00585     byte* content = NULL;
00586     byte* sig = NULL;
00587     byte* cert = NULL;
00588     byte* signedAttr = NULL;
00589     int contentSz = 0, sigSz = 0, certSz = 0, signedAttrSz = 0;
00590 
00591     (void)signedAttr;    /* not used yet, just set */
00592     (void)signedAttrSz;
00593 
00594     if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0)
00595         return BAD_FUNC_ARG;
00596 
00597     idx = 0;
00598 
00599     /* Get the contentInfo sequence */
00600     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00601         return ASN_PARSE_E;
00602 
00603     /* Get the contentInfo contentType */
00604     if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
00605         return ASN_PARSE_E;
00606 
00607     if (contentType != SIGNED_DATA) {
00608         CYASSL_MSG("PKCS#7 input not of type SignedData");
00609         return PKCS7_OID_E;
00610     }
00611 
00612     /* get the ContentInfo content */
00613     if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
00614         return ASN_PARSE_E;
00615 
00616     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00617         return ASN_PARSE_E;
00618 
00619     /* Get the signedData sequence */
00620     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00621         return ASN_PARSE_E;
00622 
00623     /* Get the version */
00624     if (GetMyVersion(pkiMsg, &idx, &version) < 0)
00625         return ASN_PARSE_E;
00626 
00627     if (version != 1) {
00628         CYASSL_MSG("PKCS#7 signedData needs to be of version 1");
00629         return ASN_VERSION_E;
00630     }
00631 
00632     /* Get the set of DigestAlgorithmIdentifiers */
00633     if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00634         return ASN_PARSE_E;
00635 
00636     /* Skip the set. */
00637     idx += length;
00638 
00639     /* Get the inner ContentInfo sequence */
00640     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00641         return ASN_PARSE_E;
00642 
00643     /* Get the inner ContentInfo contentType */
00644     if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
00645         return ASN_PARSE_E;
00646 
00647     if (contentType != DATA) {
00648         CYASSL_MSG("PKCS#7 inner input not of type Data");
00649         return PKCS7_OID_E;
00650     }
00651 
00652     if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
00653         return ASN_PARSE_E;
00654 
00655     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00656         return ASN_PARSE_E;
00657 
00658     if (pkiMsg[idx++] != ASN_OCTET_STRING)
00659         return ASN_PARSE_E;
00660 
00661     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00662         return ASN_PARSE_E;
00663 
00664     /* Save the inner data as the content. */
00665     if (length > 0) {
00666         /* Local pointer for calculating hashes later */
00667         pkcs7->content = content = &pkiMsg[idx];
00668         pkcs7->contentSz = contentSz = length;
00669         idx += length;
00670     }
00671 
00672     /* Get the implicit[0] set of certificates */
00673     if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
00674         idx++;
00675         if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00676             return ASN_PARSE_E;
00677 
00678         if (length > 0) {
00679             /* At this point, idx is at the first certificate in
00680              * a set of certificates. There may be more than one,
00681              * or none, or they may be a PKCS 6 extended
00682              * certificate. We want to save the first cert if it
00683              * is X.509. */
00684 
00685             word32 certIdx = idx;
00686 
00687             if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
00688                 if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0)
00689                     return ASN_PARSE_E;
00690 
00691                 cert = &pkiMsg[idx];
00692                 certSz += (certIdx - idx);
00693             }
00694             PKCS7_InitWithCert(pkcs7, cert, certSz);
00695         }
00696         idx += length;
00697     }
00698 
00699     /* Get the implicit[1] set of crls */
00700     if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
00701         idx++;
00702         if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00703             return ASN_PARSE_E;
00704 
00705         /* Skip the set */
00706         idx += length;
00707     }
00708 
00709     /* Get the set of signerInfos */
00710     if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00711         return ASN_PARSE_E;
00712 
00713     if (length > 0) {
00714         RsaKey key;
00715         word32 scratch = 0;
00716         int plainSz = 0;
00717         byte digest[MAX_SEQ_SZ+MAX_ALGO_SZ+MAX_OCTET_STR_SZ+SHA_DIGEST_SIZE];
00718 
00719         /* Get the sequence of the first signerInfo */
00720         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00721             return ASN_PARSE_E;
00722 
00723         /* Get the version */
00724         if (GetMyVersion(pkiMsg, &idx, &version) < 0)
00725             return ASN_PARSE_E;
00726 
00727         if (version != 1) {
00728             CYASSL_MSG("PKCS#7 signerInfo needs to be of version 1");
00729             return ASN_VERSION_E;
00730         }
00731 
00732         /* Get the sequence of IssuerAndSerialNumber */
00733         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00734             return ASN_PARSE_E;
00735 
00736         /* Skip it */
00737         idx += length;
00738 
00739         /* Get the sequence of digestAlgorithm */
00740         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00741             return ASN_PARSE_E;
00742 
00743         /* Skip it */
00744         idx += length;
00745 
00746         /* Get the IMPLICIT[0] SET OF signedAttributes */
00747         if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
00748             idx++;
00749 
00750             if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00751                 return ASN_PARSE_E;
00752 
00753             /* save pointer and length */
00754             signedAttr = &pkiMsg[idx];
00755             signedAttrSz = length;
00756 
00757             idx += length;
00758         }
00759 
00760         /* Get the sequence of digestEncryptionAlgorithm */
00761         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00762             return ASN_PARSE_E;
00763 
00764         /* Skip it */
00765         idx += length;
00766 
00767         /* Get the signature */
00768         if (pkiMsg[idx] == ASN_OCTET_STRING) {
00769             idx++;
00770 
00771             if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
00772                 return ASN_PARSE_E;
00773 
00774             /* save pointer and length */
00775             sig = &pkiMsg[idx];
00776             sigSz = length;
00777 
00778             idx += length;
00779         }
00780 
00781         XMEMSET(digest, 0, sizeof(digest));
00782         pkcs7->content = content;
00783         pkcs7->contentSz = contentSz;
00784 
00785         ret = InitRsaKey(&key, NULL);
00786         if (ret != 0) return ret;
00787         if (RsaPublicKeyDecode(pkcs7->publicKey, &scratch, &key,
00788                                pkcs7->publicKeySz) < 0) {
00789             CYASSL_MSG("ASN RSA key decode error");
00790             return PUBLIC_KEY_E;
00791         }
00792         plainSz = RsaSSL_Verify(sig, sigSz, digest, sizeof(digest), &key);
00793         FreeRsaKey(&key);
00794         if (plainSz < 0)
00795             return plainSz;
00796     }
00797 
00798     return 0;
00799 }
00800 
00801 
00802 /* create ASN.1 fomatted RecipientInfo structure, returns sequence size */
00803 CYASSL_LOCAL int CreateRecipientInfo(const byte* cert, word32 certSz,
00804                                      int keyEncAlgo, int blockKeySz,
00805                                      RNG* rng, byte* contentKeyPlain,
00806                                      byte* contentKeyEnc,
00807                                      int* keyEncSz, byte* out, word32 outSz)
00808 {
00809     word32 idx = 0;
00810     int ret = 0, totalSz = 0;
00811     int verSz, issuerSz, snSz, keyEncAlgSz;
00812     int issuerSeqSz, recipSeqSz, issuerSerialSeqSz;
00813     int encKeyOctetStrSz;
00814 
00815     byte ver[MAX_VERSION_SZ];
00816     byte serial[MAX_SN_SZ];
00817     byte issuerSerialSeq[MAX_SEQ_SZ];
00818     byte recipSeq[MAX_SEQ_SZ];
00819     byte issuerSeq[MAX_SEQ_SZ];
00820     byte keyAlgArray[MAX_ALGO_SZ];
00821     byte encKeyOctetStr[MAX_OCTET_STR_SZ];
00822 
00823     RsaKey pubKey;
00824     DecodedCert decoded;
00825 
00826     InitDecodedCert(&decoded, (byte*)cert, certSz, 0);
00827     ret = ParseCert(&decoded, CA_TYPE, NO_VERIFY, 0);
00828     if (ret < 0) {
00829         FreeDecodedCert(&decoded);
00830         return ret;
00831     }
00832 
00833     /* version */
00834     verSz = SetMyVersion(0, ver, 0);
00835 
00836     /* IssuerAndSerialNumber */
00837     if (decoded.issuerRaw == NULL || decoded.issuerRawLen == 0) {
00838         CYASSL_MSG("DecodedCert lacks raw issuer pointer and length");
00839         FreeDecodedCert(&decoded);
00840         return -1;
00841     }
00842     issuerSz    = decoded.issuerRawLen;
00843     issuerSeqSz = SetSequence(issuerSz, issuerSeq);
00844 
00845     if (decoded.serial == NULL || decoded.serialSz == 0) {
00846         CYASSL_MSG("DecodedCert missing serial number");
00847         FreeDecodedCert(&decoded);
00848         return -1;
00849     }
00850     snSz = SetSerialNumber(decoded.serial, decoded.serialSz, serial);
00851 
00852     issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz,
00853                                     issuerSerialSeq);
00854 
00855     /* KeyEncryptionAlgorithmIdentifier, only support RSA now */
00856     if (keyEncAlgo != RSAk)
00857         return ALGO_ID_E;
00858 
00859     keyEncAlgSz = SetAlgoID(keyEncAlgo, keyAlgArray, keyType, 0);
00860     if (keyEncAlgSz == 0)
00861         return BAD_FUNC_ARG;
00862 
00863     /* EncryptedKey */
00864     ret = InitRsaKey(&pubKey, 0);
00865     if (ret != 0) return ret;
00866     if (RsaPublicKeyDecode(decoded.publicKey, &idx, &pubKey,
00867                            decoded.pubKeySize) < 0) {
00868         CYASSL_MSG("ASN RSA key decode error");
00869         return PUBLIC_KEY_E;
00870     }
00871 
00872     *keyEncSz = RsaPublicEncrypt(contentKeyPlain, blockKeySz, contentKeyEnc,
00873                                  MAX_ENCRYPTED_KEY_SZ, &pubKey, rng);
00874     FreeRsaKey(&pubKey);
00875     if (*keyEncSz < 0) {
00876         CYASSL_MSG("RSA Public Encrypt failed");
00877         return *keyEncSz;
00878     }
00879 
00880     encKeyOctetStrSz = SetOctetString(*keyEncSz, encKeyOctetStr);
00881 
00882     /* RecipientInfo */
00883     recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz +
00884                              issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz +
00885                              *keyEncSz, recipSeq);
00886 
00887     if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz +
00888         keyEncAlgSz + encKeyOctetStrSz + *keyEncSz > (int)outSz) {
00889         CYASSL_MSG("RecipientInfo output buffer too small");
00890         return BUFFER_E;
00891     }
00892 
00893     XMEMCPY(out + totalSz, recipSeq, recipSeqSz);
00894     totalSz += recipSeqSz;
00895     XMEMCPY(out + totalSz, ver, verSz);
00896     totalSz += verSz;
00897     XMEMCPY(out + totalSz, issuerSerialSeq, issuerSerialSeqSz);
00898     totalSz += issuerSerialSeqSz;
00899     XMEMCPY(out + totalSz, issuerSeq, issuerSeqSz);
00900     totalSz += issuerSeqSz;
00901     XMEMCPY(out + totalSz, decoded.issuerRaw, issuerSz);
00902     totalSz += issuerSz;
00903     XMEMCPY(out + totalSz, serial, snSz);
00904     totalSz += snSz;
00905     XMEMCPY(out + totalSz, keyAlgArray, keyEncAlgSz);
00906     totalSz += keyEncAlgSz;
00907     XMEMCPY(out + totalSz, encKeyOctetStr, encKeyOctetStrSz);
00908     totalSz += encKeyOctetStrSz;
00909     XMEMCPY(out + totalSz, contentKeyEnc, *keyEncSz);
00910     totalSz += *keyEncSz;
00911 
00912     FreeDecodedCert(&decoded);
00913 
00914     return totalSz;
00915 }
00916 
00917 
00918 /* build PKCS#7 envelopedData content type, return enveloped size */
00919 int PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
00920 {
00921     int i, ret = 0, idx = 0;
00922     int totalSz = 0, padSz = 0, desOutSz = 0;
00923 
00924     int contentInfoSeqSz, outerContentTypeSz, outerContentSz;
00925     byte contentInfoSeq[MAX_SEQ_SZ];
00926     byte outerContentType[MAX_ALGO_SZ];
00927     byte outerContent[MAX_SEQ_SZ];
00928 
00929     int envDataSeqSz, verSz;
00930     byte envDataSeq[MAX_SEQ_SZ];
00931     byte ver[MAX_VERSION_SZ];
00932 
00933     RNG rng;
00934     int contentKeyEncSz, blockKeySz;
00935     int dynamicFlag = 0;
00936     byte contentKeyPlain[MAX_CONTENT_KEY_LEN];
00937     byte contentKeyEnc[MAX_ENCRYPTED_KEY_SZ];
00938     byte* plain;
00939     byte* encryptedContent;
00940 
00941     int recipSz, recipSetSz;
00942     byte recip[MAX_RECIP_SZ];
00943     byte recipSet[MAX_SET_SZ];
00944 
00945     int encContentOctetSz, encContentSeqSz, contentTypeSz;
00946     int contentEncAlgoSz, ivOctetStringSz;
00947     byte encContentSeq[MAX_SEQ_SZ];
00948     byte contentType[MAX_ALGO_SZ];
00949     byte contentEncAlgo[MAX_ALGO_SZ];
00950     byte tmpIv[DES_BLOCK_SIZE];
00951     byte ivOctetString[MAX_OCTET_STR_SZ];
00952     byte encContentOctet[MAX_OCTET_STR_SZ];
00953 
00954     if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
00955         pkcs7->encryptOID == 0 || pkcs7->singleCert == NULL)
00956         return BAD_FUNC_ARG;
00957 
00958     if (output == NULL || outputSz == 0)
00959         return BAD_FUNC_ARG;
00960 
00961     /* PKCS#7 only supports DES, 3DES for now */
00962     switch (pkcs7->encryptOID) {
00963         case DESb:
00964             blockKeySz = DES_KEYLEN;
00965             break;
00966 
00967         case DES3b:
00968             blockKeySz = DES3_KEYLEN;
00969             break;
00970 
00971         default:
00972             CYASSL_MSG("Unsupported content cipher type");
00973             return ALGO_ID_E;
00974     };
00975 
00976     /* outer content type */
00977     outerContentTypeSz = SetContentType(ENVELOPED_DATA, outerContentType);
00978 
00979     /* version, defined as 0 in RFC 2315 */
00980     verSz = SetMyVersion(0, ver, 0);
00981 
00982     /* generate random content encryption key */
00983     InitRng(&rng);
00984     RNG_GenerateBlock(&rng, contentKeyPlain, blockKeySz);
00985 
00986     /* build RecipientInfo, only handle 1 for now */
00987     recipSz = CreateRecipientInfo(pkcs7->singleCert, pkcs7->singleCertSz, RSAk,
00988                                   blockKeySz, &rng, contentKeyPlain,
00989                                   contentKeyEnc, &contentKeyEncSz, recip,
00990                                   MAX_RECIP_SZ);
00991 
00992     if (recipSz < 0) {
00993         CYASSL_MSG("Failed to create RecipientInfo");
00994         return recipSz;
00995     }
00996     recipSetSz = SetSet(recipSz, recipSet);
00997 
00998     /* EncryptedContentInfo */
00999     contentTypeSz = SetContentType(pkcs7->contentOID, contentType);
01000     if (contentTypeSz == 0)
01001         return BAD_FUNC_ARG;
01002 
01003     /* allocate encrypted content buffer, pad if necessary, PKCS#7 padding */
01004     padSz = DES_BLOCK_SIZE - (pkcs7->contentSz % DES_BLOCK_SIZE);
01005     desOutSz = pkcs7->contentSz + padSz;
01006 
01007     if (padSz != 0) {
01008         plain = XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01009         if (plain == NULL) {
01010             return MEMORY_E;
01011         }
01012         XMEMCPY(plain, pkcs7->content, pkcs7->contentSz);
01013         dynamicFlag = 1;
01014 
01015         for (i = 0; i < padSz; i++) {
01016             plain[pkcs7->contentSz + i] = padSz;
01017         }
01018 
01019     } else {
01020         plain = pkcs7->content;
01021         desOutSz = pkcs7->contentSz;
01022     }
01023 
01024     encryptedContent = XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01025     if (encryptedContent == NULL) {
01026         if (dynamicFlag)
01027             XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01028         return MEMORY_E;
01029     }
01030 
01031     /* generate IV for block cipher */
01032     RNG_GenerateBlock(&rng, tmpIv, DES_BLOCK_SIZE);
01033 
01034     /* put together IV OCTET STRING */
01035     ivOctetStringSz = SetOctetString(DES_BLOCK_SIZE, ivOctetString);
01036 
01037     /* build up our ContentEncryptionAlgorithmIdentifier sequence,
01038      * adding (ivOctetStringSz + DES_BLOCK_SIZE) for IV OCTET STRING */
01039     contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
01040                                  blkType, ivOctetStringSz + DES_BLOCK_SIZE);
01041     if (contentEncAlgoSz == 0)
01042         return BAD_FUNC_ARG;
01043 
01044     /* encrypt content */
01045     if (pkcs7->encryptOID == DESb) {
01046         Des des;
01047 
01048         ret = Des_SetKey(&des, contentKeyPlain, tmpIv, DES_ENCRYPTION);
01049 
01050         if (ret == 0)
01051             Des_CbcEncrypt(&des, encryptedContent, plain, desOutSz);
01052 
01053         if (ret != 0) {
01054             XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01055             if (dynamicFlag)
01056                 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01057             return ret;
01058         }
01059     }
01060     else if (pkcs7->encryptOID == DES3b) {
01061         Des3 des3;
01062 
01063         ret = Des3_SetKey(&des3, contentKeyPlain, tmpIv, DES_ENCRYPTION);
01064 
01065         if (ret == 0)
01066             ret = Des3_CbcEncrypt(&des3, encryptedContent, plain, desOutSz);
01067 
01068         if (ret != 0) {
01069             XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01070             if (dynamicFlag)
01071                 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01072             return ret;
01073         }
01074     }
01075 
01076     encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0,
01077                                     desOutSz, encContentOctet);
01078 
01079     encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
01080                                   ivOctetStringSz + DES_BLOCK_SIZE +
01081                                   encContentOctetSz + desOutSz, encContentSeq);
01082 
01083     /* keep track of sizes for outer wrapper layering */
01084     totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz +
01085               contentEncAlgoSz + ivOctetStringSz + DES_BLOCK_SIZE +
01086               encContentOctetSz + desOutSz;
01087 
01088     /* EnvelopedData */
01089     envDataSeqSz = SetSequence(totalSz, envDataSeq);
01090     totalSz += envDataSeqSz;
01091 
01092     /* outer content */
01093     outerContentSz = SetExplicit(0, totalSz, outerContent);
01094     totalSz += outerContentTypeSz;
01095     totalSz += outerContentSz;
01096 
01097     /* ContentInfo */
01098     contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
01099     totalSz += contentInfoSeqSz;
01100 
01101     if (totalSz > (int)outputSz) {
01102         CYASSL_MSG("Pkcs7_encrypt output buffer too small");
01103         XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01104         if (dynamicFlag)
01105             XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01106         return BUFFER_E;
01107     }
01108 
01109     XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz);
01110     idx += contentInfoSeqSz;
01111     XMEMCPY(output + idx, outerContentType, outerContentTypeSz);
01112     idx += outerContentTypeSz;
01113     XMEMCPY(output + idx, outerContent, outerContentSz);
01114     idx += outerContentSz;
01115     XMEMCPY(output + idx, envDataSeq, envDataSeqSz);
01116     idx += envDataSeqSz;
01117     XMEMCPY(output + idx, ver, verSz);
01118     idx += verSz;
01119     XMEMCPY(output + idx, recipSet, recipSetSz);
01120     idx += recipSetSz;
01121     XMEMCPY(output + idx, recip, recipSz);
01122     idx += recipSz;
01123     XMEMCPY(output + idx, encContentSeq, encContentSeqSz);
01124     idx += encContentSeqSz;
01125     XMEMCPY(output + idx, contentType, contentTypeSz);
01126     idx += contentTypeSz;
01127     XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz);
01128     idx += contentEncAlgoSz;
01129     XMEMCPY(output + idx, ivOctetString, ivOctetStringSz);
01130     idx += ivOctetStringSz;
01131     XMEMCPY(output + idx, tmpIv, DES_BLOCK_SIZE);
01132     idx += DES_BLOCK_SIZE;
01133     XMEMCPY(output + idx, encContentOctet, encContentOctetSz);
01134     idx += encContentOctetSz;
01135     XMEMCPY(output + idx, encryptedContent, desOutSz);
01136     idx += desOutSz;
01137 
01138 #ifdef NO_RC4
01139     FreeRng(&rng);
01140 #endif
01141 
01142     XMEMSET(contentKeyPlain, 0, MAX_CONTENT_KEY_LEN);
01143     XMEMSET(contentKeyEnc,   0, MAX_ENCRYPTED_KEY_SZ);
01144 
01145     if (dynamicFlag)
01146         XFREE(plain, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
01147     XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01148 
01149     return idx;
01150 }
01151 
01152 /* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */
01153 CYASSL_API int PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
01154                                          word32 pkiMsgSz, byte* output,
01155                                          word32 outputSz)
01156 {
01157     int recipFound = 0;
01158     int ret, version, length;
01159     word32 savedIdx = 0, idx = 0;
01160     word32 contentType, encOID;
01161     byte   issuerHash[SHA_DIGEST_SIZE];
01162     mp_int serialNum;
01163 
01164     int encryptedKeySz, keySz;
01165     byte tmpIv[DES_BLOCK_SIZE];
01166     byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
01167     byte* decryptedKey = NULL;
01168 
01169     RsaKey privKey;
01170     int encryptedContentSz;
01171     byte padLen;
01172     byte* encryptedContent = NULL;
01173 
01174     if (pkcs7 == NULL || pkcs7->singleCert == NULL ||
01175         pkcs7->singleCertSz == 0 || pkcs7->privateKey == NULL ||
01176         pkcs7->privateKeySz == 0)
01177         return BAD_FUNC_ARG;
01178 
01179     if (pkiMsg == NULL || pkiMsgSz == 0 ||
01180         output == NULL || outputSz == 0)
01181         return BAD_FUNC_ARG;
01182 
01183     /* load private key */
01184     ret = InitRsaKey(&privKey, 0);
01185     if (ret != 0) return ret;
01186     ret = RsaPrivateKeyDecode(pkcs7->privateKey, &idx, &privKey,
01187                               pkcs7->privateKeySz);
01188     if (ret != 0) {
01189         CYASSL_MSG("Failed to decode RSA private key");
01190         return ret;
01191     }
01192 
01193     idx = 0;
01194 
01195     /* read past ContentInfo, verify type is envelopedData */
01196     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01197         return ASN_PARSE_E;
01198 
01199     if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
01200         return ASN_PARSE_E;
01201 
01202     if (contentType != ENVELOPED_DATA) {
01203         CYASSL_MSG("PKCS#7 input not of type EnvelopedData");
01204         return PKCS7_OID_E;
01205     }
01206 
01207     if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
01208         return ASN_PARSE_E;
01209 
01210     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01211         return ASN_PARSE_E;
01212 
01213     /* remove EnvelopedData and version */
01214     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01215         return ASN_PARSE_E;
01216 
01217     if (GetMyVersion(pkiMsg, &idx, &version) < 0)
01218         return ASN_PARSE_E;
01219 
01220     if (version != 0) {
01221         CYASSL_MSG("PKCS#7 envelopedData needs to be of version 0");
01222         return ASN_VERSION_E;
01223     }
01224 
01225     /* walk through RecipientInfo set, find correct recipient */
01226     if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01227         return ASN_PARSE_E;
01228 
01229     savedIdx = idx;
01230     recipFound = 0;
01231 
01232     /* when looking for next recipient, use first sequence and version to
01233      * indicate there is another, if not, move on */
01234     while(recipFound == 0) {
01235 
01236         /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to
01237          * last good saved one */
01238         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
01239             idx = savedIdx;
01240             break;
01241         }
01242 
01243         if (GetMyVersion(pkiMsg, &idx, &version) < 0) {
01244             idx = savedIdx;
01245             break;
01246         }
01247 
01248         if (version != 0)
01249             return ASN_VERSION_E;
01250 
01251         /* remove IssuerAndSerialNumber */
01252         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01253             return ASN_PARSE_E;
01254 
01255         if (GetNameHash(pkiMsg, &idx, issuerHash, pkiMsgSz) < 0)
01256             return ASN_PARSE_E;
01257 
01258         /* if we found correct recipient, issuer hashes will match */
01259         if (XMEMCMP(issuerHash, pkcs7->issuerHash, SHA_DIGEST_SIZE) == 0) {
01260             recipFound = 1;
01261         }
01262 
01263         if (GetInt(&serialNum, pkiMsg, &idx, pkiMsgSz) < 0)
01264             return ASN_PARSE_E;
01265         mp_clear(&serialNum);
01266 
01267         if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0)
01268             return ASN_PARSE_E;
01269 
01270         /* key encryption algorithm must be RSA for now */
01271         if (encOID != RSAk)
01272             return ALGO_ID_E;
01273 
01274         /* read encryptedKey */
01275         if (pkiMsg[idx++] != ASN_OCTET_STRING)
01276             return ASN_PARSE_E;
01277 
01278         if (GetLength(pkiMsg, &idx, &encryptedKeySz, pkiMsgSz) < 0)
01279             return ASN_PARSE_E;
01280 
01281         if (recipFound == 1)
01282             XMEMCPY(encryptedKey, &pkiMsg[idx], encryptedKeySz);
01283         idx += encryptedKeySz;
01284 
01285         /* update good idx */
01286         savedIdx = idx;
01287     }
01288 
01289     if (recipFound == 0) {
01290         CYASSL_MSG("No recipient found in envelopedData that matches input");
01291         return PKCS7_RECIP_E;
01292     }
01293 
01294     /* remove EncryptedContentInfo */
01295     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01296         return ASN_PARSE_E;
01297 
01298     if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
01299         return ASN_PARSE_E;
01300 
01301     if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0)
01302         return ASN_PARSE_E;
01303 
01304     /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
01305     if (pkiMsg[idx++] != ASN_OCTET_STRING)
01306         return ASN_PARSE_E;
01307 
01308     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01309         return ASN_PARSE_E;
01310 
01311     if (length != DES_BLOCK_SIZE) {
01312         CYASSL_MSG("Incorrect IV length, must be of DES_BLOCK_SIZE");
01313         return ASN_PARSE_E;
01314     }
01315 
01316     XMEMCPY(tmpIv, &pkiMsg[idx], length);
01317     idx += length;
01318 
01319     /* read encryptedContent, cont[0] */
01320     if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0))
01321         return ASN_PARSE_E;
01322 
01323     if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0)
01324         return ASN_PARSE_E;
01325 
01326     encryptedContent = XMALLOC(encryptedContentSz, NULL,
01327                                DYNAMIC_TYPE_TMP_BUFFER);
01328 
01329     XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
01330 
01331     /* decrypt encryptedKey */
01332     keySz = RsaPrivateDecryptInline(encryptedKey, encryptedKeySz,
01333                                     &decryptedKey, &privKey);
01334     FreeRsaKey(&privKey);
01335     if (keySz <= 0)
01336         return keySz;
01337 
01338     /* decrypt encryptedContent */
01339     if (encOID == DESb) {
01340         Des des;
01341         ret = Des_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION);
01342 
01343         if (ret == 0)
01344             Des_CbcDecrypt(&des, encryptedContent, encryptedContent,
01345                                  encryptedContentSz);
01346 
01347         if (ret != 0) {
01348             XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01349             return ret;
01350         }
01351     }
01352     else if (encOID == DES3b) {
01353         Des3 des;
01354         ret = Des3_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION);
01355         if (ret == 0)
01356             ret = Des3_CbcDecrypt(&des, encryptedContent, encryptedContent,
01357                                   encryptedContentSz);
01358 
01359         if (ret != 0) {
01360             XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01361             return ret;
01362         }
01363     } else {
01364         CYASSL_MSG("Unsupported content encryption OID type");
01365         return ALGO_ID_E;
01366     }
01367 
01368     padLen = encryptedContent[encryptedContentSz-1];
01369 
01370     /* copy plaintext to output */
01371     XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
01372 
01373     /* free memory, zero out keys */
01374     XMEMSET(encryptedKey, 0, MAX_ENCRYPTED_KEY_SZ);
01375     XMEMSET(encryptedContent, 0, encryptedContentSz);
01376     XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01377 
01378     return encryptedContentSz - padLen;
01379 }
01380 
01381 
01382 #else  /* HAVE_PKCS7 */
01383 
01384 
01385 #ifdef _MSC_VER
01386     /* 4206 warning for blank file */
01387     #pragma warning(disable: 4206)
01388 #endif
01389 
01390 
01391 #endif /* HAVE_PKCS7 */
01392