Xuyi Wang / wolfcrypt

Dependents:   OS

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-2017 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 #include <wolfcrypt/settings.h>
00028 
00029 #ifdef HAVE_PKCS7
00030 
00031 #include <wolfcrypt/pkcs7.h>
00032 #include <wolfcrypt/error-crypt.h>
00033 #include <wolfcrypt/logging.h>
00034 #include <wolfcrypt/hash.h>
00035 #ifndef NO_RSA
00036     #include <wolfcrypt/rsa.h>
00037 #endif
00038 #ifdef HAVE_ECC
00039     #include <wolfcrypt/ecc.h>
00040 #endif
00041 #ifdef NO_INLINE
00042     #include <wolfcrypt/misc.h>
00043 #else
00044     #define WOLFSSL_MISC_INCLUDED
00045     #include <wolfcrypt/src/misc.c>
00046 #endif
00047 
00048 
00049 /* direction for processing, encoding or decoding */
00050 typedef enum {
00051     WC_PKCS7_ENCODE,
00052     WC_PKCS7_DECODE
00053 } pkcs7Direction;
00054 
00055 #define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ + \
00056                              MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE)
00057 
00058 
00059 /* placed ASN.1 contentType OID into *output, return idx on success,
00060  * 0 upon failure */
00061 static int wc_SetContentType(int pkcs7TypeOID, byte* output)
00062 {
00063     /* PKCS#7 content types, RFC 2315, section 14 */
00064     const byte pkcs7[]              = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
00065                                                0x0D, 0x01, 0x07 };
00066     const byte data[]               = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
00067                                                0x0D, 0x01, 0x07, 0x01 };
00068     const byte signedData[]         = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
00069                                                0x0D, 0x01, 0x07, 0x02};
00070     const byte envelopedData[]      = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
00071                                                0x0D, 0x01, 0x07, 0x03 };
00072     const byte signedAndEnveloped[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
00073                                                0x0D, 0x01, 0x07, 0x04 };
00074     const byte digestedData[]       = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
00075                                                0x0D, 0x01, 0x07, 0x05 };
00076 
00077 #ifndef NO_PKCS7_ENCRYPTED_DATA
00078     const byte encryptedData[]      = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
00079                                                0x0D, 0x01, 0x07, 0x06 };
00080 #endif
00081 
00082     int idSz;
00083     int typeSz = 0, idx = 0;
00084     const byte* typeName = 0;
00085     byte ID_Length[MAX_LENGTH_SZ];
00086 
00087     switch (pkcs7TypeOID) {
00088         case PKCS7_MSG:
00089             typeSz = sizeof(pkcs7);
00090             typeName = pkcs7;
00091             break;
00092 
00093         case DATA:
00094             typeSz = sizeof(data);
00095             typeName = data;
00096             break;
00097 
00098         case SIGNED_DATA:
00099             typeSz = sizeof(signedData);
00100             typeName = signedData;
00101             break;
00102 
00103         case ENVELOPED_DATA:
00104             typeSz = sizeof(envelopedData);
00105             typeName = envelopedData;
00106             break;
00107 
00108         case SIGNED_AND_ENVELOPED_DATA:
00109             typeSz = sizeof(signedAndEnveloped);
00110             typeName = signedAndEnveloped;
00111             break;
00112 
00113         case DIGESTED_DATA:
00114             typeSz = sizeof(digestedData);
00115             typeName = digestedData;
00116             break;
00117 
00118 #ifndef NO_PKCS7_ENCRYPTED_DATA
00119         case ENCRYPTED_DATA:
00120             typeSz = sizeof(encryptedData);
00121             typeName = encryptedData;
00122             break;
00123 #endif
00124 
00125         default:
00126             WOLFSSL_MSG("Unknown PKCS#7 Type");
00127             return 0;
00128     };
00129 
00130     idSz  = SetLength(typeSz, ID_Length);
00131     output[idx++] = ASN_OBJECT_ID;
00132     XMEMCPY(output + idx, ID_Length, idSz);
00133     idx += idSz;
00134     XMEMCPY(output + idx, typeName, typeSz);
00135     idx += typeSz;
00136 
00137     return idx;
00138 }
00139 
00140 
00141 /* get ASN.1 contentType OID sum, return 0 on success, <0 on failure */
00142 static int wc_GetContentType(const byte* input, word32* inOutIdx, word32* oid,
00143                              word32 maxIdx)
00144 {
00145     WOLFSSL_ENTER("wc_GetContentType");
00146     if (GetObjectId(input, inOutIdx, oid, oidIgnoreType, maxIdx) < 0)
00147         return ASN_PARSE_E;
00148 
00149     return 0;
00150 }
00151 
00152 
00153 /* return block size for algorithm represented by oid, or <0 on error */
00154 static int wc_PKCS7_GetOIDBlockSize(int oid)
00155 {
00156     int blockSz;
00157 
00158     switch (oid) {
00159 #ifndef NO_AES
00160     #ifdef WOLFSSL_AES_128
00161         case AES128CBCb:
00162     #endif
00163     #ifdef WOLFSSL_AES_192
00164         case AES192CBCb:
00165     #endif
00166     #ifdef WOLFSSL_AES_256
00167         case AES256CBCb:
00168     #endif
00169             blockSz = AES_BLOCK_SIZE;
00170             break;
00171 #endif
00172 #ifndef NO_DES3
00173         case DESb:
00174         case DES3b:
00175             blockSz = DES_BLOCK_SIZE;
00176             break;
00177 #endif
00178         default:
00179             WOLFSSL_MSG("Unsupported content cipher type");
00180             return ALGO_ID_E;
00181     };
00182 
00183     return blockSz;
00184 }
00185 
00186 
00187 /* get key size for algorithm represented by oid, or <0 on error */
00188 static int wc_PKCS7_GetOIDKeySize(int oid)
00189 {
00190     int blockKeySz;
00191 
00192     switch (oid) {
00193 #ifndef NO_AES
00194     #ifdef WOLFSSL_AES_128
00195         case AES128CBCb:
00196         case AES128_WRAP:
00197             blockKeySz = 16;
00198             break;
00199     #endif
00200     #ifdef WOLFSSL_AES_192
00201         case AES192CBCb:
00202         case AES192_WRAP:
00203             blockKeySz = 24;
00204             break;
00205     #endif
00206     #ifdef WOLFSSL_AES_256
00207         case AES256CBCb:
00208         case AES256_WRAP:
00209             blockKeySz = 32;
00210             break;
00211     #endif
00212 #endif
00213 #ifndef NO_DES3
00214         case DESb:
00215             blockKeySz = DES_KEYLEN;
00216             break;
00217 
00218         case DES3b:
00219             blockKeySz = DES3_KEYLEN;
00220             break;
00221 #endif
00222         default:
00223             WOLFSSL_MSG("Unsupported content cipher type");
00224             return ALGO_ID_E;
00225     };
00226 
00227     return blockKeySz;
00228 }
00229 
00230 
00231 PKCS7* wc_PKCS7_New(void* heap, int devId)
00232 {
00233     PKCS7* pkcs7 = (PKCS7*)XMALLOC(sizeof(PKCS7), heap, DYNAMIC_TYPE_PKCS7);
00234     if (pkcs7) {
00235         XMEMSET(pkcs7, 0, sizeof(PKCS7));
00236         if (wc_PKCS7_Init(pkcs7, heap, devId) == 0) {
00237             pkcs7->isDynamic = 1;
00238         }
00239         else {
00240             XFREE(pkcs7, heap, DYNAMIC_TYPE_PKCS7);
00241             pkcs7 = NULL;
00242         }
00243     }
00244     return pkcs7;
00245 }
00246 
00247 /* This is to initialize a PKCS7 structure. It sets all values to 0 and can be
00248  * used to set the heap hint.
00249  *
00250  * pkcs7 PKCS7 structure to initialize
00251  * heap  memory heap hint for PKCS7 structure to use
00252  * devId currently not used but a place holder for async operations
00253  *
00254  * returns 0 on success or a negative value for failure
00255  */
00256 int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId)
00257 {
00258     WOLFSSL_ENTER("wc_PKCS7_Init");
00259 
00260     if (pkcs7 == NULL) {
00261         return BAD_FUNC_ARG;
00262     }
00263 
00264     XMEMSET(pkcs7, 0, sizeof(PKCS7));
00265 #ifdef WOLFSSL_HEAP_TEST
00266     pkcs7->heap = (void*)WOLFSSL_HEAP_TEST;
00267 #else
00268     pkcs7->heap = heap;
00269 #endif
00270     pkcs7->devId = devId;
00271 
00272     return 0;
00273 }
00274 
00275 
00276 /* init PKCS7 struct with recipient cert, decode into DecodedCert
00277  * NOTE: keeps previously set pkcs7 heap hint, devId and isDynamic */
00278 int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz)
00279 {
00280     int ret = 0;
00281     void* heap;
00282     int devId;
00283     word16 isDynamic;
00284 
00285     if (pkcs7 == NULL || (cert == NULL && certSz != 0)) {
00286         return BAD_FUNC_ARG;
00287     }
00288 
00289     heap = pkcs7->heap;
00290     devId = pkcs7->devId;
00291     isDynamic = pkcs7->isDynamic;
00292     ret = wc_PKCS7_Init(pkcs7, heap, devId);
00293     if (ret != 0)
00294         return ret;
00295     pkcs7->isDynamic = isDynamic;
00296 
00297     if (cert != NULL && certSz > 0) {
00298 #ifdef WOLFSSL_SMALL_STACK
00299         DecodedCert* dCert;
00300 
00301         dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap,
00302                                                        DYNAMIC_TYPE_DCERT);
00303         if (dCert == NULL)
00304             return MEMORY_E;
00305 #else
00306         DecodedCert stack_dCert;
00307         DecodedCert* dCert = &stack_dCert;
00308 #endif
00309 
00310         pkcs7->singleCert = cert;
00311         pkcs7->singleCertSz = certSz;
00312         InitDecodedCert(dCert, cert, certSz, pkcs7->heap);
00313 
00314         ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0);
00315         if (ret < 0) {
00316             FreeDecodedCert(dCert);
00317 #ifdef WOLFSSL_SMALL_STACK
00318             XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
00319 #endif
00320             return ret;
00321         }
00322 
00323         XMEMCPY(pkcs7->publicKey, dCert->publicKey, dCert->pubKeySize);
00324         pkcs7->publicKeySz = dCert->pubKeySize;
00325         pkcs7->publicKeyOID = dCert->keyOID;
00326         XMEMCPY(pkcs7->issuerHash, dCert->issuerHash, KEYID_SIZE);
00327         pkcs7->issuer = dCert->issuerRaw;
00328         pkcs7->issuerSz = dCert->issuerRawLen;
00329         XMEMCPY(pkcs7->issuerSn, dCert->serial, dCert->serialSz);
00330         pkcs7->issuerSnSz = dCert->serialSz;
00331         FreeDecodedCert(dCert);
00332 
00333 #ifdef WOLFSSL_SMALL_STACK
00334         XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
00335 #endif
00336     }
00337 
00338     return ret;
00339 }
00340 
00341 
00342 /* free linked list of PKCS7DecodedAttrib structs */
00343 static void wc_PKCS7_FreeDecodedAttrib(PKCS7DecodedAttrib* attrib, void* heap)
00344 {
00345     PKCS7DecodedAttrib* current;
00346 
00347     if (attrib == NULL) {
00348         return;
00349     }
00350 
00351     current = attrib;
00352     while (current != NULL) {
00353         PKCS7DecodedAttrib* next = current->next;
00354         if (current->oid != NULL)  {
00355             XFREE(current->oid, heap, DYNAMIC_TYPE_PKCS7);
00356         }
00357         if (current->value != NULL) {
00358             XFREE(current->value, heap, DYNAMIC_TYPE_PKCS7);
00359         }
00360         XFREE(current, heap, DYNAMIC_TYPE_PKCS7);
00361         current = next;
00362     }
00363 
00364     (void)heap;
00365 }
00366 
00367 
00368 /* releases any memory allocated by a PKCS7 initializer */
00369 void wc_PKCS7_Free(PKCS7* pkcs7)
00370 {
00371     if (pkcs7 == NULL)
00372         return;
00373 
00374     wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap);
00375 
00376 #ifdef ASN_BER_TO_DER
00377     if (pkcs7->der != NULL)
00378         XFREE(pkcs7->der, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
00379 #endif
00380 
00381     if (pkcs7->isDynamic) {
00382         pkcs7->isDynamic = 0;
00383         XFREE(pkcs7, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
00384     }
00385 }
00386 
00387 
00388 /* helper function for parsing through attributes and finding a specific one.
00389  * returns PKCS7DecodedAttrib pointer on success */
00390 static PKCS7DecodedAttrib* findAttrib(PKCS7* pkcs7, const byte* oid, word32 oidSz)
00391 {
00392     PKCS7DecodedAttrib* list;
00393 
00394     if (pkcs7 == NULL || oid == NULL) {
00395         return NULL;
00396     }
00397 
00398     /* search attributes for pkiStatus */
00399     list = pkcs7->decodedAttrib;
00400     while (list != NULL) {
00401         word32 sz  = oidSz;
00402         word32 idx = 0;
00403         int    length = 0;
00404 
00405         if (list->oid[idx++] != ASN_OBJECT_ID) {
00406             WOLFSSL_MSG("Bad attribute ASN1 syntax");
00407             return NULL;
00408         }
00409 
00410         if (GetLength(list->oid, &idx, &length, list->oidSz) < 0) {
00411             WOLFSSL_MSG("Bad attribute length");
00412             return NULL;
00413         }
00414 
00415         sz = (sz < (word32)length)? sz : (word32)length;
00416         if (XMEMCMP(oid, list->oid + idx, sz) == 0) {
00417             return list;
00418         }
00419         list = list->next;
00420     }
00421     return NULL;
00422 }
00423 
00424 
00425 /* Searches through decoded attributes and returns the value for the first one
00426  * matching the oid passed in. Note that this value includes the leading ASN1
00427  * syntax. So for a printable string of "3" this would be something like
00428  *
00429  * 0x13, 0x01, 0x33
00430  *  ID   SIZE  "3"
00431  *
00432  * pkcs7  structure to get value from
00433  * oid    OID value to search for with attributes
00434  * oidSz  size of oid buffer
00435  * out    buffer to hold result
00436  * outSz  size of out buffer (if out is NULL this is set to needed size and
00437           LENGTH_ONLY_E is returned)
00438  *
00439  * returns size of value on success
00440  */
00441 int wc_PKCS7_GetAttributeValue(PKCS7* pkcs7, const byte* oid, word32 oidSz,
00442         byte* out, word32* outSz)
00443 {
00444     PKCS7DecodedAttrib* attrib;
00445 
00446     if (pkcs7 == NULL || oid == NULL || outSz == NULL) {
00447         return BAD_FUNC_ARG;
00448     }
00449 
00450     attrib = findAttrib(pkcs7, oid, oidSz);
00451     if (attrib == NULL) {
00452         return ASN_PARSE_E;
00453     }
00454 
00455     if (out == NULL) {
00456         *outSz = attrib->valueSz;
00457         return LENGTH_ONLY_E;
00458     }
00459 
00460     if (*outSz < attrib->valueSz) {
00461         return BUFFER_E;
00462     }
00463 
00464     XMEMCPY(out, attrib->value, attrib->valueSz);
00465     return attrib->valueSz;
00466 }
00467 
00468 
00469 /* build PKCS#7 data content type */
00470 int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz)
00471 {
00472     static const byte oid[] =
00473         { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
00474                          0x07, 0x01 };
00475     byte seq[MAX_SEQ_SZ];
00476     byte octetStr[MAX_OCTET_STR_SZ];
00477     word32 seqSz;
00478     word32 octetStrSz;
00479     word32 oidSz = (word32)sizeof(oid);
00480     int idx = 0;
00481 
00482     if (pkcs7 == NULL || output == NULL) {
00483         return BAD_FUNC_ARG;
00484     }
00485 
00486     octetStrSz = SetOctetString(pkcs7->contentSz, octetStr);
00487     seqSz = SetSequence(pkcs7->contentSz + octetStrSz + oidSz, seq);
00488 
00489     if (outputSz < pkcs7->contentSz + octetStrSz + oidSz + seqSz)
00490         return BUFFER_E;
00491 
00492     XMEMCPY(output, seq, seqSz);
00493     idx += seqSz;
00494     XMEMCPY(output + idx, oid, oidSz);
00495     idx += oidSz;
00496     XMEMCPY(output + idx, octetStr, octetStrSz);
00497     idx += octetStrSz;
00498     XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
00499     idx += pkcs7->contentSz;
00500 
00501     return idx;
00502 }
00503 
00504 
00505 typedef struct EncodedAttrib {
00506     byte valueSeq[MAX_SEQ_SZ];
00507         const byte* oid;
00508         byte valueSet[MAX_SET_SZ];
00509         const byte* value;
00510     word32 valueSeqSz, oidSz, idSz, valueSetSz, valueSz, totalSz;
00511 } EncodedAttrib;
00512 
00513 
00514 typedef struct ESD {
00515     wc_HashAlg  hash;
00516     enum wc_HashType hashType;
00517     byte contentDigest[WC_MAX_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */
00518     byte contentAttribsDigest[WC_MAX_DIGEST_SIZE];
00519     byte encContentDigest[MAX_ENCRYPTED_KEY_SZ];
00520 
00521     byte outerSeq[MAX_SEQ_SZ];
00522         byte outerContent[MAX_EXP_SZ];
00523             byte innerSeq[MAX_SEQ_SZ];
00524                 byte version[MAX_VERSION_SZ];
00525                 byte digAlgoIdSet[MAX_SET_SZ];
00526                     byte singleDigAlgoId[MAX_ALGO_SZ];
00527 
00528                 byte contentInfoSeq[MAX_SEQ_SZ];
00529                     byte innerContSeq[MAX_EXP_SZ];
00530                         byte innerOctets[MAX_OCTET_STR_SZ];
00531 
00532                 byte certsSet[MAX_SET_SZ];
00533 
00534                 byte signerInfoSet[MAX_SET_SZ];
00535                     byte signerInfoSeq[MAX_SEQ_SZ];
00536                         byte signerVersion[MAX_VERSION_SZ];
00537                         byte issuerSnSeq[MAX_SEQ_SZ];
00538                             byte issuerName[MAX_SEQ_SZ];
00539                             byte issuerSn[MAX_SN_SZ];
00540                         byte signerDigAlgoId[MAX_ALGO_SZ];
00541                         byte digEncAlgoId[MAX_ALGO_SZ];
00542                         byte signedAttribSet[MAX_SET_SZ];
00543                             EncodedAttrib signedAttribs[6];
00544                         byte signerDigest[MAX_OCTET_STR_SZ];
00545     word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz;
00546     word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz,
00547            singleDigAlgoIdSz, certsSetSz;
00548     word32 signerInfoSetSz, signerInfoSeqSz, signerVersionSz,
00549            issuerSnSeqSz, issuerNameSz, issuerSnSz,
00550            signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz;
00551     word32 encContentDigestSz, signedAttribsSz, signedAttribsCount,
00552            signedAttribSetSz;
00553 } ESD;
00554 
00555 
00556 static int EncodeAttributes(EncodedAttrib* ea, int eaSz,
00557                                             PKCS7Attrib* attribs, int attribsSz)
00558 {
00559     int i;
00560     int maxSz = min(eaSz, attribsSz);
00561     int allAttribsSz = 0;
00562 
00563     for (i = 0; i < maxSz; i++)
00564     {
00565         int attribSz = 0;
00566 
00567         ea[i].value = attribs[i].value;
00568         ea[i].valueSz = attribs[i].valueSz;
00569         attribSz += ea[i].valueSz;
00570         ea[i].valueSetSz = SetSet(attribSz, ea[i].valueSet);
00571         attribSz += ea[i].valueSetSz;
00572         ea[i].oid = attribs[i].oid;
00573         ea[i].oidSz = attribs[i].oidSz;
00574         attribSz += ea[i].oidSz;
00575         ea[i].valueSeqSz = SetSequence(attribSz, ea[i].valueSeq);
00576         attribSz += ea[i].valueSeqSz;
00577         ea[i].totalSz = attribSz;
00578 
00579         allAttribsSz += attribSz;
00580     }
00581     return allAttribsSz;
00582 }
00583 
00584 
00585 static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz)
00586 {
00587     int i, idx;
00588 
00589     idx = 0;
00590     for (i = 0; i < eaSz; i++) {
00591         XMEMCPY(output + idx, ea[i].valueSeq, ea[i].valueSeqSz);
00592         idx += ea[i].valueSeqSz;
00593         XMEMCPY(output + idx, ea[i].oid, ea[i].oidSz);
00594         idx += ea[i].oidSz;
00595         XMEMCPY(output + idx, ea[i].valueSet, ea[i].valueSetSz);
00596         idx += ea[i].valueSetSz;
00597         XMEMCPY(output + idx, ea[i].value, ea[i].valueSz);
00598         idx += ea[i].valueSz;
00599     }
00600     return 0;
00601 }
00602 
00603 
00604 #ifndef NO_RSA
00605 
00606 /* returns size of signature put into out, negative on error */
00607 static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd)
00608 {
00609     int ret;
00610     word32 idx;
00611 #ifdef WOLFSSL_SMALL_STACK
00612     RsaKey* privKey;
00613 #else
00614     RsaKey  stack_privKey;
00615     RsaKey* privKey = &stack_privKey;
00616 #endif
00617 
00618     if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) {
00619         return BAD_FUNC_ARG;
00620     }
00621 
00622 #ifdef WOLFSSL_SMALL_STACK
00623     privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap,
00624         DYNAMIC_TYPE_TMP_BUFFER);
00625     if (privKey == NULL)
00626         return MEMORY_E;
00627 #endif
00628 
00629     ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, pkcs7->devId);
00630     if (ret == 0) {
00631         if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) {
00632             idx = 0;
00633             ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey,
00634                                          pkcs7->privateKeySz);
00635         }
00636         else if (pkcs7->devId == INVALID_DEVID) {
00637             ret = BAD_FUNC_ARG;
00638         }
00639     }
00640     if (ret == 0) {
00641         ret = wc_RsaSSL_Sign(in, inSz, esd->encContentDigest,
00642                              sizeof(esd->encContentDigest),
00643                              privKey, pkcs7->rng);
00644     }
00645 
00646     wc_FreeRsaKey(privKey);
00647 #ifdef WOLFSSL_SMALL_STACK
00648     XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
00649 #endif
00650 
00651     return ret;
00652 }
00653 
00654 #endif /* NO_RSA */
00655 
00656 
00657 #ifdef HAVE_ECC
00658 
00659 /* returns size of signature put into out, negative on error */
00660 static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd)
00661 {
00662     int ret;
00663     word32 outSz, idx;
00664 #ifdef WOLFSSL_SMALL_STACK
00665     ecc_key* privKey;
00666 #else
00667     ecc_key  stack_privKey;
00668     ecc_key* privKey = &stack_privKey;
00669 #endif
00670 
00671     if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) {
00672         return BAD_FUNC_ARG;
00673     }
00674 
00675 #ifdef WOLFSSL_SMALL_STACK
00676     privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
00677         DYNAMIC_TYPE_TMP_BUFFER);
00678     if (privKey == NULL)
00679         return MEMORY_E;
00680 #endif
00681 
00682     ret = wc_ecc_init_ex(privKey, pkcs7->heap, pkcs7->devId);
00683     if (ret == 0) {
00684         if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) {
00685             idx = 0;
00686             ret = wc_EccPrivateKeyDecode(pkcs7->privateKey, &idx, privKey,
00687                                          pkcs7->privateKeySz);
00688         }
00689         else if (pkcs7->devId == INVALID_DEVID) {
00690             ret = BAD_FUNC_ARG;
00691         }
00692     }
00693     if (ret == 0) {
00694         outSz = sizeof(esd->encContentDigest);
00695         ret = wc_ecc_sign_hash(in, inSz, esd->encContentDigest,
00696                                &outSz, pkcs7->rng, privKey);
00697         if (ret == 0)
00698             ret = (int)outSz;
00699     }
00700 
00701     wc_ecc_free(privKey);
00702 #ifdef WOLFSSL_SMALL_STACK
00703     XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
00704 #endif
00705 
00706     return ret;
00707 }
00708 
00709 #endif /* HAVE_ECC */
00710 
00711 
00712 /* builds up SignedData signed attributes, including default ones.
00713  *
00714  * pkcs7 - pointer to initialized PKCS7 structure
00715  * esd   - pointer to initialized ESD structure, used for output
00716  *
00717  * return 0 on success, negative on error */
00718 static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd,
00719                     byte* contentTypeOid, word32 contentTypeOidSz,
00720                     byte* contentType, word32 contentTypeSz,
00721                     byte* messageDigestOid, word32 messageDigestOidSz)
00722 {
00723     int hashSz;
00724 
00725     PKCS7Attrib cannedAttribs[2];
00726     word32 cannedAttribsCount;
00727 
00728     if (pkcs7 == NULL || esd == NULL || contentTypeOid == NULL ||
00729         contentType == NULL || messageDigestOid == NULL)
00730         return BAD_FUNC_ARG;
00731 
00732     hashSz = wc_HashGetDigestSize(esd->hashType);
00733     if (hashSz < 0)
00734         return hashSz;
00735 
00736     cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib);
00737 
00738     cannedAttribs[0].oid     = contentTypeOid;
00739     cannedAttribs[0].oidSz   = contentTypeOidSz;
00740     cannedAttribs[0].value   = contentType;
00741     cannedAttribs[0].valueSz = contentTypeSz;
00742     cannedAttribs[1].oid     = messageDigestOid;
00743     cannedAttribs[1].oidSz   = messageDigestOidSz;
00744     cannedAttribs[1].value   = esd->contentDigest;
00745     cannedAttribs[1].valueSz = hashSz + 2;  /* ASN.1 heading */
00746 
00747     esd->signedAttribsCount += cannedAttribsCount;
00748     esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2,
00749                                          cannedAttribs, cannedAttribsCount);
00750 
00751     esd->signedAttribsCount += pkcs7->signedAttribsSz;
00752     esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4,
00753                               pkcs7->signedAttribs, pkcs7->signedAttribsSz);
00754 
00755     return 0;
00756 }
00757 
00758 
00759 /* gets correct encryption algo ID for SignedData, either CTC_<hash>wRSA or
00760  * CTC_<hash>wECDSA, from pkcs7->publicKeyOID and pkcs7->hashOID.
00761  *
00762  * pkcs7          - pointer to PKCS7 structure
00763  * digEncAlgoId   - [OUT] output int to store correct algo ID in
00764  * digEncAlgoType - [OUT] output for algo ID type
00765  *
00766  * return 0 on success, negative on error */
00767 static int wc_PKCS7_SignedDataGetEncAlgoId(PKCS7* pkcs7, int* digEncAlgoId,
00768                                            int* digEncAlgoType)
00769 {
00770     int algoId   = 0;
00771     int algoType = 0;
00772 
00773     if (pkcs7 == NULL || digEncAlgoId == NULL || digEncAlgoType == NULL)
00774         return BAD_FUNC_ARG;
00775 
00776     if (pkcs7->publicKeyOID == RSAk) {
00777 
00778         algoType = oidSigType;
00779 
00780         switch (pkcs7->hashOID) {
00781         #ifndef NO_SHA
00782             case SHAh:
00783                 algoId = CTC_SHAwRSA;
00784                 break;
00785         #endif
00786         #ifdef WOLFSSL_SHA224
00787             case SHA224h:
00788                 algoId = CTC_SHA224wRSA;
00789                 break;
00790         #endif
00791         #ifndef NO_SHA256
00792             case SHA256h:
00793                 algoId = CTC_SHA256wRSA;
00794                 break;
00795         #endif
00796         #ifdef WOLFSSL_SHA384
00797             case SHA384h:
00798                 algoId = CTC_SHA384wRSA;
00799                 break;
00800         #endif
00801         #ifdef WOLFSSL_SHA512
00802             case SHA512h:
00803                 algoId = CTC_SHA512wRSA;
00804                 break;
00805         #endif
00806         }
00807 
00808     }
00809 #ifdef HAVE_ECC
00810     else if (pkcs7->publicKeyOID == ECDSAk) {
00811 
00812         algoType = oidSigType;
00813 
00814         switch (pkcs7->hashOID) {
00815         #ifndef NO_SHA
00816             case SHAh:
00817                 algoId = CTC_SHAwECDSA;
00818                 break;
00819         #endif
00820         #ifdef WOLFSSL_SHA224
00821             case SHA224h:
00822                 algoId = CTC_SHA224wECDSA;
00823                 break;
00824         #endif
00825         #ifndef NO_SHA256
00826             case SHA256h:
00827                 algoId = CTC_SHA256wECDSA;
00828                 break;
00829         #endif
00830         #ifdef WOLFSSL_SHA384
00831             case SHA384h:
00832                 algoId = CTC_SHA384wECDSA;
00833                 break;
00834         #endif
00835         #ifdef WOLFSSL_SHA512
00836             case SHA512h:
00837                 algoId = CTC_SHA512wECDSA;
00838                 break;
00839         #endif
00840         }
00841     }
00842 #endif /* HAVE_ECC */
00843 
00844     if (algoId == 0) {
00845         WOLFSSL_MSG("Invalid signature algorithm type");
00846         return BAD_FUNC_ARG;
00847     }
00848 
00849     *digEncAlgoId = algoId;
00850     *digEncAlgoType = algoType;
00851 
00852     return 0;
00853 }
00854 
00855 
00856 /* build SignedData DigestInfo for use with PKCS#7/RSA
00857  *
00858  * pkcs7 - pointer to initialized PKCS7 struct
00859  * flatSignedAttribs - flattened, signed attributes
00860  * flatSignedAttrbsSz - size of flatSignedAttribs, octets
00861  * esd - pointer to initialized ESD struct
00862  * digestInfo - [OUT] output array for DigestInfo
00863  * digestInfoSz - [IN/OUT] - input size of array, size of digestInfo
00864  *
00865  * return 0 on success, negative on error */
00866 static int wc_PKCS7_BuildDigestInfo(PKCS7* pkcs7, byte* flatSignedAttribs,
00867                                     word32 flatSignedAttribsSz, ESD* esd,
00868                                     byte* digestInfo, word32* digestInfoSz)
00869 {
00870     int ret, hashSz, digIdx = 0;
00871     byte digestInfoSeq[MAX_SEQ_SZ];
00872     byte digestStr[MAX_OCTET_STR_SZ];
00873     byte attribSet[MAX_SET_SZ];
00874     byte algoId[MAX_ALGO_SZ];
00875     word32 digestInfoSeqSz, digestStrSz, algoIdSz;
00876     word32 attribSetSz;
00877 
00878     if (pkcs7 == NULL || esd == NULL || digestInfo == NULL ||
00879         digestInfoSz == NULL) {
00880         return BAD_FUNC_ARG;
00881     }
00882 
00883     hashSz = wc_HashGetDigestSize(esd->hashType);
00884     if (hashSz < 0)
00885         return hashSz;
00886 
00887     if (pkcs7->signedAttribsSz != 0) {
00888 
00889         if (flatSignedAttribs == NULL)
00890             return BAD_FUNC_ARG;
00891 
00892         attribSetSz = SetSet(flatSignedAttribsSz, attribSet);
00893 
00894         ret = wc_HashInit(&esd->hash, esd->hashType);
00895         if (ret < 0)
00896             return ret;
00897 
00898         ret = wc_HashUpdate(&esd->hash, esd->hashType,
00899                             attribSet, attribSetSz);
00900         if (ret < 0)
00901             return ret;
00902 
00903         ret = wc_HashUpdate(&esd->hash, esd->hashType,
00904                             flatSignedAttribs, flatSignedAttribsSz);
00905         if (ret < 0)
00906             return ret;
00907 
00908         ret = wc_HashFinal(&esd->hash, esd->hashType,
00909                            esd->contentAttribsDigest);
00910         if (ret < 0)
00911             return ret;
00912 
00913     } else {
00914         /* when no attrs, digest is contentDigest without tag and length */
00915         XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, hashSz);
00916     }
00917 
00918     /* set algoID, with NULL attributes */
00919     algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0);
00920 
00921     digestStrSz = SetOctetString(hashSz, digestStr);
00922     digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz,
00923                                   digestInfoSeq);
00924 
00925     if (*digestInfoSz < (digestInfoSeqSz + algoIdSz + digestStrSz + hashSz)) {
00926         return BUFFER_E;
00927     }
00928 
00929     XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
00930     digIdx += digestInfoSeqSz;
00931     XMEMCPY(digestInfo + digIdx, algoId, algoIdSz);
00932     digIdx += algoIdSz;
00933     XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
00934     digIdx += digestStrSz;
00935     XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, hashSz);
00936     digIdx += hashSz;
00937 
00938     *digestInfoSz = digIdx;
00939 
00940     return 0;
00941 }
00942 
00943 
00944 /* build SignedData signature over DigestInfo or content digest
00945  *
00946  * pkcs7 - pointer to initizlied PKCS7 struct
00947  * flatSignedAttribs - flattened, signed attributes
00948  * flatSignedAttribsSz - size of flatSignedAttribs, octets
00949  * esd - pointer to initialized ESD struct
00950  *
00951  * returns length of signature on success, negative on error */
00952 static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7,
00953                                              byte* flatSignedAttribs,
00954                                              word32 flatSignedAttribsSz,
00955                                              ESD* esd)
00956 {
00957     int ret;
00958 #ifdef HAVE_ECC
00959     int hashSz;
00960 #endif
00961     word32 digestInfoSz = MAX_PKCS7_DIGEST_SZ;
00962 #ifdef WOLFSSL_SMALL_STACK
00963     byte* digestInfo;
00964 #else
00965     byte digestInfo[MAX_PKCS7_DIGEST_SZ];
00966 #endif
00967 
00968     if (pkcs7 == NULL || esd == NULL)
00969         return BAD_FUNC_ARG;
00970 
00971 #ifdef WOLFSSL_SMALL_STACK
00972     digestInfo = (byte*)XMALLOC(digestInfoSz, pkcs7->heap,
00973         DYNAMIC_TYPE_TMP_BUFFER);
00974     if (digestInfo == NULL) {
00975         return MEMORY_E;
00976     }
00977 #endif
00978 
00979     ret = wc_PKCS7_BuildDigestInfo(pkcs7, flatSignedAttribs,
00980                                    flatSignedAttribsSz, esd, digestInfo,
00981                                    &digestInfoSz);
00982     if (ret < 0) {
00983 #ifdef WOLFSSL_SMALL_STACK
00984         XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
00985 #endif
00986         return ret;
00987     }
00988 
00989     /* sign digestInfo */
00990     switch (pkcs7->publicKeyOID) {
00991 
00992 #ifndef NO_RSA
00993         case RSAk:
00994             ret = wc_PKCS7_RsaSign(pkcs7, digestInfo, digestInfoSz, esd);
00995             break;
00996 #endif
00997 
00998 #ifdef HAVE_ECC
00999         case ECDSAk:
01000             /* CMS with ECDSA does not sign DigestInfo structure
01001              * like PKCS#7 with RSA does */
01002             hashSz = wc_HashGetDigestSize(esd->hashType);
01003             if (hashSz < 0) {
01004             #ifdef WOLFSSL_SMALL_STACK
01005                 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01006             #endif
01007                 return hashSz;
01008             }
01009 
01010             ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest,
01011                                      hashSz, esd);
01012             break;
01013 #endif
01014 
01015         default:
01016             WOLFSSL_MSG("Unsupported public key type");
01017             ret = BAD_FUNC_ARG;
01018     }
01019 
01020 #ifdef WOLFSSL_SMALL_STACK
01021     XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01022 #endif
01023 
01024     if (ret >= 0) {
01025         esd->encContentDigestSz = (word32)ret;
01026     }
01027 
01028     return ret;
01029 }
01030 
01031 /* build PKCS#7 signedData content type */
01032 int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz)
01033 {
01034     static const byte outerOid[] =
01035         { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
01036                          0x07, 0x02 };
01037     static const byte innerOid[] =
01038         { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
01039                          0x07, 0x01 };
01040 
01041     byte contentTypeOid[] =
01042             { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01,
01043                              0x09, 0x03 };
01044     byte contentType[] =
01045             { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
01046                              0x07, 0x01 };
01047     byte messageDigestOid[] =
01048             { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
01049                              0x09, 0x04 };
01050 
01051 #ifdef WOLFSSL_SMALL_STACK
01052     ESD* esd = NULL;
01053 #else
01054     ESD stack_esd;
01055     ESD* esd = &stack_esd;
01056 #endif
01057 
01058     word32 signerInfoSz = 0;
01059     word32 totalSz = 0;
01060     int idx = 0, ret = 0;
01061     int digEncAlgoId, digEncAlgoType, hashSz;
01062     byte* flatSignedAttribs = NULL;
01063     word32 flatSignedAttribsSz = 0;
01064     word32 innerOidSz = sizeof(innerOid);
01065     word32 outerOidSz = sizeof(outerOid);
01066 
01067     if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
01068         pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 ||
01069         pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0 ||
01070         output == NULL || outputSz == 0) {
01071         return BAD_FUNC_ARG;
01072     }
01073 
01074 #ifdef WOLFSSL_SMALL_STACK
01075     esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01076     if (esd == NULL)
01077         return MEMORY_E;
01078 #endif
01079 
01080     XMEMSET(esd, 0, sizeof(ESD));
01081 
01082     esd->hashType = wc_OidGetHash(pkcs7->hashOID);
01083     ret = wc_HashGetDigestSize(esd->hashType);
01084     if (ret < 0) {
01085 #ifdef WOLFSSL_SMALL_STACK
01086         XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01087 #endif
01088         return ret;
01089     }
01090     hashSz = ret;
01091 
01092     ret = wc_HashInit(&esd->hash, esd->hashType);
01093     if (ret != 0) {
01094 #ifdef WOLFSSL_SMALL_STACK
01095         XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01096 #endif
01097         return ret;
01098     }
01099 
01100     if (pkcs7->contentSz != 0)
01101     {
01102         ret = wc_HashUpdate(&esd->hash, esd->hashType,
01103                             pkcs7->content, pkcs7->contentSz);
01104         if (ret < 0) {
01105 #ifdef WOLFSSL_SMALL_STACK
01106             XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01107 #endif
01108         return ret;
01109         }
01110         esd->contentDigest[0] = ASN_OCTET_STRING;
01111         esd->contentDigest[1] = (byte)hashSz;
01112         ret = wc_HashFinal(&esd->hash, esd->hashType,
01113                            &esd->contentDigest[2]);
01114         if (ret < 0) {
01115 #ifdef WOLFSSL_SMALL_STACK
01116             XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01117 #endif
01118         return ret;
01119         }
01120     }
01121 
01122     esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets);
01123     esd->innerContSeqSz = SetExplicit(0, esd->innerOctetsSz + pkcs7->contentSz,
01124                                 esd->innerContSeq);
01125     esd->contentInfoSeqSz = SetSequence(pkcs7->contentSz + esd->innerOctetsSz +
01126                                     innerOidSz + esd->innerContSeqSz,
01127                                     esd->contentInfoSeq);
01128 
01129     esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz,
01130                                      esd->issuerSn, MAX_SN_SZ);
01131     signerInfoSz += esd->issuerSnSz;
01132     esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName);
01133     signerInfoSz += esd->issuerNameSz + pkcs7->issuerSz;
01134     esd->issuerSnSeqSz = SetSequence(signerInfoSz, esd->issuerSnSeq);
01135     signerInfoSz += esd->issuerSnSeqSz;
01136     esd->signerVersionSz = SetMyVersion(1, esd->signerVersion, 0);
01137     signerInfoSz += esd->signerVersionSz;
01138     esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId,
01139                                       oidHashType, 0);
01140     signerInfoSz += esd->signerDigAlgoIdSz;
01141 
01142     /* set signatureAlgorithm */
01143     ret = wc_PKCS7_SignedDataGetEncAlgoId(pkcs7, &digEncAlgoId,
01144                                           &digEncAlgoType);
01145     if (ret < 0) {
01146 #ifdef WOLFSSL_SMALL_STACK
01147         XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01148 #endif
01149         return ret;
01150     }
01151     esd->digEncAlgoIdSz = SetAlgoID(digEncAlgoId, esd->digEncAlgoId,
01152                                     digEncAlgoType, 0);
01153     signerInfoSz += esd->digEncAlgoIdSz;
01154 
01155     if (pkcs7->signedAttribsSz != 0) {
01156 
01157         /* build up signed attributes */
01158         ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd,
01159                                     contentTypeOid, sizeof(contentTypeOid),
01160                                     contentType, sizeof(contentType),
01161                                     messageDigestOid, sizeof(messageDigestOid));
01162         if (ret < 0) {
01163 #ifdef WOLFSSL_SMALL_STACK
01164             XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01165 #endif
01166             return MEMORY_E;
01167         }
01168 
01169         flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, pkcs7->heap,
01170                                                          DYNAMIC_TYPE_PKCS7);
01171         flatSignedAttribsSz = esd->signedAttribsSz;
01172         if (flatSignedAttribs == NULL) {
01173 #ifdef WOLFSSL_SMALL_STACK
01174             XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01175 #endif
01176             return MEMORY_E;
01177         }
01178 
01179         FlattenAttributes(flatSignedAttribs,
01180                                    esd->signedAttribs, esd->signedAttribsCount);
01181         esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz,
01182                                                           esd->signedAttribSet);
01183     }
01184 
01185     /* Calculate the final hash and encrypt it. */
01186     ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs,
01187                                             flatSignedAttribsSz, esd);
01188     if (ret < 0) {
01189         if (pkcs7->signedAttribsSz != 0)
01190             XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
01191 #ifdef WOLFSSL_SMALL_STACK
01192         XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01193 #endif
01194         return ret;
01195     }
01196 
01197     signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz;
01198 
01199     esd->signerDigestSz = SetOctetString(esd->encContentDigestSz,
01200                                                              esd->signerDigest);
01201     signerInfoSz += esd->signerDigestSz + esd->encContentDigestSz;
01202 
01203     esd->signerInfoSeqSz = SetSequence(signerInfoSz, esd->signerInfoSeq);
01204     signerInfoSz += esd->signerInfoSeqSz;
01205     esd->signerInfoSetSz = SetSet(signerInfoSz, esd->signerInfoSet);
01206     signerInfoSz += esd->signerInfoSetSz;
01207 
01208     esd->certsSetSz = SetImplicit(ASN_SET, 0, pkcs7->singleCertSz,
01209                                                                  esd->certsSet);
01210 
01211     esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId,
01212                                       oidHashType, 0);
01213     esd->digAlgoIdSetSz = SetSet(esd->singleDigAlgoIdSz, esd->digAlgoIdSet);
01214 
01215 
01216     esd->versionSz = SetMyVersion(1, esd->version, 0);
01217 
01218     totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz +
01219               esd->contentInfoSeqSz + esd->certsSetSz + pkcs7->singleCertSz +
01220               esd->innerOctetsSz + esd->innerContSeqSz +
01221               innerOidSz + pkcs7->contentSz +
01222               signerInfoSz;
01223     esd->innerSeqSz = SetSequence(totalSz, esd->innerSeq);
01224     totalSz += esd->innerSeqSz;
01225     esd->outerContentSz = SetExplicit(0, totalSz, esd->outerContent);
01226     totalSz += esd->outerContentSz + outerOidSz;
01227     esd->outerSeqSz = SetSequence(totalSz, esd->outerSeq);
01228     totalSz += esd->outerSeqSz;
01229 
01230     if (outputSz < totalSz) {
01231         if (pkcs7->signedAttribsSz != 0)
01232             XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
01233 #ifdef WOLFSSL_SMALL_STACK
01234         XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01235 #endif
01236         return BUFFER_E;
01237     }
01238 
01239     idx = 0;
01240     XMEMCPY(output + idx, esd->outerSeq, esd->outerSeqSz);
01241     idx += esd->outerSeqSz;
01242     XMEMCPY(output + idx, outerOid, outerOidSz);
01243     idx += outerOidSz;
01244     XMEMCPY(output + idx, esd->outerContent, esd->outerContentSz);
01245     idx += esd->outerContentSz;
01246     XMEMCPY(output + idx, esd->innerSeq, esd->innerSeqSz);
01247     idx += esd->innerSeqSz;
01248     XMEMCPY(output + idx, esd->version, esd->versionSz);
01249     idx += esd->versionSz;
01250     XMEMCPY(output + idx, esd->digAlgoIdSet, esd->digAlgoIdSetSz);
01251     idx += esd->digAlgoIdSetSz;
01252     XMEMCPY(output + idx, esd->singleDigAlgoId, esd->singleDigAlgoIdSz);
01253     idx += esd->singleDigAlgoIdSz;
01254     XMEMCPY(output + idx, esd->contentInfoSeq, esd->contentInfoSeqSz);
01255     idx += esd->contentInfoSeqSz;
01256     XMEMCPY(output + idx, innerOid, innerOidSz);
01257     idx += innerOidSz;
01258     XMEMCPY(output + idx, esd->innerContSeq, esd->innerContSeqSz);
01259     idx += esd->innerContSeqSz;
01260     XMEMCPY(output + idx, esd->innerOctets, esd->innerOctetsSz);
01261     idx += esd->innerOctetsSz;
01262     XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
01263     idx += pkcs7->contentSz;
01264     XMEMCPY(output + idx, esd->certsSet, esd->certsSetSz);
01265     idx += esd->certsSetSz;
01266     XMEMCPY(output + idx, pkcs7->singleCert, pkcs7->singleCertSz);
01267     idx += pkcs7->singleCertSz;
01268     XMEMCPY(output + idx, esd->signerInfoSet, esd->signerInfoSetSz);
01269     idx += esd->signerInfoSetSz;
01270     XMEMCPY(output + idx, esd->signerInfoSeq, esd->signerInfoSeqSz);
01271     idx += esd->signerInfoSeqSz;
01272     XMEMCPY(output + idx, esd->signerVersion, esd->signerVersionSz);
01273     idx += esd->signerVersionSz;
01274     XMEMCPY(output + idx, esd->issuerSnSeq, esd->issuerSnSeqSz);
01275     idx += esd->issuerSnSeqSz;
01276     XMEMCPY(output + idx, esd->issuerName, esd->issuerNameSz);
01277     idx += esd->issuerNameSz;
01278     XMEMCPY(output + idx, pkcs7->issuer, pkcs7->issuerSz);
01279     idx += pkcs7->issuerSz;
01280     XMEMCPY(output + idx, esd->issuerSn, esd->issuerSnSz);
01281     idx += esd->issuerSnSz;
01282     XMEMCPY(output + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz);
01283     idx += esd->signerDigAlgoIdSz;
01284 
01285     /* SignerInfo:Attributes */
01286     if (flatSignedAttribsSz > 0) {
01287         XMEMCPY(output + idx, esd->signedAttribSet, esd->signedAttribSetSz);
01288         idx += esd->signedAttribSetSz;
01289         XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz);
01290         idx += flatSignedAttribsSz;
01291         XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
01292     }
01293 
01294     XMEMCPY(output + idx, esd->digEncAlgoId, esd->digEncAlgoIdSz);
01295     idx += esd->digEncAlgoIdSz;
01296     XMEMCPY(output + idx, esd->signerDigest, esd->signerDigestSz);
01297     idx += esd->signerDigestSz;
01298     XMEMCPY(output + idx, esd->encContentDigest, esd->encContentDigestSz);
01299     idx += esd->encContentDigestSz;
01300 
01301 #ifdef WOLFSSL_SMALL_STACK
01302     XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01303 #endif
01304 
01305     return idx;
01306 }
01307 
01308 
01309 #ifndef NO_RSA
01310 
01311 /* returns size of signature put into out, negative on error */
01312 static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
01313                               byte* hash, word32 hashSz)
01314 {
01315     int ret = 0;
01316     word32 scratch = 0;
01317 #ifdef WOLFSSL_SMALL_STACK
01318     byte* digest;
01319     RsaKey* key;
01320 #else
01321     byte digest[MAX_PKCS7_DIGEST_SZ];
01322     RsaKey stack_key;
01323     RsaKey* key = &stack_key;
01324 #endif
01325 
01326     if (pkcs7 == NULL || sig == NULL || hash == NULL) {
01327         return BAD_FUNC_ARG;
01328     }
01329 
01330 #ifdef WOLFSSL_SMALL_STACK
01331     digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
01332                             DYNAMIC_TYPE_TMP_BUFFER);
01333 
01334     if (digest == NULL)
01335         return MEMORY_E;
01336 
01337     key = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01338     if (key == NULL) {
01339         XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01340         return MEMORY_E;
01341     }
01342 #endif
01343 
01344     XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ);
01345 
01346     ret = wc_InitRsaKey_ex(key, pkcs7->heap, pkcs7->devId);
01347     if (ret != 0) {
01348 #ifdef WOLFSSL_SMALL_STACK
01349         XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01350         XFREE(key,    pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01351 #endif
01352         return ret;
01353     }
01354 
01355     if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key,
01356                               pkcs7->publicKeySz) < 0) {
01357         WOLFSSL_MSG("ASN RSA key decode error");
01358         wc_FreeRsaKey(key);
01359 #ifdef WOLFSSL_SMALL_STACK
01360         XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01361         XFREE(key,    pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01362 #endif
01363         return PUBLIC_KEY_E;
01364     }
01365 
01366     ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, key);
01367 
01368     wc_FreeRsaKey(key);
01369 
01370     if (((int)hashSz != ret) || (XMEMCMP(digest, hash, ret) != 0)) {
01371         ret = SIG_VERIFY_E;
01372     }
01373 
01374 #ifdef WOLFSSL_SMALL_STACK
01375     XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01376     XFREE(key,    pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01377 #endif
01378 
01379     return ret;
01380 }
01381 
01382 #endif /* NO_RSA */
01383 
01384 
01385 #ifdef HAVE_ECC
01386 
01387 /* returns size of signature put into out, negative on error */
01388 static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
01389                                 byte* hash, word32 hashSz)
01390 {
01391     int ret = 0;
01392     int res = 0;
01393 #ifdef WOLFSSL_SMALL_STACK
01394     byte* digest;
01395     ecc_key* key;
01396 #else
01397     byte digest[MAX_PKCS7_DIGEST_SZ];
01398     ecc_key stack_key;
01399     ecc_key* key = &stack_key;
01400 #endif
01401     word32 idx = 0;
01402 
01403     if (pkcs7 == NULL || sig == NULL)
01404         return BAD_FUNC_ARG;
01405 
01406 #ifdef WOLFSSL_SMALL_STACK
01407     digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
01408                             DYNAMIC_TYPE_TMP_BUFFER);
01409 
01410     if (digest == NULL)
01411         return MEMORY_E;
01412 
01413     key = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01414     if (key == NULL) {
01415         XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01416         return MEMORY_E;
01417     }
01418 #endif
01419 
01420     XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ);
01421 
01422     ret = wc_ecc_init_ex(key, pkcs7->heap, pkcs7->devId);
01423     if (ret != 0) {
01424 #ifdef WOLFSSL_SMALL_STACK
01425         XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01426         XFREE(key,    pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01427 #endif
01428         return ret;
01429     }
01430 
01431     if (wc_EccPublicKeyDecode(pkcs7->publicKey, &idx, key,
01432                                                       pkcs7->publicKeySz) < 0) {
01433         WOLFSSL_MSG("ASN ECDSA key decode error");
01434         wc_ecc_free(key);
01435 #ifdef WOLFSSL_SMALL_STACK
01436         XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01437         XFREE(key,    pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01438 #endif
01439         return PUBLIC_KEY_E;
01440     }
01441 
01442     ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &res, key);
01443 
01444     wc_ecc_free(key);
01445 
01446     if (ret == 0 && res != 1) {
01447         ret = SIG_VERIFY_E;
01448     }
01449 
01450 #ifdef WOLFSSL_SMALL_STACK
01451     XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01452     XFREE(key,    pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01453 #endif
01454 
01455     return ret;
01456 }
01457 
01458 #endif /* HAVE_ECC */
01459 
01460 
01461 /* build SignedData digest, both in PKCS#7 DigestInfo format and
01462  * as plain digest for CMS.
01463  *
01464  * pkcs7          - pointer to initialized PKCS7 struct
01465  * signedAttrib   - signed attributes
01466  * signedAttribSz - size of signedAttrib, octets
01467  * pkcs7Digest    - [OUT] PKCS#7 DigestInfo
01468  * pkcs7DigestSz  - [IN/OUT] size of pkcs7Digest
01469  * plainDigest    - [OUT] pointer to plain digest, offset into pkcs7Digest
01470  * plainDigestSz  - [OUT] size of digest at plainDigest
01471  *
01472  * returns 0 on success, negative on error */
01473 static int wc_PKCS7_BuildSignedDataDigest(PKCS7* pkcs7, byte* signedAttrib,
01474                                       word32 signedAttribSz, byte* pkcs7Digest,
01475                                       word32* pkcs7DigestSz, byte** plainDigest,
01476                                       word32* plainDigestSz)
01477 {
01478     int ret = 0, digIdx = 0, hashSz;
01479     word32 attribSetSz;
01480     byte attribSet[MAX_SET_SZ];
01481     byte digest[WC_MAX_DIGEST_SIZE];
01482     byte digestInfoSeq[MAX_SEQ_SZ];
01483     byte digestStr[MAX_OCTET_STR_SZ];
01484     byte algoId[MAX_ALGO_SZ];
01485     word32 digestInfoSeqSz, digestStrSz, algoIdSz;
01486 #ifdef WOLFSSL_SMALL_STACK
01487     byte* digestInfo;
01488 #else
01489     byte digestInfo[MAX_PKCS7_DIGEST_SZ];
01490 #endif
01491 
01492     wc_HashAlg hash;
01493     enum wc_HashType hashType;
01494 
01495     if (pkcs7 == NULL || pkcs7Digest == NULL ||
01496         pkcs7DigestSz == NULL || plainDigest == NULL) {
01497         return BAD_FUNC_ARG;
01498     }
01499 
01500 #ifdef WOLFSSL_SMALL_STACK
01501     digestInfo = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
01502         DYNAMIC_TYPE_TMP_BUFFER);
01503     if (digestInfo == NULL)
01504         return MEMORY_E;
01505 #endif
01506 
01507     XMEMSET(pkcs7Digest, 0, *pkcs7DigestSz);
01508     XMEMSET(digest,      0, WC_MAX_DIGEST_SIZE);
01509     XMEMSET(digestInfo,  0, MAX_PKCS7_DIGEST_SZ);
01510 
01511     hashType = wc_OidGetHash(pkcs7->hashOID);
01512     ret = wc_HashGetDigestSize(hashType);
01513     if (ret < 0) {
01514 #ifdef WOLFSSL_SMALL_STACK
01515         XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01516 #endif
01517         return ret;
01518     }
01519     hashSz = ret;
01520 
01521     /* calculate digest */
01522     ret = wc_HashInit(&hash, hashType);
01523     if (ret < 0) {
01524 #ifdef WOLFSSL_SMALL_STACK
01525         XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01526 #endif
01527         return ret;
01528     }
01529 
01530     if (signedAttribSz > 0) {
01531 
01532         if (signedAttrib == NULL) {
01533 #ifdef WOLFSSL_SMALL_STACK
01534             XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01535 #endif
01536             return BAD_FUNC_ARG;
01537         }
01538 
01539         attribSetSz = SetSet(signedAttribSz, attribSet);
01540         ret = wc_HashUpdate(&hash, hashType, attribSet, attribSetSz);
01541         if (ret < 0) {
01542 #ifdef WOLFSSL_SMALL_STACK
01543             XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01544 #endif
01545             return ret;
01546         }
01547 
01548         ret = wc_HashUpdate(&hash, hashType, signedAttrib, signedAttribSz);
01549         if (ret < 0) {
01550 #ifdef WOLFSSL_SMALL_STACK
01551             XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01552 #endif
01553             return ret;
01554         }
01555 
01556         ret = wc_HashFinal(&hash, hashType, digest);
01557         if (ret < 0) {
01558 #ifdef WOLFSSL_SMALL_STACK
01559             XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01560 #endif
01561             return ret;
01562         }
01563 
01564     } else {
01565 
01566         if (pkcs7->content == NULL) {
01567 #ifdef WOLFSSL_SMALL_STACK
01568             XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01569 #endif
01570             return BAD_FUNC_ARG;
01571         }
01572 
01573         ret = wc_HashUpdate(&hash, hashType, pkcs7->content, pkcs7->contentSz);
01574         if (ret < 0) {
01575 #ifdef WOLFSSL_SMALL_STACK
01576             XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01577 #endif
01578             return ret;
01579         }
01580 
01581         ret = wc_HashFinal(&hash, hashType, digest);
01582         if (ret < 0) {
01583 #ifdef WOLFSSL_SMALL_STACK
01584             XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01585 #endif
01586             return ret;
01587         }
01588     }
01589 
01590     /* Set algoID, with NULL attributes */
01591     algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0);
01592 
01593     digestStrSz = SetOctetString(hashSz, digestStr);
01594     digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz,
01595                                   digestInfoSeq);
01596 
01597     XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
01598     digIdx += digestInfoSeqSz;
01599     XMEMCPY(digestInfo + digIdx, algoId, algoIdSz);
01600     digIdx += algoIdSz;
01601     XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
01602     digIdx += digestStrSz;
01603     XMEMCPY(digestInfo + digIdx, digest, hashSz);
01604     digIdx += hashSz;
01605 
01606     XMEMCPY(pkcs7Digest, digestInfo, digIdx);
01607     *pkcs7DigestSz = digIdx;
01608 
01609     /* set plain digest pointer */
01610     *plainDigest = pkcs7Digest + digIdx - hashSz;
01611     *plainDigestSz = hashSz;
01612 
01613 #ifdef WOLFSSL_SMALL_STACK
01614     XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01615 #endif
01616     return 0;
01617 }
01618 
01619 
01620 /* verifies SignedData signature, over either PKCS#7 DigestInfo or
01621  * content digest.
01622  *
01623  * pkcs7          - pointer to initialized PKCS7 struct
01624  * sig            - signature to verify
01625  * sigSz          - size of sig
01626  * signedAttrib   - signed attributes, or null if empty
01627  * signedAttribSz - size of signedAttributes
01628  *
01629  * return 0 on success, negative on error */
01630 static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig,
01631                                               word32 sigSz, byte* signedAttrib,
01632                                               word32 signedAttribSz)
01633 {
01634     int ret = 0;
01635     word32 plainDigestSz = 0, pkcs7DigestSz;
01636     byte* plainDigest = NULL; /* offset into pkcs7Digest */
01637 #ifdef WOLFSSL_SMALL_STACK
01638     byte* pkcs7Digest;
01639 #else
01640     byte  pkcs7Digest[MAX_PKCS7_DIGEST_SZ];
01641 #endif
01642 
01643     if (pkcs7 == NULL)
01644         return BAD_FUNC_ARG;
01645 
01646 #ifdef WOLFSSL_SMALL_STACK
01647     pkcs7Digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
01648                                  DYNAMIC_TYPE_TMP_BUFFER);
01649     if (pkcs7Digest == NULL)
01650         return MEMORY_E;
01651 #endif
01652 
01653     /* build hash to verify against */
01654     pkcs7DigestSz = MAX_PKCS7_DIGEST_SZ;
01655     ret = wc_PKCS7_BuildSignedDataDigest(pkcs7, signedAttrib,
01656                                          signedAttribSz, pkcs7Digest,
01657                                          &pkcs7DigestSz, &plainDigest,
01658                                          &plainDigestSz);
01659     if (ret < 0) {
01660 #ifdef WOLFSSL_SMALL_STACK
01661         XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01662 #endif
01663         return ret;
01664     }
01665 
01666     switch (pkcs7->publicKeyOID) {
01667 
01668 #ifndef NO_RSA
01669         case RSAk:
01670             ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, pkcs7Digest,
01671                                      pkcs7DigestSz);
01672             if (ret < 0) {
01673                 WOLFSSL_MSG("PKCS#7 verification failed, trying CMS");
01674                 ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, plainDigest,
01675                                          plainDigestSz);
01676             }
01677             break;
01678 #endif
01679 
01680 #ifdef HAVE_ECC
01681         case ECDSAk:
01682             ret = wc_PKCS7_EcdsaVerify(pkcs7, sig, sigSz, plainDigest,
01683                                        plainDigestSz);
01684             break;
01685 #endif
01686 
01687         default:
01688             WOLFSSL_MSG("Unsupported public key type");
01689             ret = BAD_FUNC_ARG;
01690     }
01691 
01692 #ifdef WOLFSSL_SMALL_STACK
01693      XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
01694 #endif
01695     return ret;
01696 }
01697 
01698 
01699 /* set correct public key OID based on signature OID, stores in
01700  * pkcs7->publicKeyOID and returns same value */
01701 static int wc_PKCS7_SetPublicKeyOID(PKCS7* pkcs7, int sigOID)
01702 {
01703     if (pkcs7 == NULL)
01704         return BAD_FUNC_ARG;
01705 
01706     pkcs7->publicKeyOID = 0;
01707 
01708     switch (sigOID) {
01709 
01710     #ifndef NO_RSA
01711         /* RSA signature types */
01712         case CTC_MD2wRSA:
01713         case CTC_MD5wRSA:
01714         case CTC_SHAwRSA:
01715         case CTC_SHA224wRSA:
01716         case CTC_SHA256wRSA:
01717         case CTC_SHA384wRSA:
01718         case CTC_SHA512wRSA:
01719             pkcs7->publicKeyOID = RSAk;
01720             break;
01721 
01722         /* if sigOID is already RSAk */
01723         case RSAk:
01724             pkcs7->publicKeyOID = sigOID;
01725             break;
01726     #endif
01727 
01728     #ifndef NO_DSA
01729         /* DSA signature types */
01730         case CTC_SHAwDSA:
01731             pkcs7->publicKeyOID = DSAk;
01732             break;
01733 
01734         /* if sigOID is already DSAk */
01735         case DSAk:
01736             pkcs7->publicKeyOID = sigOID;
01737             break;
01738     #endif
01739 
01740     #ifdef HAVE_ECC
01741         /* ECDSA signature types */
01742         case CTC_SHAwECDSA:
01743         case CTC_SHA224wECDSA:
01744         case CTC_SHA256wECDSA:
01745         case CTC_SHA384wECDSA:
01746         case CTC_SHA512wECDSA:
01747             pkcs7->publicKeyOID = ECDSAk;
01748             break;
01749 
01750         /* if sigOID is already ECDSAk */
01751         case ECDSAk:
01752             pkcs7->publicKeyOID = sigOID;
01753             break;
01754     #endif
01755 
01756         default:
01757             WOLFSSL_MSG("Unsupported public key algorithm");
01758             return ASN_SIG_KEY_E;
01759     }
01760 
01761     return pkcs7->publicKeyOID;
01762 }
01763 
01764 
01765 /* Parses through the attributes and adds them to the PKCS7 structure
01766  * Creates dynamic attribute structures that are free'd with calling
01767  * wc_PKCS7_Free()
01768  *
01769  * NOTE: An attribute has the ASN1 format of
01770  ** Sequence
01771  ****** Object ID
01772  ****** Set
01773  ********** {PritnableString, UTCTime, OCTET STRING ...}
01774  *
01775  * pkcs7  the PKCS7 structure to put the parsed attributes into
01776  * in     buffer holding all attributes
01777  * inSz   size of in buffer
01778  *
01779  * returns the number of attributes parsed on success
01780  */
01781 static int wc_PKCS7_ParseAttribs(PKCS7* pkcs7, byte* in, int inSz)
01782 {
01783     int    found = 0;
01784     word32 idx   = 0;
01785     word32 oid;
01786 
01787     if (pkcs7 == NULL || in == NULL || inSz < 0) {
01788         return BAD_FUNC_ARG;
01789     }
01790 
01791     while (idx < (word32)inSz) {
01792         int length  = 0;
01793         int oidIdx;
01794         PKCS7DecodedAttrib* attrib;
01795 
01796         if (GetSequence(in, &idx, &length, inSz) < 0)
01797             return ASN_PARSE_E;
01798 
01799         attrib = (PKCS7DecodedAttrib*)XMALLOC(sizeof(PKCS7DecodedAttrib),
01800                 pkcs7->heap, DYNAMIC_TYPE_PKCS7);
01801         if (attrib == NULL) {
01802             return MEMORY_E;
01803         }
01804         XMEMSET(attrib, 0, sizeof(PKCS7DecodedAttrib));
01805 
01806         oidIdx = idx;
01807         if (GetObjectId(in, &idx, &oid, oidIgnoreType, inSz)
01808                 < 0) {
01809             XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
01810             return ASN_PARSE_E;
01811         }
01812         attrib->oidSz = idx - oidIdx;
01813         attrib->oid = (byte*)XMALLOC(attrib->oidSz, pkcs7->heap,
01814                                      DYNAMIC_TYPE_PKCS7);
01815         if (attrib->oid == NULL) {
01816             XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
01817             return MEMORY_E;
01818         }
01819         XMEMCPY(attrib->oid, in + oidIdx, attrib->oidSz);
01820 
01821 
01822         /* Get Set that contains the printable string value */
01823         if (GetSet(in, &idx, &length, inSz) < 0) {
01824             XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
01825             XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
01826             return ASN_PARSE_E;
01827         }
01828 
01829         if ((inSz - idx) < (word32)length) {
01830             XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
01831             XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
01832             return ASN_PARSE_E;
01833         }
01834 
01835         attrib->valueSz = (word32)length;
01836         attrib->value = (byte*)XMALLOC(attrib->valueSz, pkcs7->heap,
01837                                        DYNAMIC_TYPE_PKCS7);
01838         if (attrib->value == NULL) {
01839             XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
01840             XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
01841             return MEMORY_E;
01842         }
01843         XMEMCPY(attrib->value, in + idx, attrib->valueSz);
01844         idx += length;
01845 
01846         /* store attribute in linked list */
01847         if (pkcs7->decodedAttrib != NULL) {
01848             attrib->next = pkcs7->decodedAttrib;
01849             pkcs7->decodedAttrib = attrib;
01850         } else {
01851             pkcs7->decodedAttrib = attrib;
01852         }
01853         found++;
01854     }
01855 
01856     return found;
01857 }
01858 
01859 
01860 /* Finds the certificates in the message and saves it. */
01861 int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
01862 {
01863     word32 idx, contentType, hashOID, sigOID;
01864     int length, version, ret;
01865     byte* content = NULL;
01866     byte* sig = NULL;
01867     byte* cert = NULL;
01868     byte* signedAttrib = NULL;
01869     int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0;
01870     byte degenerate;
01871 #ifdef ASN_BER_TO_DER
01872     byte* der;
01873 #endif
01874 
01875     if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0)
01876         return BAD_FUNC_ARG;
01877 
01878     idx = 0;
01879 
01880     /* Get the contentInfo sequence */
01881     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01882         return ASN_PARSE_E;
01883 
01884     if (length == 0 && pkiMsg[idx-1] == 0x80) {
01885 #ifdef ASN_BER_TO_DER
01886         word32 len = 0;
01887 
01888         ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len);
01889         if (ret != LENGTH_ONLY_E)
01890             return ret;
01891         pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
01892         if (pkcs7->der == NULL)
01893             return MEMORY_E;
01894         ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len);
01895         if (ret < 0)
01896             return ret;
01897 
01898         pkiMsg = pkcs7->der;
01899         pkiMsgSz = len;
01900         idx = 0;
01901         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01902             return ASN_PARSE_E;
01903 #else
01904         return BER_INDEF_E;
01905 #endif
01906     }
01907 
01908     /* Get the contentInfo contentType */
01909     if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
01910         return ASN_PARSE_E;
01911 
01912     if (contentType != SIGNED_DATA) {
01913         WOLFSSL_MSG("PKCS#7 input not of type SignedData");
01914         return PKCS7_OID_E;
01915     }
01916 
01917     /* get the ContentInfo content */
01918     if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
01919         return ASN_PARSE_E;
01920 
01921     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01922         return ASN_PARSE_E;
01923 
01924     /* Get the signedData sequence */
01925     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01926         return ASN_PARSE_E;
01927 
01928     /* Get the version */
01929     if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
01930         return ASN_PARSE_E;
01931 
01932     if (version != 1) {
01933         WOLFSSL_MSG("PKCS#7 signedData needs to be of version 1");
01934         return ASN_VERSION_E;
01935     }
01936 
01937     /* Get the set of DigestAlgorithmIdentifiers */
01938     if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01939         return ASN_PARSE_E;
01940 
01941     /* Skip the set. */
01942     idx += length;
01943     degenerate = (length == 0)? 1 : 0;
01944 
01945     /* Get the inner ContentInfo sequence */
01946     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01947         return ASN_PARSE_E;
01948 
01949     /* Get the inner ContentInfo contentType */
01950     if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
01951         return ASN_PARSE_E;
01952 
01953     if (contentType != DATA) {
01954         WOLFSSL_MSG("PKCS#7 inner input not of type Data");
01955         return PKCS7_OID_E;
01956     }
01957 
01958     /* Check for content info, it could be omitted when degenerate */
01959     {
01960         word32 localIdx = idx;
01961         ret = 0;
01962         if (pkiMsg[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
01963             ret = ASN_PARSE_E;
01964 
01965         if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, pkiMsgSz) <= 0)
01966             ret = ASN_PARSE_E;
01967 
01968         if (ret == 0 && pkiMsg[localIdx++] != ASN_OCTET_STRING)
01969             ret = ASN_PARSE_E;
01970 
01971         if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, pkiMsgSz) < 0)
01972             ret = ASN_PARSE_E;
01973 
01974         /* Save the inner data as the content. */
01975         if (length > 0) {
01976             /* Local pointer for calculating hashes later */
01977             content   = &pkiMsg[localIdx];
01978             contentSz = length;
01979             localIdx += length;
01980         }
01981 
01982         /* update idx if successful */
01983         if (ret == 0) {
01984             idx = localIdx;
01985         }
01986     }
01987 
01988     /* If getting the content info failed with non degenerate then return the
01989      * error case. Otherwise with a degenerate it is ok if the content
01990      * info was omitted */
01991     if (!degenerate && ret != 0) {
01992         return ret;
01993     }
01994 
01995     /* Get the implicit[0] set of certificates */
01996     if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
01997         idx++;
01998         if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
01999             return ASN_PARSE_E;
02000 
02001         if (length > 0) {
02002             /* At this point, idx is at the first certificate in
02003              * a set of certificates. There may be more than one,
02004              * or none, or they may be a PKCS 6 extended
02005              * certificate. We want to save the first cert if it
02006              * is X.509. */
02007 
02008             word32 certIdx = idx;
02009 
02010             if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
02011                 if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0)
02012                     return ASN_PARSE_E;
02013 
02014                 cert = &pkiMsg[idx];
02015                 certSz += (certIdx - idx);
02016             }
02017 
02018 #ifdef ASN_BER_TO_DER
02019             der = pkcs7->der;
02020 #endif
02021             /* This will reset PKCS7 structure and then set the certificate */
02022             wc_PKCS7_InitWithCert(pkcs7, cert, certSz);
02023 #ifdef ASN_BER_TO_DER
02024             pkcs7->der = der;
02025 #endif
02026 
02027             /* iterate through any additional certificates */
02028             if (MAX_PKCS7_CERTS > 0) {
02029                 word32 localIdx;
02030                 int sz = 0;
02031                 int i;
02032 
02033                 pkcs7->cert[0]   = cert;
02034                 pkcs7->certSz[0] = certSz;
02035                 certIdx = idx + certSz;
02036 
02037                 for (i = 1; i < MAX_PKCS7_CERTS && certIdx + 1 < pkiMsgSz; i++) {
02038                     localIdx = certIdx;
02039 
02040                     if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
02041                         if (GetLength(pkiMsg, &certIdx, &sz, pkiMsgSz) < 0)
02042                             return ASN_PARSE_E;
02043 
02044                         pkcs7->cert[i]   = &pkiMsg[localIdx];
02045                         pkcs7->certSz[i] = sz + (certIdx - localIdx);
02046                         certIdx += sz;
02047                     }
02048                 }
02049             }
02050         }
02051         idx += length;
02052     }
02053 
02054     /* set content and size after init of PKCS7 structure */
02055     pkcs7->content   = content;
02056     pkcs7->contentSz = contentSz;
02057 
02058     /* Get the implicit[1] set of crls */
02059     if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
02060         idx++;
02061         if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
02062             return ASN_PARSE_E;
02063 
02064         /* Skip the set */
02065         idx += length;
02066     }
02067 
02068     /* Get the set of signerInfos */
02069     if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
02070         return ASN_PARSE_E;
02071 
02072     if (length > 0) {
02073         /* Get the sequence of the first signerInfo */
02074         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
02075             return ASN_PARSE_E;
02076 
02077         /* Get the version */
02078         if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
02079             return ASN_PARSE_E;
02080 
02081         if (version != 1) {
02082             WOLFSSL_MSG("PKCS#7 signerInfo needs to be of version 1");
02083             return ASN_VERSION_E;
02084         }
02085 
02086         /* Get the sequence of IssuerAndSerialNumber */
02087         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
02088             return ASN_PARSE_E;
02089 
02090         /* Skip it */
02091         idx += length;
02092 
02093         /* Get the sequence of digestAlgorithm */
02094         if (GetAlgoId(pkiMsg, &idx, &hashOID, oidHashType, pkiMsgSz) < 0) {
02095             return ASN_PARSE_E;
02096         }
02097         pkcs7->hashOID = (int)hashOID;
02098 
02099         /* Get the IMPLICIT[0] SET OF signedAttributes */
02100         if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
02101             idx++;
02102 
02103             if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
02104                 return ASN_PARSE_E;
02105 
02106             /* save pointer and length */
02107             signedAttrib = &pkiMsg[idx];
02108             signedAttribSz = length;
02109 
02110             if (wc_PKCS7_ParseAttribs(pkcs7, signedAttrib, signedAttribSz) <0) {
02111                 WOLFSSL_MSG("Error parsing signed attributes");
02112                 return ASN_PARSE_E;
02113             }
02114 
02115             idx += length;
02116         }
02117 
02118         /* Get digestEncryptionAlgorithm */
02119         if (GetAlgoId(pkiMsg, &idx, &sigOID, oidSigType, pkiMsgSz) < 0) {
02120             return ASN_PARSE_E;
02121         }
02122 
02123         /* store public key type based on digestEncryptionAlgorithm */
02124         ret = wc_PKCS7_SetPublicKeyOID(pkcs7, sigOID);
02125         if (ret <= 0) {
02126             WOLFSSL_MSG("Failed to set public key OID from signature");
02127             return ret;
02128         }
02129 
02130         /* Get the signature */
02131         if (pkiMsg[idx] == ASN_OCTET_STRING) {
02132             idx++;
02133 
02134             if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
02135                 return ASN_PARSE_E;
02136 
02137             /* save pointer and length */
02138             sig = &pkiMsg[idx];
02139             sigSz = length;
02140 
02141             idx += length;
02142         }
02143 
02144         pkcs7->content = content;
02145         pkcs7->contentSz = contentSz;
02146 
02147         ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz,
02148                                                  signedAttrib, signedAttribSz);
02149         if (ret < 0)
02150             return ret;
02151     }
02152 
02153     return 0;
02154 }
02155 
02156 
02157 #ifdef HAVE_ECC
02158 
02159 /* KARI == KeyAgreeRecipientInfo (key agreement) */
02160 typedef struct WC_PKCS7_KARI {
02161     DecodedCert* decoded;          /* decoded recip cert */
02162     void*    heap;                 /* user heap, points to PKCS7->heap */
02163     int      devId;                /* device ID for HW based private key */
02164     ecc_key* recipKey;             /* recip key  (pub | priv) */
02165     ecc_key* senderKey;            /* sender key (pub | priv) */
02166     byte*    senderKeyExport;      /* sender ephemeral key DER */
02167     byte*    kek;                  /* key encryption key */
02168     byte*    ukm;                  /* OPTIONAL user keying material */
02169     byte*    sharedInfo;           /* ECC-CMS-SharedInfo ASN.1 encoded blob */
02170     word32   senderKeyExportSz;    /* size of sender ephemeral key DER */
02171     word32   kekSz;                /* size of key encryption key */
02172     word32   ukmSz;                /* size of user keying material */
02173     word32   sharedInfoSz;         /* size of ECC-CMS-SharedInfo encoded */
02174     byte     ukmOwner;             /* do we own ukm buffer? 1:yes, 0:no */
02175     byte     direction;            /* WC_PKCS7_ENCODE | WC_PKCS7_DECODE */
02176     byte     decodedInit : 1;      /* indicates decoded was initialized */
02177     byte     recipKeyInit : 1;     /* indicates recipKey was initialized */
02178     byte     senderKeyInit : 1;    /* indicates senderKey was initialized */
02179 } WC_PKCS7_KARI;
02180 
02181 
02182 /* wrap CEK (content encryption key) with KEK, 0 on success, < 0 on error */
02183 static int wc_PKCS7_KariKeyWrap(byte* cek, word32 cekSz, byte* kek,
02184                                 word32 kekSz, byte* out, word32 outSz,
02185                                 int keyWrapAlgo, int direction)
02186 {
02187     int ret;
02188 
02189     if (cek == NULL || kek == NULL || out == NULL)
02190         return BAD_FUNC_ARG;
02191 
02192     switch (keyWrapAlgo) {
02193 #ifndef NO_AES
02194     #ifdef WOLFSSL_AES_128
02195         case AES128_WRAP:
02196     #endif
02197     #ifdef WOLFSSL_AES_192
02198         case AES192_WRAP:
02199     #endif
02200     #ifdef WOLFSSL_AES_256
02201         case AES256_WRAP:
02202     #endif
02203 
02204             if (direction == AES_ENCRYPTION) {
02205 
02206                 ret = wc_AesKeyWrap(kek, kekSz, cek, cekSz,
02207                                     out, outSz, NULL);
02208 
02209             } else if (direction == AES_DECRYPTION) {
02210 
02211                 ret = wc_AesKeyUnWrap(kek, kekSz, cek, cekSz,
02212                                       out, outSz, NULL);
02213             } else {
02214                 WOLFSSL_MSG("Bad key un/wrap direction");
02215                 return BAD_FUNC_ARG;
02216             }
02217 
02218             if (ret <= 0)
02219                 return ret;
02220 
02221             break;
02222 #endif /* NO_AES */
02223 
02224         default:
02225             WOLFSSL_MSG("Unsupported key wrap algorithm");
02226             return BAD_KEYWRAP_ALG_E;
02227     };
02228 
02229     (void)cekSz;
02230     (void)kekSz;
02231     (void)outSz;
02232     (void)direction;
02233     return ret;
02234 }
02235 
02236 
02237 /* allocate and create new WC_PKCS7_KARI struct,
02238  * returns struct pointer on success, NULL on failure */
02239 static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction)
02240 {
02241     WC_PKCS7_KARI* kari = NULL;
02242 
02243     if (pkcs7 == NULL)
02244         return NULL;
02245 
02246     kari = (WC_PKCS7_KARI*)XMALLOC(sizeof(WC_PKCS7_KARI), pkcs7->heap,
02247                                    DYNAMIC_TYPE_PKCS7);
02248     if (kari == NULL) {
02249         WOLFSSL_MSG("Failed to allocate WC_PKCS7_KARI");
02250         return NULL;
02251     }
02252 
02253     kari->decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap,
02254                                           DYNAMIC_TYPE_PKCS7);
02255     if (kari->decoded == NULL) {
02256         WOLFSSL_MSG("Failed to allocate DecodedCert");
02257         XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
02258         return NULL;
02259     }
02260 
02261     kari->recipKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
02262                                        DYNAMIC_TYPE_PKCS7);
02263     if (kari->recipKey == NULL) {
02264         WOLFSSL_MSG("Failed to allocate recipient ecc_key");
02265         XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
02266         XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
02267         return NULL;
02268     }
02269 
02270     kari->senderKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
02271                                         DYNAMIC_TYPE_PKCS7);
02272     if (kari->senderKey == NULL) {
02273         WOLFSSL_MSG("Failed to allocate sender ecc_key");
02274         XFREE(kari->recipKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
02275         XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
02276         XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
02277         return NULL;
02278     }
02279 
02280     kari->senderKeyExport = NULL;
02281     kari->senderKeyExportSz = 0;
02282     kari->kek = NULL;
02283     kari->kekSz = 0;
02284     kari->ukm = NULL;
02285     kari->ukmSz = 0;
02286     kari->ukmOwner = 0;
02287     kari->sharedInfo = NULL;
02288     kari->sharedInfoSz = 0;
02289     kari->direction = direction;
02290     kari->decodedInit = 0;
02291     kari->recipKeyInit = 0;
02292     kari->senderKeyInit = 0;
02293 
02294     kari->heap = pkcs7->heap;
02295     kari->devId = pkcs7->devId;
02296 
02297     return kari;
02298 }
02299 
02300 
02301 /* free WC_PKCS7_KARI struct, return 0 on success */
02302 static int wc_PKCS7_KariFree(WC_PKCS7_KARI* kari)
02303 {
02304     void* heap;
02305 
02306     if (kari) {
02307         heap = kari->heap;
02308 
02309         if (kari->decoded) {
02310             if (kari->decodedInit)
02311                 FreeDecodedCert(kari->decoded);
02312             XFREE(kari->decoded, heap, DYNAMIC_TYPE_PKCS7);
02313         }
02314         if (kari->senderKey) {
02315             if (kari->senderKeyInit)
02316                 wc_ecc_free(kari->senderKey);
02317             XFREE(kari->senderKey, heap, DYNAMIC_TYPE_PKCS7);
02318         }
02319         if (kari->recipKey) {
02320             if (kari->recipKeyInit)
02321                 wc_ecc_free(kari->recipKey);
02322             XFREE(kari->recipKey, heap, DYNAMIC_TYPE_PKCS7);
02323         }
02324         if (kari->senderKeyExport) {
02325             ForceZero(kari->senderKeyExport, kari->senderKeyExportSz);
02326             XFREE(kari->senderKeyExport, heap, DYNAMIC_TYPE_PKCS7);
02327             kari->senderKeyExportSz = 0;
02328         }
02329         if (kari->kek) {
02330             ForceZero(kari->kek, kari->kekSz);
02331             XFREE(kari->kek, heap, DYNAMIC_TYPE_PKCS7);
02332             kari->kekSz = 0;
02333         }
02334         if (kari->ukm) {
02335             if (kari->ukmOwner == 1) {
02336                 XFREE(kari->ukm, heap, DYNAMIC_TYPE_PKCS7);
02337             }
02338             kari->ukmSz = 0;
02339         }
02340         if (kari->sharedInfo) {
02341             ForceZero(kari->sharedInfo, kari->sharedInfoSz);
02342             XFREE(kari->sharedInfo, heap, DYNAMIC_TYPE_PKCS7);
02343             kari->sharedInfoSz = 0;
02344         }
02345         XFREE(kari, heap, DYNAMIC_TYPE_PKCS7);
02346     }
02347 
02348     (void)heap;
02349 
02350     return 0;
02351 }
02352 
02353 
02354 /* parse recipient cert/key, return 0 on success, negative on error
02355  * key/keySz only needed during decoding (WC_PKCS7_DECODE) */
02356 static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert,
02357                                        word32 certSz, const byte* key,
02358                                        word32 keySz)
02359 {
02360     int ret;
02361     word32 idx;
02362 
02363     if (kari == NULL || kari->decoded == NULL ||
02364         cert == NULL || certSz == 0)
02365         return BAD_FUNC_ARG;
02366 
02367     /* decode certificate */
02368     InitDecodedCert(kari->decoded, (byte*)cert, certSz, kari->heap);
02369     kari->decodedInit = 1;
02370     ret = ParseCert(kari->decoded, CA_TYPE, NO_VERIFY, 0);
02371     if (ret < 0)
02372         return ret;
02373 
02374     /* make sure subject key id was read from cert */
02375     if (kari->decoded->extSubjKeyIdSet == 0) {
02376         WOLFSSL_MSG("Failed to read subject key ID from recipient cert");
02377         return BAD_FUNC_ARG;
02378     }
02379 
02380     ret = wc_ecc_init_ex(kari->recipKey, kari->heap, kari->devId);
02381     if (ret != 0)
02382         return ret;
02383 
02384     kari->recipKeyInit = 1;
02385 
02386     /* get recip public key */
02387     if (kari->direction == WC_PKCS7_ENCODE) {
02388 
02389         idx = 0;
02390         ret = wc_EccPublicKeyDecode(kari->decoded->publicKey, &idx,
02391                                     kari->recipKey, kari->decoded->pubKeySize);
02392         if (ret != 0)
02393             return ret;
02394     }
02395     /* get recip private key */
02396     else if (kari->direction == WC_PKCS7_DECODE) {
02397         if (key != NULL && keySz > 0) {
02398             idx = 0;
02399             ret = wc_EccPrivateKeyDecode(key, &idx, kari->recipKey, keySz);
02400         }
02401         else if (kari->devId == INVALID_DEVID) {
02402             ret = BAD_FUNC_ARG;
02403         }
02404         if (ret != 0)
02405             return ret;
02406 
02407     } else {
02408         /* bad direction */
02409         return BAD_FUNC_ARG;
02410     }
02411 
02412     (void)idx;
02413 
02414     return 0;
02415 }
02416 
02417 
02418 /* create ephemeral ECC key, places ecc_key in kari->senderKey,
02419  * DER encoded in kari->senderKeyExport. return 0 on success,
02420  * negative on error */
02421 static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari, WC_RNG* rng)
02422 {
02423     int ret;
02424 
02425     if (kari == NULL || kari->decoded == NULL ||
02426         kari->recipKey == NULL || kari->recipKey->dp == NULL ||
02427         rng == NULL)
02428         return BAD_FUNC_ARG;
02429 
02430     kari->senderKeyExport = (byte*)XMALLOC(kari->decoded->pubKeySize,
02431                                            kari->heap, DYNAMIC_TYPE_PKCS7);
02432     if (kari->senderKeyExport == NULL)
02433         return MEMORY_E;
02434 
02435     kari->senderKeyExportSz = kari->decoded->pubKeySize;
02436 
02437     ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId);
02438     if (ret != 0)
02439         return ret;
02440 
02441     kari->senderKeyInit = 1;
02442 
02443     ret = wc_ecc_make_key_ex(rng, kari->recipKey->dp->size,
02444                              kari->senderKey, kari->recipKey->dp->id);
02445     if (ret != 0)
02446         return ret;
02447 
02448     /* dump generated key to X.963 DER for output in CMS bundle */
02449     ret = wc_ecc_export_x963(kari->senderKey, kari->senderKeyExport,
02450                              &kari->senderKeyExportSz);
02451     if (ret != 0)
02452         return ret;
02453 
02454     return 0;
02455 }
02456 
02457 
02458 /* create ASN.1 encoded ECC-CMS-SharedInfo using specified key wrap algorithm,
02459  * place in kari->sharedInfo. returns 0 on success, negative on error */
02460 static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID)
02461 {
02462     int idx = 0;
02463     int sharedInfoSeqSz = 0;
02464     int keyInfoSz = 0;
02465     int suppPubInfoSeqSz = 0;
02466     int entityUInfoOctetSz = 0;
02467     int entityUInfoExplicitSz = 0;
02468     int kekOctetSz = 0;
02469     int sharedInfoSz = 0;
02470 
02471     word32 kekBitSz = 0;
02472 
02473     byte sharedInfoSeq[MAX_SEQ_SZ];
02474     byte keyInfo[MAX_ALGO_SZ];
02475     byte suppPubInfoSeq[MAX_SEQ_SZ];
02476     byte entityUInfoOctet[MAX_OCTET_STR_SZ];
02477     byte entityUInfoExplicitSeq[MAX_SEQ_SZ];
02478     byte kekOctet[MAX_OCTET_STR_SZ];
02479 
02480     if (kari == NULL)
02481         return BAD_FUNC_ARG;
02482 
02483     if ((kari->ukmSz > 0) && (kari->ukm == NULL))
02484         return BAD_FUNC_ARG;
02485 
02486     /* kekOctet */
02487     kekOctetSz = SetOctetString(sizeof(word32), kekOctet);
02488     sharedInfoSz += (kekOctetSz + sizeof(word32));
02489 
02490     /* suppPubInfo */
02491     suppPubInfoSeqSz = SetImplicit(ASN_SEQUENCE, 2,
02492                                    kekOctetSz + sizeof(word32),
02493                                    suppPubInfoSeq);
02494     sharedInfoSz += suppPubInfoSeqSz;
02495 
02496     /* optional ukm/entityInfo */
02497     if (kari->ukmSz > 0) {
02498         entityUInfoOctetSz = SetOctetString(kari->ukmSz, entityUInfoOctet);
02499         sharedInfoSz += (entityUInfoOctetSz + kari->ukmSz);
02500 
02501         entityUInfoExplicitSz = SetExplicit(0, entityUInfoOctetSz +
02502                                             kari->ukmSz,
02503                                             entityUInfoExplicitSeq);
02504         sharedInfoSz += entityUInfoExplicitSz;
02505     }
02506 
02507     /* keyInfo */
02508     keyInfoSz = SetAlgoID(keyWrapOID, keyInfo, oidKeyWrapType, 0);
02509     sharedInfoSz += keyInfoSz;
02510 
02511     /* sharedInfo */
02512     sharedInfoSeqSz = SetSequence(sharedInfoSz, sharedInfoSeq);
02513     sharedInfoSz += sharedInfoSeqSz;
02514 
02515     kari->sharedInfo = (byte*)XMALLOC(sharedInfoSz, kari->heap,
02516                                       DYNAMIC_TYPE_PKCS7);
02517     if (kari->sharedInfo == NULL)
02518         return MEMORY_E;
02519 
02520     kari->sharedInfoSz = sharedInfoSz;
02521 
02522     XMEMCPY(kari->sharedInfo + idx, sharedInfoSeq, sharedInfoSeqSz);
02523     idx += sharedInfoSeqSz;
02524     XMEMCPY(kari->sharedInfo + idx, keyInfo, keyInfoSz);
02525     idx += keyInfoSz;
02526     if (kari->ukmSz > 0) {
02527         XMEMCPY(kari->sharedInfo + idx, entityUInfoExplicitSeq,
02528                 entityUInfoExplicitSz);
02529         idx += entityUInfoExplicitSz;
02530         XMEMCPY(kari->sharedInfo + idx, entityUInfoOctet, entityUInfoOctetSz);
02531         idx += entityUInfoOctetSz;
02532         XMEMCPY(kari->sharedInfo + idx, kari->ukm, kari->ukmSz);
02533         idx += kari->ukmSz;
02534     }
02535     XMEMCPY(kari->sharedInfo + idx, suppPubInfoSeq, suppPubInfoSeqSz);
02536     idx += suppPubInfoSeqSz;
02537     XMEMCPY(kari->sharedInfo + idx, kekOctet, kekOctetSz);
02538     idx += kekOctetSz;
02539 
02540     kekBitSz = (kari->kekSz) * 8;              /* convert to bits */
02541 #ifdef LITTLE_ENDIAN_ORDER
02542     kekBitSz = ByteReverseWord32(kekBitSz);    /* network byte order */
02543 #endif
02544     XMEMCPY(kari->sharedInfo + idx, &kekBitSz, sizeof(kekBitSz));
02545 
02546     return 0;
02547 }
02548 
02549 
02550 /* create key encryption key (KEK) using key wrap algorithm and key encryption
02551  * algorithm, place in kari->kek. return 0 on success, <0 on error. */
02552 static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari,
02553                                     int keyWrapOID, int keyEncOID)
02554 {
02555     int ret;
02556     int kSz;
02557     enum wc_HashType kdfType;
02558     byte*  secret;
02559     word32 secretSz;
02560 
02561     if (kari == NULL || kari->recipKey == NULL ||
02562         kari->senderKey == NULL || kari->senderKey->dp == NULL)
02563         return BAD_FUNC_ARG;
02564 
02565     /* get KEK size, allocate buff */
02566     kSz = wc_PKCS7_GetOIDKeySize(keyWrapOID);
02567     if (kSz < 0)
02568         return kSz;
02569 
02570     kari->kek = (byte*)XMALLOC(kSz, kari->heap, DYNAMIC_TYPE_PKCS7);
02571     if (kari->kek == NULL)
02572         return MEMORY_E;
02573 
02574     kari->kekSz = (word32)kSz;
02575 
02576     /* generate ECC-CMS-SharedInfo */
02577     ret = wc_PKCS7_KariGenerateSharedInfo(kari, keyWrapOID);
02578     if (ret != 0)
02579         return ret;
02580 
02581     /* generate shared secret */
02582     secretSz = kari->senderKey->dp->size;
02583     secret = (byte*)XMALLOC(secretSz, kari->heap, DYNAMIC_TYPE_PKCS7);
02584     if (secret == NULL)
02585         return MEMORY_E;
02586 
02587     if (kari->direction == WC_PKCS7_ENCODE) {
02588 
02589         ret = wc_ecc_shared_secret(kari->senderKey, kari->recipKey,
02590                                    secret, &secretSz);
02591 
02592     } else if (kari->direction == WC_PKCS7_DECODE) {
02593 
02594         ret = wc_ecc_shared_secret(kari->recipKey, kari->senderKey,
02595                                    secret, &secretSz);
02596 
02597     } else {
02598         /* bad direction */
02599         XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
02600         return BAD_FUNC_ARG;
02601     }
02602 
02603     if (ret != 0) {
02604         XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
02605         return ret;
02606     }
02607 
02608     /* run through KDF */
02609     switch (keyEncOID) {
02610 
02611     #ifndef NO_SHA
02612         case dhSinglePass_stdDH_sha1kdf_scheme:
02613             kdfType = WC_HASH_TYPE_SHA;
02614             break;
02615     #endif
02616     #ifndef WOLFSSL_SHA224
02617         case dhSinglePass_stdDH_sha224kdf_scheme:
02618             kdfType = WC_HASH_TYPE_SHA224;
02619             break;
02620     #endif
02621     #ifndef NO_SHA256
02622         case dhSinglePass_stdDH_sha256kdf_scheme:
02623             kdfType = WC_HASH_TYPE_SHA256;
02624             break;
02625     #endif
02626     #ifdef WOLFSSL_SHA384
02627         case dhSinglePass_stdDH_sha384kdf_scheme:
02628             kdfType = WC_HASH_TYPE_SHA384;
02629             break;
02630     #endif
02631     #ifdef WOLFSSL_SHA512
02632         case dhSinglePass_stdDH_sha512kdf_scheme:
02633             kdfType = WC_HASH_TYPE_SHA512;
02634             break;
02635     #endif
02636         default:
02637             WOLFSSL_MSG("Unsupported key agreement algorithm");
02638             XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
02639             return BAD_FUNC_ARG;
02640     };
02641 
02642     ret = wc_X963_KDF(kdfType, secret, secretSz, kari->sharedInfo,
02643                       kari->sharedInfoSz, kari->kek, kari->kekSz);
02644     if (ret != 0) {
02645         XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
02646         return ret;
02647     }
02648 
02649     XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
02650 
02651     return 0;
02652 }
02653 
02654 
02655 /* create ASN.1 formatted KeyAgreeRecipientInfo (kari) for use with ECDH,
02656  * return sequence size or negative on error */
02657 static int wc_CreateKeyAgreeRecipientInfo(PKCS7* pkcs7, const byte* cert,
02658                             word32 certSz, int keyAgreeAlgo, int blockKeySz,
02659                             int keyWrapAlgo, int keyEncAlgo, WC_RNG* rng,
02660                             byte* contentKeyPlain, byte* contentKeyEnc,
02661                             int* keyEncSz, byte* out, word32 outSz)
02662 {
02663     int ret = 0, idx = 0;
02664     int keySz, direction = 0;
02665 
02666     /* ASN.1 layout */
02667     int totalSz = 0;
02668     int kariSeqSz = 0;
02669     byte kariSeq[MAX_SEQ_SZ];           /* IMPLICIT [1] */
02670     int verSz = 0;
02671     byte ver[MAX_VERSION_SZ];
02672 
02673     int origIdOrKeySeqSz = 0;
02674     byte origIdOrKeySeq[MAX_SEQ_SZ];    /* IMPLICIT [0] */
02675     int origPubKeySeqSz = 0;
02676     byte origPubKeySeq[MAX_SEQ_SZ];     /* IMPLICIT [1] */
02677     int origAlgIdSz = 0;
02678     byte origAlgId[MAX_ALGO_SZ];
02679     int origPubKeyStrSz = 0;
02680     byte origPubKeyStr[MAX_OCTET_STR_SZ];
02681 
02682     /* optional user keying material */
02683     int ukmOctetSz = 0;
02684     byte ukmOctetStr[MAX_OCTET_STR_SZ];
02685     int ukmExplicitSz = 0;
02686     byte ukmExplicitSeq[MAX_SEQ_SZ];
02687 
02688     int keyEncryptAlgoIdSz = 0;
02689     byte keyEncryptAlgoId[MAX_ALGO_SZ];
02690     int keyWrapAlgSz = 0;
02691     byte keyWrapAlg[MAX_ALGO_SZ];
02692 
02693     int recipEncKeysSeqSz = 0;
02694     byte recipEncKeysSeq[MAX_SEQ_SZ];
02695     int recipEncKeySeqSz = 0;
02696     byte recipEncKeySeq[MAX_SEQ_SZ];
02697     int recipKeyIdSeqSz = 0;
02698     byte recipKeyIdSeq[MAX_SEQ_SZ];     /* IMPLICIT [0] */
02699     int subjKeyIdOctetSz = 0;
02700     byte subjKeyIdOctet[MAX_OCTET_STR_SZ];
02701     int encryptedKeyOctetSz = 0;
02702     byte encryptedKeyOctet[MAX_OCTET_STR_SZ];
02703 
02704     WC_PKCS7_KARI* kari;
02705 
02706     /* only supports ECDSA for now */
02707     if (keyAgreeAlgo != ECDSAk)
02708         return BAD_FUNC_ARG;
02709 
02710     /* set direction based on keyWrapAlgo */
02711     switch (keyWrapAlgo) {
02712 #ifndef NO_AES
02713     #ifdef WOLFSSL_AES_128
02714         case AES128_WRAP:
02715     #endif
02716     #ifdef WOLFSSL_AES_192
02717         case AES192_WRAP:
02718     #endif
02719     #ifdef WOLFSSL_AES_256
02720         case AES256_WRAP:
02721     #endif
02722             direction = AES_ENCRYPTION;
02723             break;
02724 #endif
02725         default:
02726             WOLFSSL_MSG("Unsupported key wrap algorithm");
02727             return BAD_KEYWRAP_ALG_E;
02728     }
02729 
02730     kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_ENCODE);
02731     if (kari == NULL)
02732         return MEMORY_E;
02733 
02734     /* set user keying material if available */
02735     if ((pkcs7->ukmSz > 0) && (pkcs7->ukm != NULL)) {
02736         kari->ukm = pkcs7->ukm;
02737         kari->ukmSz = pkcs7->ukmSz;
02738         kari->ukmOwner = 0;
02739     }
02740 
02741     /* parse recipient cert, get public key */
02742     ret = wc_PKCS7_KariParseRecipCert(kari, cert, certSz, NULL, 0);
02743     if (ret != 0) {
02744         wc_PKCS7_KariFree(kari);
02745         return ret;
02746     }
02747 
02748     /* generate sender ephemeral ECC key */
02749     ret = wc_PKCS7_KariGenerateEphemeralKey(kari, rng);
02750     if (ret != 0) {
02751         wc_PKCS7_KariFree(kari);
02752         return ret;
02753     }
02754 
02755     /* generate KEK (key encryption key) */
02756     ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapAlgo, keyEncAlgo);
02757     if (ret != 0) {
02758         wc_PKCS7_KariFree(kari);
02759         return ret;
02760     }
02761 
02762     /* encrypt CEK with KEK */
02763     keySz = wc_PKCS7_KariKeyWrap(contentKeyPlain, blockKeySz, kari->kek,
02764                         kari->kekSz, contentKeyEnc, *keyEncSz, keyWrapAlgo,
02765                         direction);
02766     if (keySz <= 0) {
02767         wc_PKCS7_KariFree(kari);
02768         return ret;
02769     }
02770     *keyEncSz = (word32)keySz;
02771 
02772     /* Start of RecipientEncryptedKeys */
02773 
02774     /* EncryptedKey */
02775     encryptedKeyOctetSz = SetOctetString(*keyEncSz, encryptedKeyOctet);
02776     totalSz += (encryptedKeyOctetSz + *keyEncSz);
02777 
02778     /* SubjectKeyIdentifier */
02779     subjKeyIdOctetSz = SetOctetString(KEYID_SIZE, subjKeyIdOctet);
02780     totalSz += (subjKeyIdOctetSz + KEYID_SIZE);
02781 
02782     /* RecipientKeyIdentifier IMPLICIT [0] */
02783     recipKeyIdSeqSz = SetImplicit(ASN_SEQUENCE, 0, subjKeyIdOctetSz +
02784                                   KEYID_SIZE, recipKeyIdSeq);
02785     totalSz += recipKeyIdSeqSz;
02786 
02787     /* RecipientEncryptedKey */
02788     recipEncKeySeqSz = SetSequence(totalSz, recipEncKeySeq);
02789     totalSz += recipEncKeySeqSz;
02790 
02791     /* RecipientEncryptedKeys */
02792     recipEncKeysSeqSz = SetSequence(totalSz, recipEncKeysSeq);
02793     totalSz += recipEncKeysSeqSz;
02794 
02795     /* Start of optional UserKeyingMaterial */
02796 
02797     if (kari->ukmSz > 0) {
02798         ukmOctetSz = SetOctetString(kari->ukmSz, ukmOctetStr);
02799         totalSz += (ukmOctetSz + kari->ukmSz);
02800 
02801         ukmExplicitSz = SetExplicit(1, ukmOctetSz + kari->ukmSz,
02802                                     ukmExplicitSeq);
02803         totalSz += ukmExplicitSz;
02804     }
02805 
02806     /* Start of KeyEncryptionAlgorithmIdentifier */
02807 
02808     /* KeyWrapAlgorithm */
02809     keyWrapAlgSz = SetAlgoID(keyWrapAlgo, keyWrapAlg, oidKeyWrapType, 0);
02810     totalSz += keyWrapAlgSz;
02811 
02812     /* KeyEncryptionAlgorithmIdentifier */
02813     keyEncryptAlgoIdSz = SetAlgoID(keyEncAlgo, keyEncryptAlgoId,
02814                                    oidCmsKeyAgreeType, keyWrapAlgSz);
02815     totalSz += keyEncryptAlgoIdSz;
02816 
02817     /* Start of OriginatorIdentifierOrKey */
02818 
02819     /* recipient ECPoint, public key */
02820     XMEMSET(origPubKeyStr, 0, sizeof(origPubKeyStr)); /* no unused bits */
02821     origPubKeyStr[0] = ASN_BIT_STRING;
02822     origPubKeyStrSz = SetLength(kari->senderKeyExportSz + 1,
02823                                 origPubKeyStr + 1) + 2;
02824     totalSz += (origPubKeyStrSz + kari->senderKeyExportSz);
02825 
02826     /* Originator AlgorithmIdentifier */
02827     origAlgIdSz = SetAlgoID(ECDSAk, origAlgId, oidKeyType, 0);
02828     totalSz += origAlgIdSz;
02829 
02830     /* outer OriginatorPublicKey IMPLICIT [1] */
02831     origPubKeySeqSz = SetImplicit(ASN_SEQUENCE, 1,
02832                                   origAlgIdSz + origPubKeyStrSz +
02833                                   kari->senderKeyExportSz, origPubKeySeq);
02834     totalSz += origPubKeySeqSz;
02835 
02836     /* outer OriginatorIdentiferOrKey IMPLICIT [0] */
02837     origIdOrKeySeqSz = SetImplicit(ASN_SEQUENCE, 0,
02838                                    origPubKeySeqSz + origAlgIdSz +
02839                                    origPubKeyStrSz + kari->senderKeyExportSz,
02840                                    origIdOrKeySeq);
02841     totalSz += origIdOrKeySeqSz;
02842 
02843     /* version, always 3 */
02844     verSz = SetMyVersion(3, ver, 0);
02845     totalSz += verSz;
02846 
02847     /* outer IMPLICIT [1] kari */
02848     kariSeqSz = SetImplicit(ASN_SEQUENCE, 1, totalSz, kariSeq);
02849     totalSz += kariSeqSz;
02850 
02851     if ((word32)totalSz > outSz) {
02852         WOLFSSL_MSG("KeyAgreeRecipientInfo output buffer too small");
02853         wc_PKCS7_KariFree(kari);
02854 
02855         return BUFFER_E;
02856     }
02857 
02858     XMEMCPY(out + idx, kariSeq, kariSeqSz);
02859     idx += kariSeqSz;
02860     XMEMCPY(out + idx, ver, verSz);
02861     idx += verSz;
02862 
02863     XMEMCPY(out + idx, origIdOrKeySeq, origIdOrKeySeqSz);
02864     idx += origIdOrKeySeqSz;
02865     XMEMCPY(out + idx, origPubKeySeq, origPubKeySeqSz);
02866     idx += origPubKeySeqSz;
02867     XMEMCPY(out + idx, origAlgId, origAlgIdSz);
02868     idx += origAlgIdSz;
02869     XMEMCPY(out + idx, origPubKeyStr, origPubKeyStrSz);
02870     idx += origPubKeyStrSz;
02871     /* ephemeral public key */
02872     XMEMCPY(out + idx, kari->senderKeyExport, kari->senderKeyExportSz);
02873     idx += kari->senderKeyExportSz;
02874 
02875     if (kari->ukmSz > 0) {
02876         XMEMCPY(out + idx, ukmExplicitSeq, ukmExplicitSz);
02877         idx += ukmExplicitSz;
02878         XMEMCPY(out + idx, ukmOctetStr, ukmOctetSz);
02879         idx += ukmOctetSz;
02880         XMEMCPY(out + idx, kari->ukm, kari->ukmSz);
02881         idx += kari->ukmSz;
02882     }
02883 
02884     XMEMCPY(out + idx, keyEncryptAlgoId, keyEncryptAlgoIdSz);
02885     idx += keyEncryptAlgoIdSz;
02886     XMEMCPY(out + idx, keyWrapAlg, keyWrapAlgSz);
02887     idx += keyWrapAlgSz;
02888 
02889     XMEMCPY(out + idx, recipEncKeysSeq, recipEncKeysSeqSz);
02890     idx += recipEncKeysSeqSz;
02891     XMEMCPY(out + idx, recipEncKeySeq, recipEncKeySeqSz);
02892     idx += recipEncKeySeqSz;
02893     XMEMCPY(out + idx, recipKeyIdSeq, recipKeyIdSeqSz);
02894     idx += recipKeyIdSeqSz;
02895     XMEMCPY(out + idx, subjKeyIdOctet, subjKeyIdOctetSz);
02896     idx += subjKeyIdOctetSz;
02897     /* subject key id */
02898     XMEMCPY(out + idx, kari->decoded->extSubjKeyId, KEYID_SIZE);
02899     idx += KEYID_SIZE;
02900     XMEMCPY(out + idx, encryptedKeyOctet, encryptedKeyOctetSz);
02901     idx += encryptedKeyOctetSz;
02902     /* encrypted CEK */
02903     XMEMCPY(out + idx, contentKeyEnc, *keyEncSz);
02904     idx += *keyEncSz;
02905 
02906     wc_PKCS7_KariFree(kari);
02907 
02908     return idx;
02909 }
02910 
02911 #endif /* HAVE_ECC */
02912 
02913 #ifndef NO_RSA
02914 
02915 /* create ASN.1 formatted RecipientInfo structure, returns sequence size */
02916 static int wc_CreateRecipientInfo(const byte* cert, word32 certSz,
02917                                   int keyEncAlgo, int blockKeySz,
02918                                   WC_RNG* rng, byte* contentKeyPlain,
02919                                   byte* contentKeyEnc, int* keyEncSz,
02920                                   byte* out, word32 outSz, void* heap)
02921 {
02922     word32 idx = 0;
02923     int ret = 0, totalSz = 0;
02924     int verSz, issuerSz, snSz, keyEncAlgSz;
02925     int issuerSeqSz, recipSeqSz, issuerSerialSeqSz;
02926     int encKeyOctetStrSz;
02927 
02928     byte ver[MAX_VERSION_SZ];
02929     byte issuerSerialSeq[MAX_SEQ_SZ];
02930     byte recipSeq[MAX_SEQ_SZ];
02931     byte issuerSeq[MAX_SEQ_SZ];
02932     byte encKeyOctetStr[MAX_OCTET_STR_SZ];
02933 
02934 #ifdef WOLFSSL_SMALL_STACK
02935     byte *serial;
02936     byte *keyAlgArray;
02937 
02938     RsaKey* pubKey;
02939     DecodedCert* decoded;
02940 
02941     serial = (byte*)XMALLOC(MAX_SN_SZ, heap, DYNAMIC_TYPE_TMP_BUFFER);
02942     keyAlgArray = (byte*)XMALLOC(MAX_SN_SZ, heap, DYNAMIC_TYPE_TMP_BUFFER);
02943     decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap,
02944                                                        DYNAMIC_TYPE_TMP_BUFFER);
02945 
02946     if (decoded == NULL || serial == NULL || keyAlgArray == NULL) {
02947         if (serial)      XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
02948         if (keyAlgArray) XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
02949         if (decoded)     XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
02950         return MEMORY_E;
02951     }
02952 
02953 #else
02954     byte serial[MAX_SN_SZ];
02955     byte keyAlgArray[MAX_ALGO_SZ];
02956 
02957     RsaKey stack_pubKey;
02958     RsaKey* pubKey = &stack_pubKey;
02959     DecodedCert stack_decoded;
02960     DecodedCert* decoded = &stack_decoded;
02961 #endif
02962 
02963     InitDecodedCert(decoded, (byte*)cert, certSz, heap);
02964     ret = ParseCert(decoded, CA_TYPE, NO_VERIFY, 0);
02965     if (ret < 0) {
02966         FreeDecodedCert(decoded);
02967 #ifdef WOLFSSL_SMALL_STACK
02968         XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
02969         XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
02970         XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
02971 #endif
02972         return ret;
02973     }
02974 
02975     /* version */
02976     verSz = SetMyVersion(0, ver, 0);
02977 
02978     /* IssuerAndSerialNumber */
02979     if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) {
02980         WOLFSSL_MSG("DecodedCert lacks raw issuer pointer and length");
02981         FreeDecodedCert(decoded);
02982 #ifdef WOLFSSL_SMALL_STACK
02983         XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
02984         XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
02985         XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
02986 #endif
02987         return -1;
02988     }
02989     issuerSz    = decoded->issuerRawLen;
02990     issuerSeqSz = SetSequence(issuerSz, issuerSeq);
02991 
02992     if (decoded->serialSz == 0) {
02993         WOLFSSL_MSG("DecodedCert missing serial number");
02994         FreeDecodedCert(decoded);
02995 #ifdef WOLFSSL_SMALL_STACK
02996         XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
02997         XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
02998         XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
02999 #endif
03000         return -1;
03001     }
03002     snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial, MAX_SN_SZ);
03003 
03004     issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz,
03005                                     issuerSerialSeq);
03006 
03007     /* KeyEncryptionAlgorithmIdentifier, only support RSA now */
03008     if (keyEncAlgo != RSAk) {
03009         FreeDecodedCert(decoded);
03010 #ifdef WOLFSSL_SMALL_STACK
03011         XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
03012         XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
03013         XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
03014 #endif
03015         return ALGO_ID_E;
03016     }
03017 
03018     keyEncAlgSz = SetAlgoID(keyEncAlgo, keyAlgArray, oidKeyType, 0);
03019     if (keyEncAlgSz == 0) {
03020         FreeDecodedCert(decoded);
03021 #ifdef WOLFSSL_SMALL_STACK
03022         XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
03023         XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
03024         XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
03025 #endif
03026         return BAD_FUNC_ARG;
03027     }
03028 
03029 #ifdef WOLFSSL_SMALL_STACK
03030     pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_TMP_BUFFER);
03031     if (pubKey == NULL) {
03032         FreeDecodedCert(decoded);
03033         XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
03034         XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
03035         XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
03036         return MEMORY_E;
03037     }
03038 #endif
03039 
03040     /* EncryptedKey */
03041     ret = wc_InitRsaKey_ex(pubKey, heap, INVALID_DEVID);
03042     if (ret != 0) {
03043         FreeDecodedCert(decoded);
03044 #ifdef WOLFSSL_SMALL_STACK
03045         XFREE(pubKey,      heap, DYNAMIC_TYPE_TMP_BUFFER);
03046         XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
03047         XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
03048         XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
03049 #endif
03050         return ret;
03051     }
03052 
03053     if (wc_RsaPublicKeyDecode(decoded->publicKey, &idx, pubKey,
03054                            decoded->pubKeySize) < 0) {
03055         WOLFSSL_MSG("ASN RSA key decode error");
03056         wc_FreeRsaKey(pubKey);
03057         FreeDecodedCert(decoded);
03058 #ifdef WOLFSSL_SMALL_STACK
03059         XFREE(pubKey,      heap, DYNAMIC_TYPE_TMP_BUFFER);
03060         XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
03061         XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
03062         XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
03063 #endif
03064         return PUBLIC_KEY_E;
03065     }
03066 
03067     *keyEncSz = wc_RsaPublicEncrypt(contentKeyPlain, blockKeySz, contentKeyEnc,
03068                                  MAX_ENCRYPTED_KEY_SZ, pubKey, rng);
03069     wc_FreeRsaKey(pubKey);
03070 
03071 #ifdef WOLFSSL_SMALL_STACK
03072     XFREE(pubKey, heap, DYNAMIC_TYPE_TMP_BUFFER);
03073 #endif
03074 
03075     if (*keyEncSz < 0) {
03076         WOLFSSL_MSG("RSA Public Encrypt failed");
03077         FreeDecodedCert(decoded);
03078 #ifdef WOLFSSL_SMALL_STACK
03079         XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
03080         XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
03081         XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
03082 #endif
03083         return *keyEncSz;
03084     }
03085 
03086     encKeyOctetStrSz = SetOctetString(*keyEncSz, encKeyOctetStr);
03087 
03088     /* RecipientInfo */
03089     recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz +
03090                              issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz +
03091                              *keyEncSz, recipSeq);
03092 
03093     if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz +
03094         keyEncAlgSz + encKeyOctetStrSz + *keyEncSz > (int)outSz) {
03095         WOLFSSL_MSG("RecipientInfo output buffer too small");
03096         FreeDecodedCert(decoded);
03097 #ifdef WOLFSSL_SMALL_STACK
03098         XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
03099         XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
03100         XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
03101 #endif
03102         return BUFFER_E;
03103     }
03104 
03105     XMEMCPY(out + totalSz, recipSeq, recipSeqSz);
03106     totalSz += recipSeqSz;
03107     XMEMCPY(out + totalSz, ver, verSz);
03108     totalSz += verSz;
03109     XMEMCPY(out + totalSz, issuerSerialSeq, issuerSerialSeqSz);
03110     totalSz += issuerSerialSeqSz;
03111     XMEMCPY(out + totalSz, issuerSeq, issuerSeqSz);
03112     totalSz += issuerSeqSz;
03113     XMEMCPY(out + totalSz, decoded->issuerRaw, issuerSz);
03114     totalSz += issuerSz;
03115     XMEMCPY(out + totalSz, serial, snSz);
03116     totalSz += snSz;
03117     XMEMCPY(out + totalSz, keyAlgArray, keyEncAlgSz);
03118     totalSz += keyEncAlgSz;
03119     XMEMCPY(out + totalSz, encKeyOctetStr, encKeyOctetStrSz);
03120     totalSz += encKeyOctetStrSz;
03121     XMEMCPY(out + totalSz, contentKeyEnc, *keyEncSz);
03122     totalSz += *keyEncSz;
03123 
03124     FreeDecodedCert(decoded);
03125 
03126 #ifdef WOLFSSL_SMALL_STACK
03127     XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
03128     XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
03129     XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
03130 #endif
03131 
03132     return totalSz;
03133 }
03134 #endif /* !NO_RSA */
03135 
03136 
03137 /* encrypt content using encryptOID algo */
03138 static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz,
03139                                    byte* iv, int ivSz, byte* in, int inSz,
03140                                    byte* out)
03141 {
03142     int ret;
03143 #ifndef NO_AES
03144     Aes  aes;
03145 #endif
03146 #ifndef NO_DES3
03147     Des  des;
03148     Des3 des3;
03149 #endif
03150 
03151     if (key == NULL || iv == NULL || in == NULL || out == NULL)
03152         return BAD_FUNC_ARG;
03153 
03154     switch (encryptOID) {
03155 #ifndef NO_AES
03156     #ifdef WOLFSSL_AES_128
03157         case AES128CBCb:
03158     #endif
03159     #ifdef WOLFSSL_AES_192
03160         case AES192CBCb:
03161     #endif
03162     #ifdef WOLFSSL_AES_256
03163         case AES256CBCb:
03164     #endif
03165             if (
03166                 #ifdef WOLFSSL_AES_128
03167                     (encryptOID == AES128CBCb && keySz != 16 ) ||
03168                 #endif
03169                 #ifdef WOLFSSL_AES_192
03170                     (encryptOID == AES192CBCb && keySz != 24 ) ||
03171                 #endif
03172                 #ifdef WOLFSSL_AES_256
03173                     (encryptOID == AES256CBCb && keySz != 32 ) ||
03174                 #endif
03175                     (ivSz  != AES_BLOCK_SIZE) )
03176                 return BAD_FUNC_ARG;
03177 
03178             ret = wc_AesSetKey(&aes, key, keySz, iv, AES_ENCRYPTION);
03179             if (ret == 0)
03180                 ret = wc_AesCbcEncrypt(&aes, out, in, inSz);
03181 
03182             break;
03183 #endif
03184 #ifndef NO_DES3
03185         case DESb:
03186             if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE)
03187                 return BAD_FUNC_ARG;
03188 
03189             ret = wc_Des_SetKey(&des, key, iv, DES_ENCRYPTION);
03190             if (ret == 0)
03191                 ret = wc_Des_CbcEncrypt(&des, out, in, inSz);
03192 
03193             break;
03194 
03195         case DES3b:
03196             if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE)
03197                 return BAD_FUNC_ARG;
03198 
03199             ret = wc_Des3_SetKey(&des3, key, iv, DES_ENCRYPTION);
03200             if (ret == 0)
03201                 ret = wc_Des3_CbcEncrypt(&des3, out, in, inSz);
03202 
03203             break;
03204 #endif
03205         default:
03206             WOLFSSL_MSG("Unsupported content cipher type");
03207             return ALGO_ID_E;
03208     };
03209 
03210     return ret;
03211 }
03212 
03213 
03214 /* decrypt content using encryptOID algo */
03215 static int wc_PKCS7_DecryptContent(int encryptOID, byte* key, int keySz,
03216                                    byte* iv, int ivSz, byte* in, int inSz,
03217                                    byte* out)
03218 {
03219     int ret;
03220 #ifndef NO_AES
03221     Aes  aes;
03222 #endif
03223 #ifndef NO_DES3
03224     Des  des;
03225     Des3 des3;
03226 #endif
03227 
03228     if (key == NULL || iv == NULL || in == NULL || out == NULL)
03229         return BAD_FUNC_ARG;
03230 
03231     switch (encryptOID) {
03232 #ifndef NO_AES
03233     #ifdef WOLFSSL_AES_128
03234         case AES128CBCb:
03235     #endif
03236     #ifdef WOLFSSL_AES_192
03237         case AES192CBCb:
03238     #endif
03239     #ifdef WOLFSSL_AES_256
03240         case AES256CBCb:
03241     #endif
03242             if (
03243                 #ifdef WOLFSSL_AES_128
03244                     (encryptOID == AES128CBCb && keySz != 16 ) ||
03245                 #endif
03246                 #ifdef WOLFSSL_AES_192
03247                     (encryptOID == AES192CBCb && keySz != 24 ) ||
03248                 #endif
03249                 #ifdef WOLFSSL_AES_256
03250                     (encryptOID == AES256CBCb && keySz != 32 ) ||
03251                 #endif
03252                     (ivSz  != AES_BLOCK_SIZE) )
03253                 return BAD_FUNC_ARG;
03254 
03255             ret = wc_AesSetKey(&aes, key, keySz, iv, AES_DECRYPTION);
03256             if (ret == 0)
03257                 ret = wc_AesCbcDecrypt(&aes, out, in, inSz);
03258 
03259             break;
03260 #endif
03261 #ifndef NO_DES3
03262         case DESb:
03263             if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE)
03264                 return BAD_FUNC_ARG;
03265 
03266             ret = wc_Des_SetKey(&des, key, iv, DES_DECRYPTION);
03267             if (ret == 0)
03268                 ret = wc_Des_CbcDecrypt(&des, out, in, inSz);
03269 
03270             break;
03271         case DES3b:
03272             if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE)
03273                 return BAD_FUNC_ARG;
03274 
03275             ret = wc_Des3_SetKey(&des3, key, iv, DES_DECRYPTION);
03276             if (ret == 0)
03277                 ret = wc_Des3_CbcDecrypt(&des3, out, in, inSz);
03278 
03279             break;
03280 #endif
03281         default:
03282             WOLFSSL_MSG("Unsupported content cipher type");
03283             return ALGO_ID_E;
03284     };
03285 
03286     return ret;
03287 }
03288 
03289 
03290 /* generate random IV, place in iv, return 0 on success negative on error */
03291 static int wc_PKCS7_GenerateIV(PKCS7* pkcs7, WC_RNG* rng, byte* iv, word32 ivSz)
03292 {
03293     int ret;
03294     WC_RNG* rnd = NULL;
03295 
03296     if (iv == NULL || ivSz == 0)
03297         return BAD_FUNC_ARG;
03298 
03299     /* input RNG is optional, init local one if input rng is NULL */
03300     if (rng == NULL) {
03301         rnd = (WC_RNG*)XMALLOC(sizeof(WC_RNG), pkcs7->heap, DYNAMIC_TYPE_RNG);
03302         if (rnd == NULL)
03303             return MEMORY_E;
03304 
03305         ret = wc_InitRng_ex(rnd, pkcs7->heap, pkcs7->devId);
03306         if (ret != 0) {
03307             XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG);
03308             return ret;
03309         }
03310 
03311     } else {
03312         rnd = rng;
03313     }
03314 
03315     ret = wc_RNG_GenerateBlock(rnd, iv, ivSz);
03316 
03317     if (rng == NULL) {
03318         wc_FreeRng(rnd);
03319         XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG);
03320     }
03321 
03322     return ret;
03323 }
03324 
03325 
03326 /* return size of padded data, padded to blockSz chunks, or negative on error */
03327 int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz)
03328 {
03329     int padSz;
03330 
03331     if (blockSz == 0)
03332         return BAD_FUNC_ARG;
03333 
03334     padSz = blockSz - (inputSz % blockSz);
03335 
03336     return padSz;
03337 }
03338 
03339 
03340 /* pad input data to blockSz chunk, place in outSz. out must be big enough
03341  * for input + pad bytes. See wc_PKCS7_GetPadSize() helper. */
03342 int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz,
03343                      word32 blockSz)
03344 {
03345     int i, padSz;
03346 
03347     if (in == NULL  || inSz == 0 ||
03348         out == NULL || outSz == 0)
03349         return BAD_FUNC_ARG;
03350 
03351     padSz = wc_PKCS7_GetPadSize(inSz, blockSz);
03352 
03353     if (outSz < (inSz + padSz))
03354         return BAD_FUNC_ARG;
03355 
03356     XMEMCPY(out, in, inSz);
03357 
03358     for (i = 0; i < padSz; i++) {
03359         out[inSz + i] = (byte)padSz;
03360     }
03361 
03362     return inSz + padSz;
03363 }
03364 
03365 
03366 /* build PKCS#7 envelopedData content type, return enveloped size */
03367 int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
03368 {
03369     int ret, idx = 0;
03370     int totalSz, padSz, encryptedOutSz;
03371 
03372     int contentInfoSeqSz, outerContentTypeSz, outerContentSz;
03373     byte contentInfoSeq[MAX_SEQ_SZ];
03374     byte outerContentType[MAX_ALGO_SZ];
03375     byte outerContent[MAX_SEQ_SZ];
03376 
03377     int envDataSeqSz, verSz;
03378     byte envDataSeq[MAX_SEQ_SZ];
03379     byte ver[MAX_VERSION_SZ];
03380 
03381     WC_RNG rng;
03382     int contentKeyEncSz, blockSz, blockKeySz;
03383     byte contentKeyPlain[MAX_CONTENT_KEY_LEN];
03384 #ifdef WOLFSSL_SMALL_STACK
03385     byte* contentKeyEnc;
03386 #else
03387     byte contentKeyEnc[MAX_ENCRYPTED_KEY_SZ];
03388 #endif
03389     byte* plain;
03390     byte* encryptedContent;
03391 
03392     int recipSz, recipSetSz;
03393 #ifdef WOLFSSL_SMALL_STACK
03394     byte* recip;
03395 #else
03396     byte recip[MAX_RECIP_SZ];
03397 #endif
03398     byte recipSet[MAX_SET_SZ];
03399 
03400     int encContentOctetSz, encContentSeqSz, contentTypeSz;
03401     int contentEncAlgoSz, ivOctetStringSz;
03402     byte encContentSeq[MAX_SEQ_SZ];
03403     byte contentType[MAX_ALGO_SZ];
03404     byte contentEncAlgo[MAX_ALGO_SZ];
03405     byte tmpIv[MAX_CONTENT_IV_SIZE];
03406     byte ivOctetString[MAX_OCTET_STR_SZ];
03407     byte encContentOctet[MAX_OCTET_STR_SZ];
03408 
03409     if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
03410         pkcs7->encryptOID == 0 || pkcs7->singleCert == NULL ||
03411         pkcs7->publicKeyOID == 0)
03412         return BAD_FUNC_ARG;
03413 
03414     if (output == NULL || outputSz == 0)
03415         return BAD_FUNC_ARG;
03416 
03417     blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
03418     if (blockKeySz < 0)
03419         return blockKeySz;
03420 
03421     blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID);
03422     if (blockSz < 0)
03423         return blockSz;
03424 
03425     /* outer content type */
03426     outerContentTypeSz = wc_SetContentType(ENVELOPED_DATA, outerContentType);
03427 
03428     /* version, defined as 0 in RFC 2315 */
03429 #ifdef HAVE_ECC
03430     if (pkcs7->publicKeyOID == ECDSAk) {
03431         verSz = SetMyVersion(2, ver, 0);
03432     } else
03433 #endif
03434     {
03435         verSz = SetMyVersion(0, ver, 0);
03436     }
03437 
03438     /* generate random content encryption key */
03439     ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
03440     if (ret != 0)
03441         return ret;
03442 
03443     ret = wc_RNG_GenerateBlock(&rng, contentKeyPlain, blockKeySz);
03444     if (ret != 0) {
03445         wc_FreeRng(&rng);
03446         return ret;
03447     }
03448 
03449 #ifdef WOLFSSL_SMALL_STACK
03450     recip         = (byte*)XMALLOC(MAX_RECIP_SZ, pkcs7->heap,
03451                                                        DYNAMIC_TYPE_PKCS7);
03452     contentKeyEnc = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
03453                                                        DYNAMIC_TYPE_PKCS7);
03454     if (contentKeyEnc == NULL || recip == NULL) {
03455         if (recip)         XFREE(recip,         pkcs7->heap, DYNAMIC_TYPE_PKCS7);
03456         if (contentKeyEnc) XFREE(contentKeyEnc, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
03457         wc_FreeRng(&rng);
03458         return MEMORY_E;
03459     }
03460 #endif
03461     contentKeyEncSz = MAX_ENCRYPTED_KEY_SZ;
03462 
03463     /* build RecipientInfo, only handle 1 for now */
03464     switch (pkcs7->publicKeyOID) {
03465 #ifndef NO_RSA
03466         case RSAk:
03467             recipSz = wc_CreateRecipientInfo(pkcs7->singleCert,
03468                                     pkcs7->singleCertSz,
03469                                     pkcs7->publicKeyOID,
03470                                     blockKeySz, &rng, contentKeyPlain,
03471                                     contentKeyEnc, &contentKeyEncSz, recip,
03472                                     MAX_RECIP_SZ, pkcs7->heap);
03473             break;
03474 #endif
03475 #ifdef HAVE_ECC
03476         case ECDSAk:
03477             recipSz = wc_CreateKeyAgreeRecipientInfo(pkcs7, pkcs7->singleCert,
03478                                     pkcs7->singleCertSz,
03479                                     pkcs7->publicKeyOID,
03480                                     blockKeySz, pkcs7->keyWrapOID,
03481                                     pkcs7->keyAgreeOID, &rng,
03482                                     contentKeyPlain, contentKeyEnc,
03483                                     &contentKeyEncSz, recip, MAX_RECIP_SZ);
03484             break;
03485 #endif
03486 
03487         default:
03488             WOLFSSL_MSG("Unsupported RecipientInfo public key type");
03489             return BAD_FUNC_ARG;
03490     };
03491 
03492     ForceZero(contentKeyEnc, MAX_ENCRYPTED_KEY_SZ);
03493 
03494 #ifdef WOLFSSL_SMALL_STACK
03495     XFREE(contentKeyEnc, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
03496 #endif
03497 
03498     if (recipSz < 0) {
03499         WOLFSSL_MSG("Failed to create RecipientInfo");
03500         wc_FreeRng(&rng);
03501 #ifdef WOLFSSL_SMALL_STACK
03502         XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03503 #endif
03504         return recipSz;
03505     }
03506     recipSetSz = SetSet(recipSz, recipSet);
03507 
03508     /* generate IV for block cipher */
03509     ret = wc_PKCS7_GenerateIV(pkcs7, &rng, tmpIv, blockSz);
03510     wc_FreeRng(&rng);
03511     if (ret != 0) {
03512 #ifdef WOLFSSL_SMALL_STACK
03513         XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03514 #endif
03515         return ret;
03516     }
03517 
03518     /* EncryptedContentInfo */
03519     contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType);
03520     if (contentTypeSz == 0) {
03521 #ifdef WOLFSSL_SMALL_STACK
03522         XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03523 #endif
03524         return BAD_FUNC_ARG;
03525     }
03526 
03527     /* allocate encrypted content buffer and PKCS#7 padding */
03528     padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz);
03529     if (padSz < 0)
03530         return padSz;
03531 
03532     encryptedOutSz = pkcs7->contentSz + padSz;
03533 
03534     plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap,
03535                            DYNAMIC_TYPE_PKCS7);
03536     if (plain == NULL)
03537         return MEMORY_E;
03538 
03539     ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain,
03540                            encryptedOutSz, blockSz);
03541     if (ret < 0) {
03542         XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
03543         return ret;
03544     }
03545 
03546     encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap,
03547                                       DYNAMIC_TYPE_PKCS7);
03548     if (encryptedContent == NULL) {
03549         XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
03550 #ifdef WOLFSSL_SMALL_STACK
03551         XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03552 #endif
03553         return MEMORY_E;
03554     }
03555 
03556     /* put together IV OCTET STRING */
03557     ivOctetStringSz = SetOctetString(blockSz, ivOctetString);
03558 
03559     /* build up our ContentEncryptionAlgorithmIdentifier sequence,
03560      * adding (ivOctetStringSz + blockSz) for IV OCTET STRING */
03561     contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
03562                                  oidBlkType, ivOctetStringSz + blockSz);
03563 
03564     if (contentEncAlgoSz == 0) {
03565         XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
03566         XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
03567 #ifdef WOLFSSL_SMALL_STACK
03568         XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
03569 #endif
03570         return BAD_FUNC_ARG;
03571     }
03572 
03573     /* encrypt content */
03574     ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, contentKeyPlain,
03575             blockKeySz, tmpIv, blockSz, plain, encryptedOutSz,
03576             encryptedContent);
03577 
03578     if (ret != 0) {
03579         XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
03580         XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
03581 #ifdef WOLFSSL_SMALL_STACK
03582         XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
03583 #endif
03584         return ret;
03585     }
03586 
03587     encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz,
03588                                     encContentOctet);
03589 
03590     encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
03591                                   ivOctetStringSz + blockSz +
03592                                   encContentOctetSz + encryptedOutSz,
03593                                   encContentSeq);
03594 
03595     /* keep track of sizes for outer wrapper layering */
03596     totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz +
03597               contentEncAlgoSz + ivOctetStringSz + blockSz +
03598               encContentOctetSz + encryptedOutSz;
03599 
03600     /* EnvelopedData */
03601     envDataSeqSz = SetSequence(totalSz, envDataSeq);
03602     totalSz += envDataSeqSz;
03603 
03604     /* outer content */
03605     outerContentSz = SetExplicit(0, totalSz, outerContent);
03606     totalSz += outerContentTypeSz;
03607     totalSz += outerContentSz;
03608 
03609     /* ContentInfo */
03610     contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
03611     totalSz += contentInfoSeqSz;
03612 
03613     if (totalSz > (int)outputSz) {
03614         WOLFSSL_MSG("Pkcs7_encrypt output buffer too small");
03615         XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
03616         XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03617 #ifdef WOLFSSL_SMALL_STACK
03618         XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03619 #endif
03620         return BUFFER_E;
03621     }
03622 
03623     XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz);
03624     idx += contentInfoSeqSz;
03625     XMEMCPY(output + idx, outerContentType, outerContentTypeSz);
03626     idx += outerContentTypeSz;
03627     XMEMCPY(output + idx, outerContent, outerContentSz);
03628     idx += outerContentSz;
03629     XMEMCPY(output + idx, envDataSeq, envDataSeqSz);
03630     idx += envDataSeqSz;
03631     XMEMCPY(output + idx, ver, verSz);
03632     idx += verSz;
03633     XMEMCPY(output + idx, recipSet, recipSetSz);
03634     idx += recipSetSz;
03635     XMEMCPY(output + idx, recip, recipSz);
03636     idx += recipSz;
03637     XMEMCPY(output + idx, encContentSeq, encContentSeqSz);
03638     idx += encContentSeqSz;
03639     XMEMCPY(output + idx, contentType, contentTypeSz);
03640     idx += contentTypeSz;
03641     XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz);
03642     idx += contentEncAlgoSz;
03643     XMEMCPY(output + idx, ivOctetString, ivOctetStringSz);
03644     idx += ivOctetStringSz;
03645     XMEMCPY(output + idx, tmpIv, blockSz);
03646     idx += blockSz;
03647     XMEMCPY(output + idx, encContentOctet, encContentOctetSz);
03648     idx += encContentOctetSz;
03649     XMEMCPY(output + idx, encryptedContent, encryptedOutSz);
03650     idx += encryptedOutSz;
03651 
03652     ForceZero(contentKeyPlain, MAX_CONTENT_KEY_LEN);
03653 
03654     XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
03655     XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
03656 
03657 #ifdef WOLFSSL_SMALL_STACK
03658     XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03659 #endif
03660 
03661     return idx;
03662 }
03663 
03664 #ifndef NO_RSA
03665 /* decode KeyTransRecipientInfo (ktri), return 0 on success, <0 on error */
03666 static int wc_PKCS7_DecodeKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
03667                                word32* idx, byte* decryptedKey,
03668                                word32* decryptedKeySz, int* recipFound)
03669 {
03670     int length, encryptedKeySz, ret;
03671     int keySz;
03672     word32 encOID;
03673     word32 keyIdx;
03674     byte   issuerHash[KEYID_SIZE];
03675     byte*  outKey = NULL;
03676 
03677 #ifdef WC_RSA_BLINDING
03678     WC_RNG rng;
03679 #endif
03680 
03681 #ifdef WOLFSSL_SMALL_STACK
03682     mp_int* serialNum;
03683     byte* encryptedKey;
03684     RsaKey* privKey;
03685 #else
03686     mp_int stack_serialNum;
03687     mp_int* serialNum = &stack_serialNum;
03688     byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
03689 
03690     RsaKey stack_privKey;
03691     RsaKey* privKey = &stack_privKey;
03692 #endif
03693 
03694     /* remove IssuerAndSerialNumber */
03695     if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
03696         return ASN_PARSE_E;
03697 
03698     if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0)
03699         return ASN_PARSE_E;
03700 
03701     /* if we found correct recipient, issuer hashes will match */
03702     if (XMEMCMP(issuerHash, pkcs7->issuerHash, KEYID_SIZE) == 0) {
03703         *recipFound = 1;
03704     }
03705 
03706 #ifdef WOLFSSL_SMALL_STACK
03707     serialNum = (mp_int*)XMALLOC(sizeof(mp_int), pkcs7->heap,
03708                                  DYNAMIC_TYPE_TMP_BUFFER);
03709     if (serialNum == NULL)
03710         return MEMORY_E;
03711 #endif
03712 
03713     if (GetInt(serialNum, pkiMsg, idx, pkiMsgSz) < 0) {
03714 #ifdef WOLFSSL_SMALL_STACK
03715         XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03716 #endif
03717         return ASN_PARSE_E;
03718     }
03719 
03720     mp_clear(serialNum);
03721 
03722 #ifdef WOLFSSL_SMALL_STACK
03723     XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03724 #endif
03725 
03726     if (GetAlgoId(pkiMsg, idx, &encOID, oidKeyType, pkiMsgSz) < 0)
03727         return ASN_PARSE_E;
03728 
03729     /* key encryption algorithm must be RSA for now */
03730     if (encOID != RSAk)
03731         return ALGO_ID_E;
03732 
03733     /* read encryptedKey */
03734 #ifdef WOLFSSL_SMALL_STACK
03735     encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
03736                                   DYNAMIC_TYPE_TMP_BUFFER);
03737     if (encryptedKey == NULL)
03738         return MEMORY_E;
03739 #endif
03740 
03741     if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) {
03742 #ifdef WOLFSSL_SMALL_STACK
03743         XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03744 #endif
03745         return ASN_PARSE_E;
03746     }
03747 
03748     if (GetLength(pkiMsg, idx, &encryptedKeySz, pkiMsgSz) < 0) {
03749 #ifdef WOLFSSL_SMALL_STACK
03750         XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03751 #endif
03752         return ASN_PARSE_E;
03753     }
03754 
03755     if (*recipFound == 1)
03756         XMEMCPY(encryptedKey, &pkiMsg[*idx], encryptedKeySz);
03757     *idx += encryptedKeySz;
03758 
03759     /* load private key */
03760 #ifdef WOLFSSL_SMALL_STACK
03761     privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap,
03762         DYNAMIC_TYPE_TMP_BUFFER);
03763     if (privKey == NULL) {
03764         XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03765         return MEMORY_E;
03766     }
03767 #endif
03768 
03769     ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, INVALID_DEVID);
03770     if (ret != 0) {
03771 #ifdef WOLFSSL_SMALL_STACK
03772         XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03773         XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03774 #endif
03775         return ret;
03776     }
03777 
03778     if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) {
03779         keyIdx = 0;
03780         ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &keyIdx, privKey,
03781                                      pkcs7->privateKeySz);
03782     }
03783     else if (pkcs7->devId == INVALID_DEVID) {
03784         ret = BAD_FUNC_ARG;
03785     }
03786     if (ret != 0) {
03787         WOLFSSL_MSG("Failed to decode RSA private key");
03788         wc_FreeRsaKey(privKey);
03789 #ifdef WOLFSSL_SMALL_STACK
03790         XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03791         XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03792 #endif
03793         return ret;
03794     }
03795 
03796     /* decrypt encryptedKey */
03797     #ifdef WC_RSA_BLINDING
03798     ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
03799     if (ret == 0) {
03800         ret = wc_RsaSetRNG(privKey, &rng);
03801     }
03802     #endif
03803     if (ret == 0) {
03804         keySz = wc_RsaPrivateDecryptInline(encryptedKey, encryptedKeySz,
03805                                            &outKey, privKey);
03806         #ifdef WC_RSA_BLINDING
03807             wc_FreeRng(&rng);
03808         #endif
03809     } else {
03810         keySz = ret;
03811     }
03812     wc_FreeRsaKey(privKey);
03813 
03814     if (keySz <= 0 || outKey == NULL) {
03815         ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ);
03816 #ifdef WOLFSSL_SMALL_STACK
03817         XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03818         XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03819 #endif
03820         return keySz;
03821     } else {
03822         *decryptedKeySz = keySz;
03823         XMEMCPY(decryptedKey, outKey, keySz);
03824         ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ);
03825     }
03826 
03827 #ifdef WOLFSSL_SMALL_STACK
03828     XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03829     XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
03830 #endif
03831 
03832     return 0;
03833 }
03834 #endif /* !NO_RSA */
03835 
03836 #ifdef HAVE_ECC
03837 
03838 /* remove ASN.1 OriginatorIdentifierOrKey, return 0 on success, <0 on error */
03839 static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari,
03840                         byte* pkiMsg, word32 pkiMsgSz, word32* idx)
03841 {
03842     int ret, length;
03843     word32 keyOID;
03844 
03845     if (kari == NULL || pkiMsg == NULL || idx == NULL)
03846         return BAD_FUNC_ARG;
03847 
03848     /* remove OriginatorIdentifierOrKey */
03849     if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
03850         (*idx)++;
03851         if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
03852             return ASN_PARSE_E;
03853 
03854     } else {
03855         return ASN_PARSE_E;
03856     }
03857 
03858     /* remove OriginatorPublicKey */
03859     if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
03860         (*idx)++;
03861         if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
03862             return ASN_PARSE_E;
03863 
03864     } else {
03865         return ASN_PARSE_E;
03866     }
03867 
03868     /* remove AlgorithmIdentifier */
03869     if (GetAlgoId(pkiMsg, idx, &keyOID, oidKeyType, pkiMsgSz) < 0)
03870         return ASN_PARSE_E;
03871 
03872     if (keyOID != ECDSAk)
03873         return ASN_PARSE_E;
03874 
03875     /* remove ECPoint BIT STRING */
03876     if ((pkiMsgSz > (*idx + 1)) && (pkiMsg[(*idx)++] != ASN_BIT_STRING))
03877         return ASN_PARSE_E;
03878 
03879     if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
03880         return ASN_PARSE_E;
03881 
03882     if ((pkiMsgSz < (*idx + 1)) || (pkiMsg[(*idx)++] != 0x00))
03883         return ASN_EXPECT_0_E;
03884 
03885     /* get sender ephemeral public ECDSA key */
03886     ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId);
03887     if (ret != 0)
03888         return ret;
03889 
03890     kari->senderKeyInit = 1;
03891 
03892     /* length-1 for unused bits counter */
03893     ret = wc_ecc_import_x963(pkiMsg + (*idx), length - 1, kari->senderKey);
03894     if (ret != 0)
03895         return ret;
03896 
03897     (*idx) += length - 1;
03898 
03899     return 0;
03900 }
03901 
03902 
03903 /* remove optional UserKeyingMaterial if available, return 0 on success,
03904  * < 0 on error */
03905 static int wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI* kari,
03906                         byte* pkiMsg, word32 pkiMsgSz, word32* idx)
03907 {
03908     int length;
03909     word32 savedIdx;
03910 
03911     if (kari == NULL || pkiMsg == NULL || idx == NULL)
03912         return BAD_FUNC_ARG;
03913 
03914     savedIdx = *idx;
03915 
03916     /* starts with EXPLICIT [1] */
03917     if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
03918         *idx = savedIdx;
03919         return 0;
03920     }
03921 
03922     if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) {
03923         *idx = savedIdx;
03924         return 0;
03925     }
03926 
03927     /* get OCTET STRING */
03928     if ( (pkiMsgSz > ((*idx) + 1)) &&
03929          (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) {
03930         *idx = savedIdx;
03931         return 0;
03932     }
03933 
03934     if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) {
03935         *idx = savedIdx;
03936         return 0;
03937     }
03938 
03939     kari->ukm = NULL;
03940     if (length > 0) {
03941         kari->ukm = (byte*)XMALLOC(length, kari->heap, DYNAMIC_TYPE_PKCS7);
03942         if (kari->ukm == NULL)
03943             return MEMORY_E;
03944 
03945         XMEMCPY(kari->ukm, pkiMsg + (*idx), length);
03946         kari->ukmOwner = 1;
03947     }
03948 
03949     (*idx) += length;
03950     kari->ukmSz = length;
03951 
03952     return 0;
03953 }
03954 
03955 
03956 /* remove ASN.1 KeyEncryptionAlgorithmIdentifier, return 0 on success,
03957  * < 0 on error */
03958 static int wc_PKCS7_KariGetKeyEncryptionAlgorithmId(WC_PKCS7_KARI* kari,
03959                         byte* pkiMsg, word32 pkiMsgSz, word32* idx,
03960                         word32* keyAgreeOID, word32* keyWrapOID)
03961 {
03962     if (kari == NULL || pkiMsg == NULL || idx == NULL ||
03963         keyAgreeOID == NULL || keyWrapOID == NULL)
03964         return BAD_FUNC_ARG;
03965 
03966     /* remove KeyEncryptionAlgorithmIdentifier */
03967     if (GetAlgoId(pkiMsg, idx, keyAgreeOID, oidCmsKeyAgreeType,
03968                   pkiMsgSz) < 0)
03969         return ASN_PARSE_E;
03970 
03971     /* remove KeyWrapAlgorithm, stored in parameter of KeyEncAlgoId */
03972     if (GetAlgoId(pkiMsg, idx, keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0)
03973         return ASN_PARSE_E;
03974 
03975     return 0;
03976 }
03977 
03978 
03979 /* remove ASN.1 SubjectKeyIdentifier, return 0 on success, < 0 on error
03980  * if subject key ID matches, recipFound is set to 1 */
03981 static int wc_PKCS7_KariGetSubjectKeyIdentifier(WC_PKCS7_KARI* kari,
03982                         byte* pkiMsg, word32 pkiMsgSz, word32* idx,
03983                         int* recipFound)
03984 {
03985     int length;
03986     byte subjKeyId[KEYID_SIZE];
03987 
03988     if (kari == NULL || pkiMsg == NULL || idx == NULL || recipFound == NULL)
03989         return BAD_FUNC_ARG;
03990 
03991     /* remove RecipientKeyIdentifier IMPLICIT [0] */
03992     if ( (pkiMsgSz > (*idx + 1)) &&
03993          (pkiMsg[(*idx)++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) {
03994 
03995         if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
03996             return ASN_PARSE_E;
03997 
03998     } else {
03999         return ASN_PARSE_E;
04000     }
04001 
04002     /* remove SubjectKeyIdentifier */
04003     if ( (pkiMsgSz > (*idx + 1)) &&
04004          (pkiMsg[(*idx)++] != ASN_OCTET_STRING) )
04005         return ASN_PARSE_E;
04006 
04007     if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
04008         return ASN_PARSE_E;
04009 
04010     if (length != KEYID_SIZE)
04011         return ASN_PARSE_E;
04012 
04013     XMEMCPY(subjKeyId, pkiMsg + (*idx), KEYID_SIZE);
04014     (*idx) += length;
04015 
04016     /* subject key id should match if recipient found */
04017     if (XMEMCMP(subjKeyId, kari->decoded->extSubjKeyId, KEYID_SIZE) == 0) {
04018         *recipFound = 1;
04019     }
04020 
04021     return 0;
04022 }
04023 
04024 
04025 /* remove ASN.1 IssuerAndSerialNumber, return 0 on success, < 0 on error
04026  * if issuer and serial number match, recipFound is set to 1 */
04027 static int wc_PKCS7_KariGetIssuerAndSerialNumber(WC_PKCS7_KARI* kari,
04028                         byte* pkiMsg, word32 pkiMsgSz, word32* idx,
04029                         int* recipFound)
04030 {
04031     int length, ret;
04032     byte issuerHash[KEYID_SIZE];
04033 #ifdef WOLFSSL_SMALL_STACK
04034     mp_int* serial;
04035     mp_int* recipSerial;
04036 #else
04037     mp_int  stack_serial;
04038     mp_int* serial = &stack_serial;
04039 
04040     mp_int  stack_recipSerial;
04041     mp_int* recipSerial = &stack_recipSerial;
04042 #endif
04043 
04044     /* remove IssuerAndSerialNumber */
04045     if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
04046         return ASN_PARSE_E;
04047 
04048     if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0)
04049         return ASN_PARSE_E;
04050 
04051     /* if we found correct recipient, issuer hashes will match */
04052     if (XMEMCMP(issuerHash, kari->decoded->issuerHash, KEYID_SIZE) == 0) {
04053         *recipFound = 1;
04054     }
04055 
04056 #ifdef WOLFSSL_SMALL_STACK
04057     serial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap,
04058                               DYNAMIC_TYPE_TMP_BUFFER);
04059     if (serial == NULL)
04060         return MEMORY_E;
04061 
04062     recipSerial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap,
04063                                    DYNAMIC_TYPE_TMP_BUFFER);
04064     if (recipSerial == NULL) {
04065         XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
04066         return MEMORY_E;
04067     }
04068 #endif
04069 
04070     if (GetInt(serial, pkiMsg, idx, pkiMsgSz) < 0) {
04071 #ifdef WOLFSSL_SMALL_STACK
04072         XFREE(serial,      kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
04073         XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
04074 #endif
04075         return ASN_PARSE_E;
04076     }
04077 
04078     ret = mp_read_unsigned_bin(recipSerial, kari->decoded->serial,
04079                              kari->decoded->serialSz);
04080     if (ret != MP_OKAY) {
04081         mp_clear(serial);
04082         WOLFSSL_MSG("Failed to parse CMS recipient serial number");
04083 #ifdef WOLFSSL_SMALL_STACK
04084         XFREE(serial,      kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
04085         XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
04086 #endif
04087         return ret;
04088     }
04089 
04090     if (mp_cmp(recipSerial, serial) != MP_EQ) {
04091         mp_clear(serial);
04092         mp_clear(recipSerial);
04093         WOLFSSL_MSG("CMS serial number does not match recipient");
04094 #ifdef WOLFSSL_SMALL_STACK
04095         XFREE(serial,      kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
04096         XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
04097 #endif
04098         return PKCS7_RECIP_E;
04099     }
04100 
04101     mp_clear(serial);
04102     mp_clear(recipSerial);
04103 
04104 #ifdef WOLFSSL_SMALL_STACK
04105     XFREE(serial,      kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
04106     XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
04107 #endif
04108 
04109     return 0;
04110 }
04111 
04112 
04113 /* remove ASN.1 RecipientEncryptedKeys, return 0 on success, < 0 on error */
04114 static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari,
04115                         byte* pkiMsg, word32 pkiMsgSz, word32* idx,
04116                         int* recipFound, byte* encryptedKey,
04117                         int* encryptedKeySz)
04118 {
04119     int length;
04120     int ret = 0;
04121 
04122     if (kari == NULL || pkiMsg == NULL || idx == NULL ||
04123         recipFound == NULL || encryptedKey == NULL)
04124         return BAD_FUNC_ARG;
04125 
04126     /* remove RecipientEncryptedKeys */
04127     if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
04128         return ASN_PARSE_E;
04129 
04130     /* remove RecipientEncryptedKeys */
04131     if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
04132         return ASN_PARSE_E;
04133 
04134     /* KeyAgreeRecipientIdentifier is CHOICE of IssuerAndSerialNumber
04135      * or [0] IMMPLICIT RecipientKeyIdentifier */
04136     if ( (pkiMsgSz > (*idx + 1)) &&
04137          (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) {
04138 
04139         /* try to get RecipientKeyIdentifier */
04140         ret = wc_PKCS7_KariGetSubjectKeyIdentifier(kari, pkiMsg, pkiMsgSz,
04141                                                    idx, recipFound);
04142     } else {
04143         /* try to get IssuerAndSerialNumber */
04144         ret = wc_PKCS7_KariGetIssuerAndSerialNumber(kari, pkiMsg, pkiMsgSz,
04145                                                     idx, recipFound);
04146     }
04147 
04148     /* if we don't have either option, malformed CMS */
04149     if (ret != 0)
04150         return ret;
04151 
04152     /* remove EncryptedKey */
04153     if ( (pkiMsgSz > (*idx + 1)) &&
04154          (pkiMsg[(*idx)++] != ASN_OCTET_STRING) )
04155         return ASN_PARSE_E;
04156 
04157     if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
04158         return ASN_PARSE_E;
04159 
04160     /* put encrypted CEK in decryptedKey buffer for now, decrypt later */
04161     if (length > *encryptedKeySz)
04162         return BUFFER_E;
04163 
04164     XMEMCPY(encryptedKey, pkiMsg + (*idx), length);
04165     *encryptedKeySz = length;
04166     (*idx) += length;
04167 
04168     return 0;
04169 }
04170 
04171 #endif /* HAVE_ECC */
04172 
04173 
04174 /* decode ASN.1 KeyAgreeRecipientInfo (kari), return 0 on success,
04175  * < 0 on error */
04176 static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
04177                                word32* idx, byte* decryptedKey,
04178                                word32* decryptedKeySz, int* recipFound)
04179 {
04180 #ifdef HAVE_ECC
04181     int ret, keySz;
04182     int encryptedKeySz;
04183     int direction = 0;
04184     word32 keyAgreeOID, keyWrapOID;
04185 
04186 #ifdef WOLFSSL_SMALL_STACK
04187     byte* encryptedKey;
04188 #else
04189     byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
04190 #endif
04191 
04192     WC_PKCS7_KARI* kari;
04193 
04194     if (pkcs7 == NULL || pkcs7->singleCert == NULL ||
04195         pkcs7->singleCertSz == 0 || pkiMsg == NULL ||
04196         idx == NULL || decryptedKey == NULL || decryptedKeySz == NULL) {
04197         return BAD_FUNC_ARG;
04198     }
04199 
04200     kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_DECODE);
04201     if (kari == NULL)
04202         return MEMORY_E;
04203 
04204 #ifdef WOLFSSL_SMALL_STACK
04205     encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
04206                                   DYNAMIC_TYPE_PKCS7);
04207     if (encryptedKey == NULL) {
04208         wc_PKCS7_KariFree(kari);
04209         return MEMORY_E;
04210     }
04211 #endif
04212     encryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
04213 
04214     /* parse cert and key */
04215     ret = wc_PKCS7_KariParseRecipCert(kari, (byte*)pkcs7->singleCert,
04216                                       pkcs7->singleCertSz, pkcs7->privateKey,
04217                                       pkcs7->privateKeySz);
04218     if (ret != 0) {
04219         wc_PKCS7_KariFree(kari);
04220         #ifdef WOLFSSL_SMALL_STACK
04221             XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04222         #endif
04223         return ret;
04224     }
04225 
04226     /* remove OriginatorIdentifierOrKey */
04227     ret = wc_PKCS7_KariGetOriginatorIdentifierOrKey(kari, pkiMsg,
04228                                                     pkiMsgSz, idx);
04229     if (ret != 0) {
04230         wc_PKCS7_KariFree(kari);
04231         #ifdef WOLFSSL_SMALL_STACK
04232             XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04233         #endif
04234         return ret;
04235     }
04236 
04237     /* try and remove optional UserKeyingMaterial */
04238     ret = wc_PKCS7_KariGetUserKeyingMaterial(kari, pkiMsg, pkiMsgSz, idx);
04239     if (ret != 0) {
04240         wc_PKCS7_KariFree(kari);
04241         #ifdef WOLFSSL_SMALL_STACK
04242             XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04243         #endif
04244         return ret;
04245     }
04246 
04247     /* remove KeyEncryptionAlgorithmIdentifier */
04248     ret = wc_PKCS7_KariGetKeyEncryptionAlgorithmId(kari, pkiMsg, pkiMsgSz,
04249                                                    idx, &keyAgreeOID,
04250                                                    &keyWrapOID);
04251     if (ret != 0) {
04252         wc_PKCS7_KariFree(kari);
04253         #ifdef WOLFSSL_SMALL_STACK
04254             XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04255         #endif
04256         return ret;
04257     }
04258 
04259     /* if user has not explicitly set keyAgreeOID, set from one in bundle */
04260     if (pkcs7->keyAgreeOID == 0)
04261         pkcs7->keyAgreeOID = keyAgreeOID;
04262 
04263     /* set direction based on key wrap algorithm */
04264     switch (keyWrapOID) {
04265 #ifndef NO_AES
04266     #ifdef WOLFSSL_AES_128
04267         case AES128_WRAP:
04268     #endif
04269     #ifdef WOLFSSL_AES_192
04270         case AES192_WRAP:
04271     #endif
04272     #ifdef WOLFSSL_AES_256
04273         case AES256_WRAP:
04274     #endif
04275             direction = AES_DECRYPTION;
04276             break;
04277 #endif
04278         default:
04279             wc_PKCS7_KariFree(kari);
04280             #ifdef WOLFSSL_SMALL_STACK
04281                 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04282             #endif
04283             WOLFSSL_MSG("AES key wrap algorithm unsupported");
04284             return BAD_KEYWRAP_ALG_E;
04285     }
04286 
04287     /* remove RecipientEncryptedKeys */
04288     ret = wc_PKCS7_KariGetRecipientEncryptedKeys(kari, pkiMsg, pkiMsgSz,
04289                                idx, recipFound, encryptedKey, &encryptedKeySz);
04290     if (ret != 0) {
04291         wc_PKCS7_KariFree(kari);
04292         #ifdef WOLFSSL_SMALL_STACK
04293             XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04294         #endif
04295         return ret;
04296     }
04297 
04298     /* create KEK */
04299     ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapOID, pkcs7->keyAgreeOID);
04300     if (ret != 0) {
04301         wc_PKCS7_KariFree(kari);
04302         #ifdef WOLFSSL_SMALL_STACK
04303             XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04304         #endif
04305         return ret;
04306     }
04307 
04308     /* decrypt CEK with KEK */
04309     keySz = wc_PKCS7_KariKeyWrap(encryptedKey, encryptedKeySz, kari->kek,
04310                                  kari->kekSz, decryptedKey, *decryptedKeySz,
04311                                  keyWrapOID, direction);
04312     if (keySz <= 0) {
04313         wc_PKCS7_KariFree(kari);
04314         #ifdef WOLFSSL_SMALL_STACK
04315             XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04316         #endif
04317         return keySz;
04318     }
04319     *decryptedKeySz = (word32)keySz;
04320 
04321     wc_PKCS7_KariFree(kari);
04322     #ifdef WOLFSSL_SMALL_STACK
04323         XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04324     #endif
04325 
04326     return 0;
04327 #else
04328     (void)pkcs7;
04329     (void)pkiMsg;
04330     (void)pkiMsgSz;
04331     (void)idx;
04332     (void)decryptedKey;
04333     (void)decryptedKeySz;
04334     (void)recipFound;
04335 
04336     return NOT_COMPILED_IN;
04337 #endif /* HAVE_ECC */
04338 }
04339 
04340 
04341 /* decode ASN.1 RecipientInfos SET, return 0 on success, < 0 on error */
04342 static int wc_PKCS7_DecodeRecipientInfos(PKCS7* pkcs7, byte* pkiMsg,
04343                             word32 pkiMsgSz, word32* idx, byte* decryptedKey,
04344                             word32* decryptedKeySz, int* recipFound)
04345 {
04346     word32 savedIdx;
04347     int version, ret, length;
04348 
04349     if (pkcs7 == NULL || pkiMsg == NULL || idx == NULL ||
04350         decryptedKey == NULL || decryptedKeySz == NULL ||
04351         recipFound == NULL) {
04352         return BAD_FUNC_ARG;
04353     }
04354 
04355     savedIdx = *idx;
04356 
04357     /* when looking for next recipient, use first sequence and version to
04358      * indicate there is another, if not, move on */
04359     while(*recipFound == 0) {
04360 
04361         /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to
04362          * last good saved one */
04363         if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) > 0) {
04364 
04365             if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) {
04366                 *idx = savedIdx;
04367                 break;
04368             }
04369 
04370             if (version != 0)
04371                 return ASN_VERSION_E;
04372 
04373         #ifndef NO_RSA
04374             /* found ktri */
04375             ret = wc_PKCS7_DecodeKtri(pkcs7, pkiMsg, pkiMsgSz, idx,
04376                                       decryptedKey, decryptedKeySz,
04377                                       recipFound);
04378             if (ret != 0)
04379                 return ret;
04380         #else
04381             return NOT_COMPILED_IN;
04382         #endif
04383         }
04384         else {
04385             /* kari is IMPLICIT[1] */
04386             *idx = savedIdx;
04387             if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
04388                 (*idx)++;
04389 
04390                 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
04391                     return ASN_PARSE_E;
04392 
04393                 if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) {
04394                     *idx = savedIdx;
04395                     break;
04396                 }
04397 
04398                 if (version != 3)
04399                     return ASN_VERSION_E;
04400 
04401                 /* found kari */
04402                 ret = wc_PKCS7_DecodeKari(pkcs7, pkiMsg, pkiMsgSz, idx,
04403                                           decryptedKey, decryptedKeySz,
04404                                           recipFound);
04405                 if (ret != 0)
04406                     return ret;
04407             }
04408             else {
04409                 /* failed to find RecipientInfo, restore idx and continue */
04410                 *idx = savedIdx;
04411                 break;
04412             }
04413         }
04414 
04415         /* update good idx */
04416         savedIdx = *idx;
04417     }
04418 
04419     return 0;
04420 }
04421 
04422 
04423 /* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */
04424 WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
04425                                          word32 pkiMsgSz, byte* output,
04426                                          word32 outputSz)
04427 {
04428     int recipFound = 0;
04429     int ret, version, length;
04430     word32 idx = 0;
04431     word32 contentType, encOID;
04432     word32 decryptedKeySz;
04433 
04434     int expBlockSz, blockKeySz;
04435     byte tmpIv[MAX_CONTENT_IV_SIZE];
04436 
04437 #ifdef WOLFSSL_SMALL_STACK
04438     byte* decryptedKey;
04439 #else
04440     byte decryptedKey[MAX_ENCRYPTED_KEY_SZ];
04441 #endif
04442     int encryptedContentSz;
04443     byte padLen;
04444     byte* encryptedContent = NULL;
04445     int explicitOctet;
04446 
04447     if (pkcs7 == NULL || pkcs7->singleCert == NULL ||
04448         pkcs7->singleCertSz == 0)
04449         return BAD_FUNC_ARG;
04450 
04451     if (pkiMsg == NULL || pkiMsgSz == 0 ||
04452         output == NULL || outputSz == 0)
04453         return BAD_FUNC_ARG;
04454 
04455     /* read past ContentInfo, verify type is envelopedData */
04456     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
04457         return ASN_PARSE_E;
04458 
04459     if (length == 0 && pkiMsg[idx-1] == 0x80) {
04460 #ifdef ASN_BER_TO_DER
04461         word32 len = 0;
04462 
04463         ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len);
04464         if (ret != LENGTH_ONLY_E)
04465             return ret;
04466         pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04467         if (pkcs7->der == NULL)
04468             return MEMORY_E;
04469         ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len);
04470         if (ret < 0)
04471             return ret;
04472 
04473         pkiMsg = pkcs7->der;
04474         pkiMsgSz = len;
04475         idx = 0;
04476         if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
04477             return ASN_PARSE_E;
04478 #else
04479         return BER_INDEF_E;
04480 #endif
04481     }
04482 
04483     if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
04484         return ASN_PARSE_E;
04485 
04486     if (contentType != ENVELOPED_DATA) {
04487         WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData");
04488         return PKCS7_OID_E;
04489     }
04490 
04491     if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
04492         return ASN_PARSE_E;
04493 
04494     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
04495         return ASN_PARSE_E;
04496 
04497     /* remove EnvelopedData and version */
04498     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
04499         return ASN_PARSE_E;
04500 
04501     if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
04502         return ASN_PARSE_E;
04503 
04504     /* TODO :: make this more accurate */
04505     if ((pkcs7->publicKeyOID == RSAk && version != 0)
04506     #ifdef HAVE_ECC
04507             || (pkcs7->publicKeyOID == ECDSAk && version != 2)
04508     #endif
04509             ) {
04510         WOLFSSL_MSG("PKCS#7 envelopedData needs to be of version 0");
04511         return ASN_VERSION_E;
04512     }
04513 
04514     /* walk through RecipientInfo set, find correct recipient */
04515     if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
04516         return ASN_PARSE_E;
04517 
04518 #ifdef WOLFSSL_SMALL_STACK
04519     decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
04520                                                        DYNAMIC_TYPE_PKCS7);
04521     if (decryptedKey == NULL)
04522         return MEMORY_E;
04523 #endif
04524     decryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
04525 
04526     ret = wc_PKCS7_DecodeRecipientInfos(pkcs7, pkiMsg, pkiMsgSz, &idx,
04527                                         decryptedKey, &decryptedKeySz,
04528                                         &recipFound);
04529     if (ret != 0) {
04530 #ifdef WOLFSSL_SMALL_STACK
04531         XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04532 #endif
04533         return ret;
04534     }
04535 
04536     if (recipFound == 0) {
04537         WOLFSSL_MSG("No recipient found in envelopedData that matches input");
04538 #ifdef WOLFSSL_SMALL_STACK
04539         XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04540 #endif
04541         return PKCS7_RECIP_E;
04542     }
04543 
04544     /* remove EncryptedContentInfo */
04545     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
04546 #ifdef WOLFSSL_SMALL_STACK
04547         XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04548 #endif
04549         return ASN_PARSE_E;
04550     }
04551 
04552     if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) {
04553 #ifdef WOLFSSL_SMALL_STACK
04554         XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04555 #endif
04556         return ASN_PARSE_E;
04557     }
04558 
04559     if (GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0) {
04560 #ifdef WOLFSSL_SMALL_STACK
04561         XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04562 #endif
04563         return ASN_PARSE_E;
04564     }
04565 
04566     blockKeySz = wc_PKCS7_GetOIDKeySize(encOID);
04567     if (blockKeySz < 0) {
04568 #ifdef WOLFSSL_SMALL_STACK
04569         XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04570 #endif
04571         return blockKeySz;
04572     }
04573 
04574     expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID);
04575     if (expBlockSz < 0) {
04576 #ifdef WOLFSSL_SMALL_STACK
04577         XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04578 #endif
04579         return expBlockSz;
04580     }
04581 
04582     /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
04583     if (pkiMsg[idx++] != ASN_OCTET_STRING) {
04584 #ifdef WOLFSSL_SMALL_STACK
04585         XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04586 #endif
04587         return ASN_PARSE_E;
04588     }
04589 
04590     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
04591 #ifdef WOLFSSL_SMALL_STACK
04592         XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04593 #endif
04594         return ASN_PARSE_E;
04595     }
04596 
04597     if (length != expBlockSz) {
04598         WOLFSSL_MSG("Incorrect IV length, must be of content alg block size");
04599 #ifdef WOLFSSL_SMALL_STACK
04600         XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04601 #endif
04602         return ASN_PARSE_E;
04603     }
04604 
04605     XMEMCPY(tmpIv, &pkiMsg[idx], length);
04606     idx += length;
04607 
04608     explicitOctet = pkiMsg[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0);
04609 
04610     /* read encryptedContent, cont[0] */
04611     if (pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) &&
04612         pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) {
04613 #ifdef WOLFSSL_SMALL_STACK
04614         XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04615 #endif
04616         return ASN_PARSE_E;
04617     }
04618     idx++;
04619 
04620     if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) {
04621 #ifdef WOLFSSL_SMALL_STACK
04622         XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04623 #endif
04624         return ASN_PARSE_E;
04625     }
04626 
04627     if (explicitOctet) {
04628         if (pkiMsg[idx++] != ASN_OCTET_STRING) {
04629 #ifdef WOLFSSL_SMALL_STACK
04630             XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04631 #endif
04632             return ASN_PARSE_E;
04633         }
04634 
04635         if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) {
04636 #ifdef WOLFSSL_SMALL_STACK
04637             XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04638 #endif
04639             return ASN_PARSE_E;
04640         }
04641     }
04642 
04643     encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap,
04644                                                        DYNAMIC_TYPE_PKCS7);
04645     if (encryptedContent == NULL) {
04646 #ifdef WOLFSSL_SMALL_STACK
04647         XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04648 #endif
04649         return MEMORY_E;
04650     }
04651 
04652     XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
04653 
04654     /* decrypt encryptedContent */
04655     ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz,
04656                                   tmpIv, expBlockSz, encryptedContent,
04657                                   encryptedContentSz, encryptedContent);
04658     if (ret != 0) {
04659         XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04660 #ifdef WOLFSSL_SMALL_STACK
04661         XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04662 #endif
04663         return ret;
04664     }
04665 
04666     padLen = encryptedContent[encryptedContentSz-1];
04667 
04668     /* copy plaintext to output */
04669     XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
04670 
04671     /* free memory, zero out keys */
04672     ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ);
04673     ForceZero(encryptedContent, encryptedContentSz);
04674     XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04675 #ifdef WOLFSSL_SMALL_STACK
04676     XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04677 #endif
04678 
04679     return encryptedContentSz - padLen;
04680 }
04681 
04682 
04683 #ifndef NO_PKCS7_ENCRYPTED_DATA
04684 
04685 /* build PKCS#7 encryptedData content type, return encrypted size */
04686 int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz)
04687 {
04688     int ret, idx = 0;
04689     int totalSz, padSz, encryptedOutSz;
04690 
04691     int contentInfoSeqSz, outerContentTypeSz, outerContentSz;
04692     byte contentInfoSeq[MAX_SEQ_SZ];
04693     byte outerContentType[MAX_ALGO_SZ];
04694     byte outerContent[MAX_SEQ_SZ];
04695 
04696     int encDataSeqSz, verSz, blockSz;
04697     byte encDataSeq[MAX_SEQ_SZ];
04698     byte ver[MAX_VERSION_SZ];
04699 
04700     byte* plain = NULL;
04701     byte* encryptedContent = NULL;
04702 
04703     int encContentOctetSz, encContentSeqSz, contentTypeSz;
04704     int contentEncAlgoSz, ivOctetStringSz;
04705     byte encContentSeq[MAX_SEQ_SZ];
04706     byte contentType[MAX_ALGO_SZ];
04707     byte contentEncAlgo[MAX_ALGO_SZ];
04708     byte tmpIv[MAX_CONTENT_IV_SIZE];
04709     byte ivOctetString[MAX_OCTET_STR_SZ];
04710     byte encContentOctet[MAX_OCTET_STR_SZ];
04711 
04712     byte attribSet[MAX_SET_SZ];
04713     EncodedAttrib* attribs = NULL;
04714     word32 attribsSz;
04715     word32 attribsCount;
04716     word32 attribsSetSz;
04717 
04718     byte* flatAttribs = NULL;
04719 
04720     if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
04721         pkcs7->encryptOID == 0 || pkcs7->encryptionKey == NULL ||
04722         pkcs7->encryptionKeySz == 0)
04723         return BAD_FUNC_ARG;
04724 
04725     if (output == NULL || outputSz == 0)
04726         return BAD_FUNC_ARG;
04727 
04728     /* outer content type */
04729     outerContentTypeSz = wc_SetContentType(ENCRYPTED_DATA, outerContentType);
04730 
04731     /* version, 2 if unprotectedAttrs present, 0 if absent */
04732     if (pkcs7->unprotectedAttribsSz > 0) {
04733         verSz = SetMyVersion(2, ver, 0);
04734     } else {
04735         verSz = SetMyVersion(0, ver, 0);
04736     }
04737 
04738     /* EncryptedContentInfo */
04739     contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType);
04740     if (contentTypeSz == 0)
04741         return BAD_FUNC_ARG;
04742 
04743     /* allocate encrypted content buffer, do PKCS#7 padding */
04744     blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID);
04745     if (blockSz < 0)
04746         return blockSz;
04747 
04748     padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz);
04749     if (padSz < 0)
04750         return padSz;
04751 
04752     encryptedOutSz = pkcs7->contentSz + padSz;
04753 
04754     plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap,
04755                            DYNAMIC_TYPE_PKCS7);
04756     if (plain == NULL)
04757         return MEMORY_E;
04758 
04759     ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain,
04760                            encryptedOutSz, blockSz);
04761     if (ret < 0) {
04762         XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04763         return ret;
04764     }
04765 
04766     encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap,
04767                                       DYNAMIC_TYPE_PKCS7);
04768     if (encryptedContent == NULL) {
04769         XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04770         return MEMORY_E;
04771     }
04772 
04773     /* put together IV OCTET STRING */
04774     ivOctetStringSz = SetOctetString(blockSz, ivOctetString);
04775 
04776     /* build up ContentEncryptionAlgorithmIdentifier sequence,
04777        adding (ivOctetStringSz + blockSz) for IV OCTET STRING */
04778     contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
04779                                  oidBlkType, ivOctetStringSz + blockSz);
04780     if (contentEncAlgoSz == 0) {
04781         XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04782         XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04783         return BAD_FUNC_ARG;
04784     }
04785 
04786     /* encrypt content */
04787     ret = wc_PKCS7_GenerateIV(pkcs7, NULL, tmpIv, blockSz);
04788     if (ret != 0) {
04789         XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04790         XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04791         return ret;
04792     }
04793 
04794     ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->encryptionKey,
04795             pkcs7->encryptionKeySz, tmpIv, blockSz, plain, encryptedOutSz,
04796             encryptedContent);
04797     if (ret != 0) {
04798         XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04799         XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04800         return ret;
04801     }
04802 
04803     encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0,
04804                                     encryptedOutSz, encContentOctet);
04805 
04806     encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
04807                                   ivOctetStringSz + blockSz +
04808                                   encContentOctetSz + encryptedOutSz,
04809                                   encContentSeq);
04810 
04811     /* optional UnprotectedAttributes */
04812     if (pkcs7->unprotectedAttribsSz != 0) {
04813 
04814         if (pkcs7->unprotectedAttribs == NULL) {
04815             XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04816             XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04817             return BAD_FUNC_ARG;
04818         }
04819 
04820         attribs = (EncodedAttrib*)XMALLOC(
04821                 sizeof(EncodedAttrib) * pkcs7->unprotectedAttribsSz,
04822                 pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04823         if (attribs == NULL) {
04824             XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04825             XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04826             return MEMORY_E;
04827         }
04828 
04829         attribsCount = pkcs7->unprotectedAttribsSz;
04830         attribsSz = EncodeAttributes(attribs, pkcs7->unprotectedAttribsSz,
04831                                      pkcs7->unprotectedAttribs,
04832                                      pkcs7->unprotectedAttribsSz);
04833 
04834         flatAttribs = (byte*)XMALLOC(attribsSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04835         if (flatAttribs == NULL) {
04836             XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04837             XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04838             XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04839             return MEMORY_E;
04840         }
04841 
04842         FlattenAttributes(flatAttribs, attribs, attribsCount);
04843         attribsSetSz = SetImplicit(ASN_SET, 1, attribsSz, attribSet);
04844 
04845     } else {
04846         attribsSz = 0;
04847         attribsSetSz = 0;
04848     }
04849 
04850     /* keep track of sizes for outer wrapper layering */
04851     totalSz = verSz + encContentSeqSz + contentTypeSz + contentEncAlgoSz +
04852               ivOctetStringSz + blockSz + encContentOctetSz + encryptedOutSz +
04853               attribsSz + attribsSetSz;;
04854 
04855     /* EncryptedData */
04856     encDataSeqSz = SetSequence(totalSz, encDataSeq);
04857     totalSz += encDataSeqSz;
04858 
04859     /* outer content */
04860     outerContentSz = SetExplicit(0, totalSz, outerContent);
04861     totalSz += outerContentTypeSz;
04862     totalSz += outerContentSz;
04863 
04864     /* ContentInfo */
04865     contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
04866     totalSz += contentInfoSeqSz;
04867 
04868     if (totalSz > (int)outputSz) {
04869         WOLFSSL_MSG("PKCS#7 output buffer too small");
04870         if (pkcs7->unprotectedAttribsSz != 0) {
04871             XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04872             XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04873         }
04874         XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04875         XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04876         return BUFFER_E;
04877     }
04878 
04879     XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz);
04880     idx += contentInfoSeqSz;
04881     XMEMCPY(output + idx, outerContentType, outerContentTypeSz);
04882     idx += outerContentTypeSz;
04883     XMEMCPY(output + idx, outerContent, outerContentSz);
04884     idx += outerContentSz;
04885     XMEMCPY(output + idx, encDataSeq, encDataSeqSz);
04886     idx += encDataSeqSz;
04887     XMEMCPY(output + idx, ver, verSz);
04888     idx += verSz;
04889     XMEMCPY(output + idx, encContentSeq, encContentSeqSz);
04890     idx += encContentSeqSz;
04891     XMEMCPY(output + idx, contentType, contentTypeSz);
04892     idx += contentTypeSz;
04893     XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz);
04894     idx += contentEncAlgoSz;
04895     XMEMCPY(output + idx, ivOctetString, ivOctetStringSz);
04896     idx += ivOctetStringSz;
04897     XMEMCPY(output + idx, tmpIv, blockSz);
04898     idx += blockSz;
04899     XMEMCPY(output + idx, encContentOctet, encContentOctetSz);
04900     idx += encContentOctetSz;
04901     XMEMCPY(output + idx, encryptedContent, encryptedOutSz);
04902     idx += encryptedOutSz;
04903 
04904     if (pkcs7->unprotectedAttribsSz != 0) {
04905         XMEMCPY(output + idx, attribSet, attribsSetSz);
04906         idx += attribsSetSz;
04907         XMEMCPY(output + idx, flatAttribs, attribsSz);
04908         idx += attribsSz;
04909         XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04910         XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04911     }
04912 
04913     XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04914     XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
04915 
04916     return idx;
04917 }
04918 
04919 
04920 /* decode and store unprotected attributes in PKCS7->decodedAttrib. Return
04921  * 0 on success, negative on error. User must call wc_PKCS7_Free(). */
04922 static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg,
04923                                              word32 pkiMsgSz, word32* inOutIdx)
04924 {
04925     int ret, attribLen;
04926     word32 idx;
04927 
04928     if (pkcs7 == NULL || pkiMsg == NULL ||
04929         pkiMsgSz == 0 || inOutIdx == NULL)
04930         return BAD_FUNC_ARG;
04931 
04932     idx = *inOutIdx;
04933 
04934     if (pkiMsg[idx] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
04935         return ASN_PARSE_E;
04936     idx++;
04937 
04938     if (GetLength(pkiMsg, &idx, &attribLen, pkiMsgSz) < 0)
04939         return ASN_PARSE_E;
04940 
04941     /* loop through attributes */
04942     if ((ret = wc_PKCS7_ParseAttribs(pkcs7, pkiMsg + idx, attribLen)) < 0) {
04943         return ret;
04944     }
04945 
04946     *inOutIdx = idx;
04947 
04948     return 0;
04949 }
04950 
04951 
04952 /* unwrap and decrypt PKCS#7/CMS encrypted-data object, returned decoded size */
04953 int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
04954                                  byte* output, word32 outputSz)
04955 {
04956     int ret, version, length, haveAttribs;
04957     word32 idx = 0;
04958     word32 contentType, encOID;
04959 
04960     int expBlockSz;
04961     byte tmpIv[MAX_CONTENT_IV_SIZE];
04962 
04963     int encryptedContentSz;
04964     byte padLen;
04965     byte* encryptedContent = NULL;
04966 
04967     if (pkcs7 == NULL || pkcs7->encryptionKey == NULL ||
04968         pkcs7->encryptionKeySz == 0)
04969         return BAD_FUNC_ARG;
04970 
04971     if (pkiMsg == NULL || pkiMsgSz == 0 ||
04972         output == NULL || outputSz == 0)
04973         return BAD_FUNC_ARG;
04974     /* read past ContentInfo, verify type is encrypted-data */
04975     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
04976         return ASN_PARSE_E;
04977 
04978     if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
04979         return ASN_PARSE_E;
04980 
04981     if (contentType != ENCRYPTED_DATA) {
04982         WOLFSSL_MSG("PKCS#7 input not of type EncryptedData");
04983         return PKCS7_OID_E;
04984     }
04985 
04986     if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
04987         return ASN_PARSE_E;
04988 
04989     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
04990         return ASN_PARSE_E;
04991 
04992     /* remove EncryptedData and version */
04993     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
04994         return ASN_PARSE_E;
04995 
04996     /* get version, check later */
04997     haveAttribs = 0;
04998     if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
04999         return ASN_PARSE_E;
05000 
05001     /* remove EncryptedContentInfo */
05002     if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
05003         return ASN_PARSE_E;
05004 
05005     if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
05006         return ASN_PARSE_E;
05007 
05008     if (GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0)
05009         return ASN_PARSE_E;
05010 
05011     expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID);
05012     if (expBlockSz < 0)
05013         return expBlockSz;
05014 
05015     /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
05016     if (pkiMsg[idx++] != ASN_OCTET_STRING)
05017         return ASN_PARSE_E;
05018 
05019     if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
05020         return ASN_PARSE_E;
05021 
05022     if (length != expBlockSz) {
05023         WOLFSSL_MSG("Incorrect IV length, must be of content alg block size");
05024         return ASN_PARSE_E;
05025     }
05026 
05027     XMEMCPY(tmpIv, &pkiMsg[idx], length);
05028     idx += length;
05029 
05030     /* read encryptedContent, cont[0] */
05031     if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0))
05032         return ASN_PARSE_E;
05033 
05034     if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0)
05035         return ASN_PARSE_E;
05036 
05037     encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap,
05038                                       DYNAMIC_TYPE_PKCS7);
05039     if (encryptedContent == NULL)
05040         return MEMORY_E;
05041 
05042     XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
05043     idx += encryptedContentSz;
05044 
05045     /* decrypt encryptedContent */
05046     ret = wc_PKCS7_DecryptContent(encOID, pkcs7->encryptionKey,
05047                                   pkcs7->encryptionKeySz, tmpIv, expBlockSz,
05048                                   encryptedContent, encryptedContentSz,
05049                                   encryptedContent);
05050     if (ret != 0) {
05051         XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
05052         return ret;
05053     }
05054 
05055     padLen = encryptedContent[encryptedContentSz-1];
05056 
05057     /* copy plaintext to output */
05058     XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
05059 
05060     /* get implicit[1] unprotected attributes, optional */
05061     pkcs7->decodedAttrib = NULL;
05062     if (idx < pkiMsgSz) {
05063 
05064         haveAttribs = 1;
05065 
05066         ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg,
05067                                                    pkiMsgSz, &idx);
05068         if (ret != 0) {
05069             ForceZero(encryptedContent, encryptedContentSz);
05070             XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
05071             return ASN_PARSE_E;
05072         }
05073     }
05074 
05075     /* go back and check the version now that attribs have been processed */
05076     if ((haveAttribs == 0 && version != 0) ||
05077         (haveAttribs == 1 && version != 2) ) {
05078         XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
05079         WOLFSSL_MSG("Wrong PKCS#7 EncryptedData version");
05080         return ASN_VERSION_E;
05081     }
05082 
05083     ForceZero(encryptedContent, encryptedContentSz);
05084     XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
05085 
05086     return encryptedContentSz - padLen;
05087 }
05088 
05089 #endif /* NO_PKCS7_ENCRYPTED_DATA */
05090 
05091 #else  /* HAVE_PKCS7 */
05092 
05093 
05094 #ifdef _MSC_VER
05095     /* 4206 warning for blank file */
05096     #pragma warning(disable: 4206)
05097 #endif
05098 
05099 
05100 #endif /* HAVE_PKCS7 */
05101 
05102