wolf SSL / wolfSSL-TLS13-Beta

Fork of wolfSSL by wolf SSL

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pkcs7.c Source File

pkcs7.c

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