123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763 |
- /* pkcs12.c
- *
- * Copyright (C) 2006-2023 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
- /* PKCS#12 allows storage of key and certificates into containers */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <wolfssl/wolfcrypt/settings.h>
- #if defined(HAVE_PKCS12) && \
- !defined(NO_ASN) && !defined(NO_PWDBASED) && !defined(NO_HMAC) && \
- !defined(NO_CERTS)
- #include <wolfssl/wolfcrypt/asn.h>
- #include <wolfssl/wolfcrypt/asn_public.h>
- #include <wolfssl/wolfcrypt/error-crypt.h>
- #include <wolfssl/wolfcrypt/hmac.h>
- #include <wolfssl/wolfcrypt/logging.h>
- #ifdef NO_INLINE
- #include <wolfssl/wolfcrypt/misc.h>
- #else
- #define WOLFSSL_MISC_INCLUDED
- #include <wolfcrypt/src/misc.c>
- #endif
- #include <wolfssl/wolfcrypt/pkcs12.h>
- #include <wolfssl/wolfcrypt/pwdbased.h>
- #include <wolfssl/wolfcrypt/hash.h>
- #define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
- enum {
- WC_PKCS12_KeyBag = 667,
- WC_PKCS12_ShroudedKeyBag = 668,
- WC_PKCS12_CertBag = 669,
- WC_PKCS12_CertBag_Type1 = 675,
- WC_PKCS12_CrlBag = 670,
- WC_PKCS12_SecretBag = 671,
- WC_PKCS12_SafeContentsBag = 672,
- WC_PKCS12_DATA = 651,
- WC_PKCS12_ENCRYPTED_DATA = 656,
- WC_PKCS12_DATA_OBJ_SZ = 11,
- WC_PKCS12_MAC_SALT_SZ = 8
- };
- static const byte WC_PKCS12_ENCRYPTED_OID[] =
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06};
- static const byte WC_PKCS12_DATA_OID[] =
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01};
- static const byte WC_PKCS12_CertBag_Type1_OID[] =
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x16, 0x01};
- static const byte WC_PKCS12_CertBag_OID[] =
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x03};
- static const byte WC_PKCS12_KeyBag_OID[] =
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x01};
- static const byte WC_PKCS12_ShroudedKeyBag_OID[] =
- {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x02};
- typedef struct ContentInfo {
- byte* data;
- struct ContentInfo* next;
- word32 encC; /* encryptedContent */
- word32 dataSz;
- int type; /* DATA / encrypted / enveloped */
- } ContentInfo;
- typedef struct AuthenticatedSafe {
- ContentInfo* CI;
- byte* data; /* T contents.... */
- word32 oid; /* encrypted or not */
- word32 numCI; /* number of Content Info structs */
- word32 dataSz;
- } AuthenticatedSafe;
- typedef struct MacData {
- byte* digest;
- byte* salt;
- word32 oid;
- word32 digestSz;
- word32 saltSz;
- int itt; /* number of iterations when creating HMAC key */
- } MacData;
- struct WC_PKCS12 {
- void* heap;
- AuthenticatedSafe* safe;
- MacData* signData;
- word32 oid; /* DATA / Enveloped DATA ... */
- byte indefinite;
- #ifdef ASN_BER_TO_DER
- byte* safeDer; /* der encoded version of message */
- byte* der; /* der encoded version of message */
- word32 safeDersz;
- word32 derSz;
- #endif
- };
- /* for friendlyName, localKeyId .... */
- typedef struct WC_PKCS12_ATTRIBUTE {
- byte* data;
- word32 oid;
- word32 dataSz;
- } WC_PKCS12_ATTRIBUTE;
- WC_PKCS12* wc_PKCS12_new(void)
- {
- WC_PKCS12* pkcs12 = (WC_PKCS12*)XMALLOC(sizeof(WC_PKCS12),
- NULL, DYNAMIC_TYPE_PKCS);
- if (pkcs12 == NULL) {
- WOLFSSL_MSG("Memory issue when creating WC_PKCS12 struct");
- return NULL;
- }
- XMEMSET(pkcs12, 0, sizeof(WC_PKCS12));
- return pkcs12;
- }
- static void freeSafe(AuthenticatedSafe* safe, void* heap)
- {
- int i;
- if (safe == NULL) {
- return;
- }
- /* free content info structs */
- for (i = (int)safe->numCI; i > 0; i--) {
- ContentInfo* ci = safe->CI;
- safe->CI = ci->next;
- XFREE(ci, heap, DYNAMIC_TYPE_PKCS);
- }
- if (safe->data != NULL) {
- XFREE(safe->data, heap, DYNAMIC_TYPE_PKCS);
- }
- XFREE(safe, heap, DYNAMIC_TYPE_PKCS);
- (void)heap;
- }
- void wc_PKCS12_free(WC_PKCS12* pkcs12)
- {
- void* heap;
- /* if null pointer is passed in do nothing */
- if (pkcs12 == NULL) {
- WOLFSSL_MSG("Trying to free null WC_PKCS12 object");
- return;
- }
- heap = pkcs12->heap;
- if (pkcs12->safe != NULL) {
- freeSafe(pkcs12->safe, heap);
- }
- /* free mac data */
- if (pkcs12->signData != NULL) {
- if (pkcs12->signData->digest != NULL) {
- XFREE(pkcs12->signData->digest, heap, DYNAMIC_TYPE_DIGEST);
- }
- if (pkcs12->signData->salt != NULL) {
- XFREE(pkcs12->signData->salt, heap, DYNAMIC_TYPE_SALT);
- }
- XFREE(pkcs12->signData, heap, DYNAMIC_TYPE_PKCS);
- }
- #ifdef ASN_BER_TO_DER
- if (pkcs12->der != NULL) {
- XFREE(pkcs12->der, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- }
- if (pkcs12->safeDer != NULL) {
- XFREE(pkcs12->safeDer, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- }
- #endif
- XFREE(pkcs12, NULL, DYNAMIC_TYPE_PKCS);
- }
- /* return 0 on success */
- static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input,
- word32* idx, word32 maxIdx)
- {
- AuthenticatedSafe* safe;
- word32 oid;
- word32 localIdx = *idx;
- int ret;
- int size = 0;
- byte tag;
- safe = (AuthenticatedSafe*)XMALLOC(sizeof(AuthenticatedSafe), pkcs12->heap,
- DYNAMIC_TYPE_PKCS);
- if (safe == NULL) {
- return MEMORY_E;
- }
- XMEMSET(safe, 0, sizeof(AuthenticatedSafe));
- ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType, maxIdx);
- if (ret < 0) {
- WOLFSSL_LEAVE("Get object id failed", ret);
- freeSafe(safe, pkcs12->heap);
- return ASN_PARSE_E;
- }
- safe->oid = oid;
- /* check tag, length */
- if (GetASNTag(input, &localIdx, &tag, maxIdx) < 0) {
- freeSafe(safe, pkcs12->heap);
- return ASN_PARSE_E;
- }
- if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
- WOLFSSL_MSG("Unexpected tag in PKCS12 DER");
- freeSafe(safe, pkcs12->heap);
- return ASN_PARSE_E;
- }
- if (GetLength(input, &localIdx, &size, maxIdx) <= 0) {
- freeSafe(safe, pkcs12->heap);
- return ASN_PARSE_E;
- }
- switch (oid) {
- case WC_PKCS12_ENCRYPTED_DATA:
- WOLFSSL_MSG("Found PKCS12 OBJECT: ENCRYPTED DATA");
- break;
- case WC_PKCS12_DATA:
- WOLFSSL_MSG("Found PKCS12 OBJECT: DATA");
- /* get octets holding contents */
- if (GetASNTag(input, &localIdx, &tag, maxIdx) < 0) {
- freeSafe(safe, pkcs12->heap);
- return ASN_PARSE_E;
- }
- if (tag != ASN_OCTET_STRING) {
- WOLFSSL_MSG("Wrong tag with content PKCS12 type DATA");
- freeSafe(safe, pkcs12->heap);
- return ASN_PARSE_E;
- }
- if (GetLength(input, &localIdx, &size, maxIdx) <= 0) {
- freeSafe(safe, pkcs12->heap);
- return ASN_PARSE_E;
- }
- break;
- }
- safe->dataSz = (word32)size;
- safe->data = (byte*)XMALLOC((size_t)size, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- if (safe->data == NULL) {
- freeSafe(safe, pkcs12->heap);
- return MEMORY_E;
- }
- XMEMCPY(safe->data, input + localIdx, (size_t)size);
- *idx = localIdx;
- localIdx = 0;
- input = safe->data;
- size = (int)safe->dataSz;
- #ifdef ASN_BER_TO_DER
- if (pkcs12->indefinite) {
- if (wc_BerToDer(input, safe->dataSz, NULL,
- &pkcs12->safeDersz) != LENGTH_ONLY_E) {
- WOLFSSL_MSG("Not BER sequence");
- return ASN_PARSE_E;
- }
- pkcs12->safeDer = (byte*)XMALLOC(pkcs12->safeDersz, pkcs12->heap,
- DYNAMIC_TYPE_PKCS);
- if (pkcs12->safeDer == NULL) {
- freeSafe(safe, pkcs12->heap);
- return MEMORY_E;
- }
- ret = wc_BerToDer(input, safe->dataSz, pkcs12->safeDer, &pkcs12->safeDersz);
- if (ret < 0) {
- freeSafe(safe, pkcs12->heap);
- return ret;
- }
- input = pkcs12->safeDer;
- }
- #endif /* ASN_BER_TO_DER */
- /* an instance of AuthenticatedSafe is created from
- * ContentInfo's strung together in a SEQUENCE. Here we iterate
- * through the ContentInfo's and add them to our
- * AuthenticatedSafe struct */
- {
- int CISz;
- ret = GetSequence(input, &localIdx, &CISz, (word32)size);
- if (ret < 0) {
- freeSafe(safe, pkcs12->heap);
- return ASN_PARSE_E;
- }
- CISz += (int)localIdx;
- while (localIdx < (word32)CISz) {
- int curSz = 0;
- word32 curIdx;
- ContentInfo* ci = NULL;
- #ifdef WOLFSSL_DEBUG_PKCS12
- printf("\t\tlooking for Content Info.... ");
- #endif
- if ((ret = GetSequence(input, &localIdx, &curSz, (word32)size)) < 0) {
- freeSafe(safe, pkcs12->heap);
- return ret;
- }
- if (curSz > CISz) {
- /* subset should not be larger than universe */
- freeSafe(safe, pkcs12->heap);
- return ASN_PARSE_E;
- }
- curIdx = localIdx;
- if ((ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType,
- (word32)size)) < 0) {
- WOLFSSL_LEAVE("Get object id failed", ret);
- freeSafe(safe, pkcs12->heap);
- return ret;
- }
- /* create new content info struct ... possible OID sanity check? */
- ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), pkcs12->heap,
- DYNAMIC_TYPE_PKCS);
- if (ci == NULL) {
- freeSafe(safe, pkcs12->heap);
- return MEMORY_E;
- }
- ci->type = (int)oid;
- ci->dataSz = (word32)curSz - (localIdx-curIdx);
- ci->data = (byte*)input + localIdx;
- localIdx += ci->dataSz;
- #ifdef WOLFSSL_DEBUG_PKCS12
- switch (oid) {
- case WC_PKCS12_ENCRYPTED_DATA:
- printf("CONTENT INFO: ENCRYPTED DATA, size = %d\n", ci->dataSz);
- break;
- case WC_PKCS12_DATA:
- printf("CONTENT INFO: DATA, size = %d\n", ci->dataSz);
- break;
- default:
- printf("CONTENT INFO: UNKNOWN, size = %d\n", ci->dataSz);
- }
- #endif
- /* insert to head of list */
- ci->next = safe->CI;
- safe->CI = ci;
- safe->numCI += 1;
- }
- }
- pkcs12->safe = safe;
- *idx += localIdx;
- return ret;
- }
- /* parse optional mac data
- * return 0 on success */
- static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx,
- word32 totalSz)
- {
- MacData* mac;
- word32 curIdx = *idx;
- word32 oid = 0;
- int size, ret;
- byte tag;
- /* Digest Info : Sequence
- * DigestAlgorithmIdentifier
- * Digest
- */
- if (GetSequence(mem, &curIdx, &size, totalSz) <= 0) {
- WOLFSSL_MSG("Failed to get PKCS12 sequence");
- return ASN_PARSE_E;
- }
- #ifdef WOLFSSL_DEBUG_PKCS12
- printf("\t\tSEQUENCE: DigestInfo size = %d\n", size);
- #endif
- mac = (MacData*)XMALLOC(sizeof(MacData), pkcs12->heap, DYNAMIC_TYPE_PKCS);
- if (mac == NULL) {
- return MEMORY_E;
- }
- XMEMSET(mac, 0, sizeof(MacData));
- /* DigestAlgorithmIdentifier */
- if ((ret = GetAlgoId(mem, &curIdx, &oid, oidIgnoreType, totalSz)) < 0) {
- WOLFSSL_MSG("Failed to get PKCS12 sequence");
- XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- return ret;
- }
- mac->oid = oid;
- #ifdef WOLFSSL_DEBUG_PKCS12
- printf("\t\tALGO ID = %d\n", oid);
- #endif
- /* Digest: should be octet type holding digest */
- if (GetASNTag(mem, &curIdx, &tag, totalSz) < 0) {
- XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- return ASN_PARSE_E;
- }
- if (tag != ASN_OCTET_STRING) {
- WOLFSSL_MSG("Failed to get digest");
- XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- return ASN_PARSE_E;
- }
- if (GetLength(mem, &curIdx, &size, totalSz) <= 0) {
- XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- return ASN_PARSE_E;
- }
- mac->digestSz = (word32)size;
- mac->digest = (byte*)XMALLOC(mac->digestSz, pkcs12->heap,
- DYNAMIC_TYPE_DIGEST);
- if (mac->digest == NULL || mac->digestSz + curIdx > totalSz) {
- ERROR_OUT(MEMORY_E, exit_gsd);
- }
- XMEMCPY(mac->digest, mem + curIdx, mac->digestSz);
- #ifdef WOLFSSL_DEBUG_PKCS12
- {
- byte* p;
- for (printf("\t\tDigest = "), p = (byte*)mem+curIdx;
- p < (byte*)mem + curIdx + mac->digestSz;
- printf("%02X", *p), p++);
- printf(" : size = %d\n", mac->digestSz);
- }
- #endif
- curIdx += mac->digestSz;
- /* get salt, should be octet string */
- if (GetASNTag(mem, &curIdx, &tag, totalSz) < 0) {
- ERROR_OUT(ASN_PARSE_E, exit_gsd);
- }
- if (tag != ASN_OCTET_STRING) {
- WOLFSSL_MSG("Failed to get salt");
- ERROR_OUT(ASN_PARSE_E, exit_gsd);
- }
- if ((ret = GetLength(mem, &curIdx, &size, totalSz)) < 0) {
- goto exit_gsd;
- }
- mac->saltSz = (word32)size;
- mac->salt = (byte*)XMALLOC(mac->saltSz, pkcs12->heap, DYNAMIC_TYPE_SALT);
- if (mac->salt == NULL || mac->saltSz + curIdx > totalSz) {
- ERROR_OUT(MEMORY_E, exit_gsd);
- }
- XMEMCPY(mac->salt, mem + curIdx, mac->saltSz);
- #ifdef WOLFSSL_DEBUG_PKCS12
- {
- byte* p;
- for (printf("\t\tSalt = "), p = (byte*)mem + curIdx;
- p < (byte*)mem + curIdx + mac->saltSz;
- printf("%02X", *p), p++);
- printf(" : size = %d\n", mac->saltSz);
- }
- #endif
- curIdx += mac->saltSz;
- /* check for MAC iterations, default to 1 */
- mac->itt = WC_PKCS12_MAC_DEFAULT;
- if (curIdx < totalSz) {
- int number = 0;
- if (GetShortInt(mem, &curIdx, &number, totalSz) >= 0) {
- /* found a iteration value */
- mac->itt = number;
- }
- }
- #ifdef WOLFSSL_DEBUG_PKCS12
- printf("\t\tITERATIONS : %d\n", mac->itt);
- #endif
- *idx = curIdx;
- pkcs12->signData = mac;
- ret = 0; /* success */
- exit_gsd:
- /* failure cleanup */
- if (ret != 0) {
- if (mac) {
- if (mac->digest)
- XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_DIGEST);
- XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- }
- }
- return ret;
- }
- /* expects PKCS12 signData to be set up with OID
- *
- * returns the size of mac created on success. A negative value will be returned
- * in the case that an error happened.
- */
- static int wc_PKCS12_create_mac(WC_PKCS12* pkcs12, byte* data, word32 dataSz,
- const byte* psw, word32 pswSz, byte* out, word32 outSz)
- {
- Hmac hmac;
- MacData* mac;
- int ret, kLen;
- enum wc_HashType hashT;
- int idx = 0;
- int id = 3; /* value from RFC 7292 indicating key is used for MAC */
- word32 i;
- byte unicodePasswd[MAX_UNICODE_SZ];
- byte key[PKCS_MAX_KEY_SIZE];
- if (pkcs12 == NULL || pkcs12->signData == NULL || data == NULL ||
- out == NULL) {
- return BAD_FUNC_ARG;
- }
- mac = pkcs12->signData;
- /* unicode set up from asn.c */
- if ((pswSz * 2 + 2) > (int)sizeof(unicodePasswd)) {
- WOLFSSL_MSG("PKCS12 max unicode size too small");
- return UNICODE_SIZE_E;
- }
- for (i = 0; i < pswSz; i++) {
- unicodePasswd[idx++] = 0x00;
- unicodePasswd[idx++] = (byte)psw[i];
- }
- /* add trailing NULL */
- unicodePasswd[idx++] = 0x00;
- unicodePasswd[idx++] = 0x00;
- /* get hash type used and resulting size of HMAC key */
- hashT = wc_OidGetHash((int)mac->oid);
- if (hashT == WC_HASH_TYPE_NONE) {
- ForceZero(unicodePasswd, MAX_UNICODE_SZ);
- WOLFSSL_MSG("Unsupported hash used");
- return BAD_FUNC_ARG;
- }
- kLen = wc_HashGetDigestSize(hashT);
- /* check out buffer is large enough */
- if (kLen < 0 || outSz < (word32)kLen) {
- ForceZero(unicodePasswd, MAX_UNICODE_SZ);
- return BAD_FUNC_ARG;
- }
- /* idx contains size of unicodePasswd */
- ret = wc_PKCS12_PBKDF_ex(key, unicodePasswd, idx, mac->salt, (int)mac->saltSz,
- mac->itt, kLen, (int)hashT, id, pkcs12->heap);
- ForceZero(unicodePasswd, MAX_UNICODE_SZ);
- if (ret < 0) {
- return ret;
- }
- /* now that key has been created use it to get HMAC hash on data */
- if ((ret = wc_HmacInit(&hmac, pkcs12->heap, INVALID_DEVID)) != 0) {
- return ret;
- }
- ret = wc_HmacSetKey(&hmac, (int)hashT, key, (word32)kLen);
- if (ret == 0)
- ret = wc_HmacUpdate(&hmac, data, dataSz);
- if (ret == 0)
- ret = wc_HmacFinal(&hmac, out);
- wc_HmacFree(&hmac);
- if (ret != 0)
- return ret;
- return kLen; /* same as digest size */
- }
- /* check mac on pkcs12, pkcs12->mac has been sanity checked before entering *
- * returns the result of comparison, success is 0 */
- static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz,
- const byte* psw, word32 pswSz)
- {
- MacData* mac;
- int ret;
- byte digest[WC_MAX_DIGEST_SIZE];
- if (pkcs12 == NULL || pkcs12->signData == NULL || data == NULL) {
- return BAD_FUNC_ARG;
- }
- mac = pkcs12->signData;
- #ifdef WOLFSSL_DEBUG_PKCS12
- printf("Verifying MAC with OID = %d\n", mac->oid);
- #endif
- /* check if this builds digest size is too small */
- if (mac->digestSz > WC_MAX_DIGEST_SIZE) {
- WOLFSSL_MSG("PKCS12 max digest size too small");
- return BAD_FUNC_ARG;
- }
- if ((ret = wc_PKCS12_create_mac(pkcs12, data, dataSz, psw, pswSz,
- digest, WC_MAX_DIGEST_SIZE)) < 0) {
- return ret;
- }
- #ifdef WOLFSSL_DEBUG_PKCS12
- {
- byte* p;
- for (printf("\t\tHash = "), p = (byte*)digest;
- p < (byte*)digest + mac->digestSz;
- printf("%02X", *p), p++);
- printf(" : size = %d\n", mac->digestSz);
- }
- #endif
- return XMEMCMP(digest, mac->digest, mac->digestSz);
- }
- int wc_PKCS12_verify_ex(WC_PKCS12* pkcs12, const byte* psw, word32 pswSz)
- {
- if (pkcs12 == NULL || pkcs12->safe == NULL) {
- return BAD_FUNC_ARG;
- }
- return wc_PKCS12_verify(pkcs12, pkcs12->safe->data, pkcs12->safe->dataSz,
- psw, pswSz);
- }
- /* Convert DER format stored in der buffer to WC_PKCS12 struct
- * Puts the raw contents of Content Info into structure without completely
- * parsing or decoding.
- * der : pointer to der buffer holding PKCS12
- * derSz : size of der buffer
- * pkcs12 : non-null pkcs12 pointer
- * return 0 on success and negative on failure.
- */
- int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12)
- {
- word32 idx = 0;
- word32 totalSz = 0;
- int ret;
- int size = 0;
- int version = 0;
- WOLFSSL_ENTER("wolfSSL_d2i_PKCS12");
- if (der == NULL || pkcs12 == NULL) {
- return BAD_FUNC_ARG;
- }
- totalSz = derSz;
- if (GetSequence(der, &idx, &size, totalSz) < 0) {
- WOLFSSL_MSG("Failed to get PKCS12 sequence");
- return ASN_PARSE_E;
- }
- /* get version */
- if ((ret = GetMyVersion(der, &idx, &version, totalSz)) < 0) {
- return ret;
- }
- #ifdef ASN_BER_TO_DER
- if (size == 0) {
- if (wc_BerToDer(der, totalSz, NULL,
- (word32*)&size) != LENGTH_ONLY_E) {
- WOLFSSL_MSG("Not BER sequence");
- return ASN_PARSE_E;
- }
- pkcs12->der = (byte*)XMALLOC((size_t)size, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- if (pkcs12->der == NULL)
- return MEMORY_E;
- ret = wc_BerToDer(der, derSz, pkcs12->der, (word32*)&size);
- if (ret < 0) {
- return ret;
- }
- der = pkcs12->der;
- pkcs12->derSz = (word32)size;
- totalSz = (word32)size;
- idx = 0;
- if (GetSequence(der, &idx, &size, totalSz) < 0) {
- WOLFSSL_MSG("Failed to get PKCS12 sequence");
- return ASN_PARSE_E;
- }
- /* get version */
- if ((ret = GetMyVersion(der, &idx, &version, totalSz)) < 0) {
- return ret;
- }
- pkcs12->indefinite = 1;
- }
- else
- #endif /* ASN_BER_TO_DER */
- {
- pkcs12->indefinite = 0;
- }
- #ifdef WOLFSSL_DEBUG_PKCS12
- printf("\nBEGIN: PKCS12 size = %d\n", totalSz);
- printf("version = %d\n", version);
- #endif
- if (version != WC_PKCS12_VERSION_DEFAULT) {
- WOLFSSL_MSG("PKCS12 unsupported version!");
- WOLFSSL_ERROR_VERBOSE(ASN_VERSION_E);
- return ASN_VERSION_E;
- }
- if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) {
- return ret;
- }
- #ifdef WOLFSSL_DEBUG_PKCS12
- printf("\tSEQUENCE: AuthenticatedSafe size = %d\n", size);
- #endif
- if ((ret = GetSafeContent(pkcs12, der, &idx, (word32)size + idx)) < 0) {
- WOLFSSL_MSG("GetSafeContent error");
- return ret;
- }
- #ifdef ASN_BER_TO_DER
- /* If indef, skip EOF */
- if (pkcs12->indefinite) {
- while((idx < totalSz) && (der[idx] == ASN_EOC)) {
- idx+=1;
- }
- }
- #endif
- /* if more buffer left check for MAC data */
- if (idx < totalSz) {
- if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) {
- WOLFSSL_MSG("Ignoring unknown data at end of PKCS12 DER buffer");
- }
- else {
- #ifdef WOLFSSL_DEBUG_PKCS12
- printf("\tSEQUENCE: Signature size = %d\n", size);
- #endif
- if ((ret = GetSignData(pkcs12, der, &idx, totalSz)) < 0) {
- return ASN_PARSE_E;
- }
- }
- }
- #ifdef WOLFSSL_DEBUG_PKCS12
- printf("END: PKCS12\n");
- #endif
- return ret;
- }
- #ifndef NO_FILESYSTEM
- /* Parse the DER-encoded PKCS #12 object in the provided file. Populate the
- * WC_PKCS12 object pointed to by the passed in pointer, allocating the object
- * if necessary.
- *
- * file : path to PKCS #12 file.
- * pkcs12: pointer to a pointer to a WC_PKCS12 object to populate. If *pkcs12 is
- * NULL, this function will allocate a new WC_PKCS12.
- * return 0 on success and negative on failure.
- */
- int wc_d2i_PKCS12_fp(const char* file, WC_PKCS12** pkcs12)
- {
- int ret = 0;
- byte* buf = NULL;
- size_t bufSz = 0;
- WC_PKCS12* tmpPkcs12 = NULL;
- int callerAlloc = 1;
- WOLFSSL_ENTER("wc_d2i_PKCS12_fp");
- if (pkcs12 == NULL) {
- WOLFSSL_MSG("pkcs12 parameter NULL.");
- ret = BAD_FUNC_ARG;
- }
- if (ret == 0)
- ret = wc_FileLoad(file, &buf, &bufSz, NULL);
- if (ret == 0) {
- if (*pkcs12 == NULL) {
- tmpPkcs12 = wc_PKCS12_new();
- if (tmpPkcs12 == NULL) {
- WOLFSSL_MSG("Failed to allocate PKCS12 object.");
- ret = MEMORY_E;
- }
- else {
- *pkcs12 = tmpPkcs12;
- callerAlloc = 0;
- }
- }
- }
- if (ret == 0) {
- ret = wc_d2i_PKCS12(buf, (word32)bufSz, *pkcs12);
- if (ret != 0) {
- WOLFSSL_MSG("wc_d2i_PKCS12 failed.");
- }
- }
- if (ret != 0 && callerAlloc == 0 && *pkcs12 != NULL) {
- wc_PKCS12_free(*pkcs12);
- *pkcs12 = NULL;
- }
- if (buf != NULL) {
- XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- WOLFSSL_LEAVE("wc_d2i_PKCS12_fp", ret);
- return ret;
- }
- #endif /* NO_FILESYSTEM */
- /* Convert WC_PKCS12 struct to allocated DER buffer.
- * pkcs12 : non-null pkcs12 pointer
- * der : pointer-pointer to der buffer. If NULL space will be
- * allocated for der, which must be freed by application.
- * derSz : size of buffer passed in when der is not NULL. NULL arg disables
- * sanity checks on buffer read/writes. Max size gets set to derSz when
- * the "der" buffer passed in is NULL and LENGTH_ONLY_E is returned.
- * return size of DER on success and negative on failure.
- */
- int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz)
- {
- int ret = 0;
- word32 seqSz = 0, verSz = 0, totalSz = 0, idx = 0, sdBufSz = 0;
- byte *buf = NULL;
- byte ver[MAX_VERSION_SZ];
- byte seq[MAX_SEQ_SZ];
- byte *sdBuf = NULL;
- if ((pkcs12 == NULL) || (pkcs12->safe == NULL) ||
- (der == NULL && derSz == NULL)) {
- return BAD_FUNC_ARG;
- }
- /* Create the MAC portion */
- if (pkcs12->signData != NULL) {
- MacData *mac = (MacData*)pkcs12->signData;
- word32 innerSz = 0;
- word32 outerSz = 0;
- /* get exact size */
- {
- byte ASNLENGTH[MAX_LENGTH_SZ];
- byte ASNSHORT[MAX_SHORT_SZ];
- byte ASNALGO[MAX_ALGO_SZ];
- word32 tmpIdx = 0;
- /* algo id */
- innerSz += SetAlgoID((int)mac->oid, ASNALGO, oidHashType, 0);
- /* Octet string holding digest */
- innerSz += ASN_TAG_SZ;
- innerSz += SetLength(mac->digestSz, ASNLENGTH);
- innerSz += mac->digestSz;
- /* salt */
- outerSz += ASN_TAG_SZ;
- outerSz += SetLength(mac->saltSz, ASNLENGTH);
- outerSz += mac->saltSz;
- /* MAC iterations */
- ret = SetShortInt(ASNSHORT, &tmpIdx, (word32)mac->itt, MAX_SHORT_SZ);
- if (ret >= 0) {
- outerSz += (word32)ret;
- ret = 0;
- }
- else {
- return ret;
- }
- /* sequence of inner data */
- outerSz += SetSequence(innerSz, seq);
- outerSz += innerSz;
- }
- sdBufSz = outerSz + SetSequence(outerSz, seq);
- sdBuf = (byte*)XMALLOC(sdBufSz, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- if (sdBuf == NULL) {
- ret = MEMORY_E;
- }
- if (ret == 0) {
- idx += SetSequence(outerSz, sdBuf);
- idx += SetSequence(innerSz, &sdBuf[idx]);
- /* Set Algorithm Identifier */
- {
- word32 algoIdSz;
- algoIdSz = SetAlgoID((int)mac->oid, &sdBuf[idx], oidHashType, 0);
- if (algoIdSz == 0) {
- ret = ALGO_ID_E;
- }
- else {
- idx += algoIdSz;
- }
- }
- }
- if (ret == 0) {
- /* Octet string holding digest */
- idx += SetOctetString(mac->digestSz, &sdBuf[idx]);
- XMEMCPY(&sdBuf[idx], mac->digest, mac->digestSz);
- idx += mac->digestSz;
- /* Set salt */
- idx += SetOctetString(mac->saltSz, &sdBuf[idx]);
- XMEMCPY(&sdBuf[idx], mac->salt, mac->saltSz);
- idx += mac->saltSz;
- /* MAC iterations */
- {
- int tmpSz;
- word32 tmpIdx = 0;
- byte ar[MAX_SHORT_SZ];
- tmpSz = SetShortInt(ar, &tmpIdx, (word32)mac->itt, MAX_SHORT_SZ);
- if (tmpSz < 0) {
- ret = tmpSz;
- }
- else {
- XMEMCPY(&sdBuf[idx], ar, (size_t)tmpSz);
- }
- }
- totalSz += sdBufSz;
- }
- }
- /* Calculate size of der */
- if (ret == 0) {
- totalSz += pkcs12->safe->dataSz;
- totalSz += 4; /* Octet string */
- totalSz += 4; /* Element */
- totalSz += 2 + sizeof(WC_PKCS12_DATA_OID);
- totalSz += 4; /* Seq */
- ret = SetMyVersion(WC_PKCS12_VERSION_DEFAULT, ver, FALSE);
- if (ret > 0) {
- verSz = (word32)ret;
- ret = 0; /* value larger than 0 is success */
- totalSz += verSz;
- seqSz = SetSequence(totalSz, seq);
- totalSz += seqSz;
- /* check if getting length only */
- if (der == NULL && derSz != NULL) {
- *derSz = (int)totalSz;
- XFREE(sdBuf, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- return LENGTH_ONLY_E;
- }
- if (*der == NULL) {
- /* Allocate if requested */
- buf = (byte*)XMALLOC(totalSz, NULL, DYNAMIC_TYPE_PKCS);
- }
- else {
- buf = *der;
- /* sanity check on buffer size if passed in */
- if (derSz != NULL) {
- if (*derSz < (int)totalSz) {
- WOLFSSL_MSG("Buffer passed in is too small");
- ret = BUFFER_E;
- }
- }
- }
- }
- }
- if (buf == NULL) {
- ret = MEMORY_E;
- }
- if (ret == 0) {
- idx = 0;
- /* Copy parts to buf */
- XMEMCPY(&buf[idx], seq, seqSz);
- idx += seqSz;
- XMEMCPY(&buf[idx], ver, verSz);
- idx += verSz;
- seqSz = SetSequence(totalSz - sdBufSz - idx - 4, seq);
- XMEMCPY(&buf[idx], seq, seqSz);
- idx += seqSz;
- /* OID */
- idx += (word32)SetObjectId(sizeof(WC_PKCS12_DATA_OID), &buf[idx]);
- XMEMCPY(&buf[idx], WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID));
- idx += sizeof(WC_PKCS12_DATA_OID);
- /* Element */
- buf[idx++] = ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC;
- idx += SetLength(totalSz - sdBufSz - idx - 3, &buf[idx]);
- /* Octet string */
- idx += SetOctetString(totalSz - sdBufSz - idx - 4, &buf[idx]);
- XMEMCPY(&buf[idx], pkcs12->safe->data, pkcs12->safe->dataSz);
- idx += pkcs12->safe->dataSz;
- if (pkcs12->signData != NULL) {
- XMEMCPY(&buf[idx], sdBuf, sdBufSz);
- }
- if (*der == NULL) {
- /* Point to start of data allocated for DER */
- *der = buf;
- }
- else {
- /* Increment pointer to byte past DER */
- *der = &buf[totalSz];
- }
- /* Return size of der */
- ret = (int)totalSz;
- }
- XFREE(sdBuf, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- /* Allocation of buf was the last time ret could be a failure,
- * so no need to free here */
- return ret;
- }
- /* helper function to free WC_DerCertList */
- void wc_FreeCertList(WC_DerCertList* list, void* heap)
- {
- WC_DerCertList* current = list;
- WC_DerCertList* next;
- if (list == NULL) {
- return;
- }
- while (current != NULL) {
- next = current->next;
- if (current->buffer != NULL) {
- XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
- }
- XFREE(current, heap, DYNAMIC_TYPE_PKCS);
- current = next;
- }
- (void)heap;
- }
- static WARN_UNUSED_RESULT int freeDecCertList(WC_DerCertList** list,
- byte** pkey, word32* pkeySz, byte** cert, word32* certSz, void* heap)
- {
- WC_DerCertList* current = *list;
- WC_DerCertList* previous = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert *DeCert = (DecodedCert *)XMALLOC(
- sizeof(*DeCert), heap, DYNAMIC_TYPE_PKCS);
- if (DeCert == NULL)
- return MEMORY_E;
- #else
- DecodedCert DeCert[1];
- #endif
- while (current != NULL) {
- InitDecodedCert(DeCert, current->buffer, current->bufferSz, heap);
- if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL) == 0) {
- if (wc_CheckPrivateKeyCert(*pkey, *pkeySz, DeCert) == 1) {
- WOLFSSL_MSG("Key Pair found");
- *cert = current->buffer;
- *certSz = current->bufferSz;
- if (previous == NULL) {
- *list = current->next;
- }
- else {
- previous->next = current->next;
- }
- FreeDecodedCert(DeCert);
- XFREE(current, heap, DYNAMIC_TYPE_PKCS);
- break;
- }
- }
- FreeDecodedCert(DeCert);
- previous = current;
- current = current->next;
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(DeCert, heap, DYNAMIC_TYPE_PKCS);
- #endif
- return 0;
- }
- #ifdef ASN_BER_TO_DER
- /* append data to encrypted content cache in PKCS12 structure
- * return buffer on success, NULL on error */
- static byte* PKCS12_ConcatonateContent(WC_PKCS12* pkcs12,byte* mergedData,
- word32* mergedSz, byte* in, word32 inSz)
- {
- byte* oldContent;
- word32 oldContentSz;
- (void)pkcs12;
- if (mergedData == NULL || in == NULL)
- return NULL;
- /* save pointer to old cache */
- oldContent = mergedData;
- oldContentSz = *mergedSz;
- /* re-allocate new buffer to fit appended data */
- mergedData = (byte*)XMALLOC(oldContentSz + inSz, pkcs12->heap,
- DYNAMIC_TYPE_PKCS);
- if (mergedData != NULL) {
- if (oldContent != NULL) {
- XMEMCPY(mergedData, oldContent, oldContentSz);
- }
- XMEMCPY(mergedData + oldContentSz, in, inSz);
- *mergedSz += inSz;
- }
- XFREE(oldContent, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- return mergedData;
- }
- /* Check if constructed [0] is seen after wc_BerToDer() or not.
- * returns 1 if seen, 0 if not, ASN_PARSE_E on error */
- static int PKCS12_CheckConstructedZero(byte* data, word32 dataSz, word32* idx)
- {
- word32 oid;
- int ret = 0;
- int number, size;
- byte tag = 0;
- if (GetSequence(data, idx, &size, dataSz) < 0) {
- ret = ASN_PARSE_E;
- }
- if (ret == 0 && GetObjectId(data, idx, &oid, oidIgnoreType, dataSz)) {
- ret = ASN_PARSE_E;
- }
- if (ret == 0 && GetSequence(data, idx, &size, dataSz) < 0) {
- ret = ASN_PARSE_E;
- }
- if (ret == 0 && GetOctetString(data, idx, &size, dataSz) < 0) {
- ret = ASN_PARSE_E;
- }
- *idx += (word32)size;
- if (ret == 0 && GetShortInt(data, idx, &number, dataSz) < 0) {
- ret = ASN_PARSE_E;
- }
- /* Check if wc_BerToDer() handled constructed [0] and octet
- * strings properly, manually fix it if not. */
- if (ret == 0 && GetASNTag(data, idx, &tag, dataSz) < 0) {
- ret = ASN_PARSE_E;
- }
- else if (ret == 0 && tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
- ret = 1;
- }
- return ret;
- }
- /* Manually coalesce definite length octet strings into one unconstructed
- * definite length octet string.
- * returns 0 on success, negative on failure */
- static int PKCS12_CoalesceOctetStrings(WC_PKCS12* pkcs12, byte* data,
- word32 dataSz, word32* idx, int* curIdx)
- {
- byte* mergedData = NULL; /* buffer for concatenated strings */
- word32 mergedSz = 0; /* total size of merged strings */
- int encryptedContentSz = 0;
- int originalEncSz = 0;
- int ret = 0;
- word32 saveIdx;
- byte tag;
- saveIdx = *idx;
- if (GetLength(data, idx, &originalEncSz, dataSz) < 0) {
- ret = ASN_PARSE_E;
- }
- /* Loop through octet strings and concatenate them without
- * the tags and length */
- while ((int)*idx < originalEncSz + *curIdx) {
- if (GetASNTag(data, idx, &tag, dataSz) < 0) {
- ret = ASN_PARSE_E;
- }
- if (ret == 0 && (tag != ASN_OCTET_STRING)) {
- ret = ASN_PARSE_E;
- }
- if (ret == 0 && GetLength(data, idx,
- &encryptedContentSz, dataSz) <= 0) {
- ret = ASN_PARSE_E;
- }
- if (ret == 0) {
- if (mergedData == NULL) {
- mergedData = (byte*)XMALLOC((size_t)encryptedContentSz,
- pkcs12->heap, DYNAMIC_TYPE_PKCS);
- if (mergedData == NULL) {
- ret = MEMORY_E;
- }
- }
- mergedData = PKCS12_ConcatonateContent(pkcs12, mergedData,
- &mergedSz, &data[*idx], (word32)encryptedContentSz);
- if (mergedData == NULL) {
- ret = MEMORY_E;
- }
- }
- if (ret != 0) {
- break;
- }
- *idx += (word32)encryptedContentSz;
- }
- *idx = saveIdx;
- *idx += SetLength(mergedSz, &data[*idx]);
- if (mergedSz > 0) {
- /* Copy over concatenated octet strings into data buffer */
- XMEMCPY(&data[*idx], mergedData, mergedSz);
- XFREE(mergedData, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- }
- return ret;
- }
- #endif
- /* return 0 on success and negative on failure.
- * By side effect returns private key, cert, and optionally ca.
- * Parses and decodes the parts of PKCS12
- *
- * NOTE: can parse with USER RSA enabled but may return cert that is not the
- * pair for the key when using RSA key pairs.
- *
- * pkcs12 : non-null WC_PKCS12 struct
- * psw : password to use for PKCS12 decode
- * pkey : Private key returned
- * cert : x509 cert returned
- * ca : optional ca returned
- */
- int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
- byte** pkey, word32* pkeySz, byte** cert, word32* certSz,
- WC_DerCertList** ca)
- {
- ContentInfo* ci = NULL;
- WC_DerCertList* certList = NULL;
- WC_DerCertList* tailList = NULL;
- byte* buf = NULL;
- word32 i, oid;
- word32 algId;
- int ret, pswSz;
- #ifdef ASN_BER_TO_DER
- int curIdx;
- #endif
- WOLFSSL_ENTER("wc_PKCS12_parse");
- if (pkcs12 == NULL || psw == NULL || cert == NULL || certSz == NULL ||
- pkey == NULL || pkeySz == NULL) {
- return BAD_FUNC_ARG;
- }
- pswSz = (int)XSTRLEN(psw);
- *cert = NULL;
- *pkey = NULL;
- if (ca != NULL)
- *ca = NULL;
- /* if there is sign data then verify the MAC */
- if (pkcs12->signData != NULL ) {
- if ((ret = wc_PKCS12_verify(pkcs12, pkcs12->safe->data,
- pkcs12->safe->dataSz, (byte*)psw, (word32)pswSz)) != 0) {
- WOLFSSL_MSG("PKCS12 Bad MAC on verify");
- WOLFSSL_LEAVE("wc_PKCS12_parse verify ", ret);
- (void)ret;
- return MAC_CMP_FAILED_E;
- }
- }
- if (pkcs12->safe == NULL) {
- WOLFSSL_MSG("No PKCS12 safes to parse");
- return BAD_FUNC_ARG;
- }
- /* Decode content infos */
- ci = pkcs12->safe->CI;
- for (i = 0; i < pkcs12->safe->numCI; i++) {
- byte* data;
- word32 idx = 0;
- int size, totalSz;
- byte tag;
- data = ci->data;
- if (ci->type == WC_PKCS12_ENCRYPTED_DATA) {
- int number;
- WOLFSSL_MSG("Decrypting PKCS12 Content Info Container");
- if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) {
- goto exit_pk12par;
- }
- if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) {
- goto exit_pk12par;
- }
- if ((ret = GetShortInt(data, &idx, &number, ci->dataSz)) < 0) {
- goto exit_pk12par;
- }
- if (number != 0) {
- WOLFSSL_MSG("Expecting 0 for Integer with Encrypted PKCS12");
- }
- if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) {
- goto exit_pk12par;
- }
- ret = GetObjectId(data, &idx, &oid, oidIgnoreType, ci->dataSz);
- if (ret < 0 || oid != WC_PKCS12_DATA) {
- WOLFSSL_MSG("Not PKCS12 DATA object or get object parse error");
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- #ifdef ASN_BER_TO_DER
- curIdx = (int)idx;
- /* If indefinite length format, ensure it is in the ASN format
- * the DecryptContent() expects */
- if (pkcs12->indefinite && PKCS12_CheckConstructedZero(data,
- ci->dataSz, &idx) == 1) {
- data[idx-1] = ASN_LONG_LENGTH;
- ret = PKCS12_CoalesceOctetStrings(pkcs12, data, ci->dataSz,
- &idx, &curIdx);
- if (ret < 0) {
- goto exit_pk12par;
- }
- }
- idx = (word32)curIdx;
- #endif
- /* decrypted content overwrites input buffer */
- size = (int)(ci->dataSz - idx);
- buf = (byte*)XMALLOC((size_t)size, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- if (buf == NULL) {
- ERROR_OUT(MEMORY_E, exit_pk12par);
- }
- XMEMCPY(buf, data + idx, (size_t)size);
- if ((ret = DecryptContent(buf, (word32)size, psw, pswSz)) < 0) {
- WOLFSSL_MSG("Decryption failed, algorithm not compiled in?");
- goto exit_pk12par;
- }
- data = buf;
- idx = 0;
- #ifdef WOLFSSL_DEBUG_PKCS12
- {
- byte* p;
- for (printf("\tData = "), p = (byte*)buf;
- p < (byte*)buf + size;
- printf("%02X", *p), p++);
- printf("\n");
- }
- #endif
- }
- else { /* type DATA */
- WOLFSSL_MSG("Parsing PKCS12 DATA Content Info Container");
- if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if (GetLength(data, &idx, &size, ci->dataSz) <= 0) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if (tag != ASN_OCTET_STRING) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) {
- goto exit_pk12par;
- }
- }
- /* parse through bags in ContentInfo */
- if ((ret = GetSequence(data, &idx, &totalSz, ci->dataSz)) < 0) {
- goto exit_pk12par;
- }
- totalSz += (int)idx;
- while ((int)idx < totalSz) {
- int bagSz;
- if ((ret = GetSequence(data, &idx, &bagSz, ci->dataSz)) < 0) {
- goto exit_pk12par;
- }
- bagSz += (int)idx;
- if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType,
- ci->dataSz)) < 0) {
- goto exit_pk12par;
- }
- switch (oid) {
- case WC_PKCS12_KeyBag: /* 667 */
- WOLFSSL_MSG("PKCS12 Key Bag found");
- if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) {
- if (ret == 0)
- ret = ASN_PARSE_E;
- goto exit_pk12par;
- }
- if (*pkey == NULL) {
- *pkey = (byte*)XMALLOC((size_t)size, pkcs12->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (*pkey == NULL) {
- ERROR_OUT(MEMORY_E, exit_pk12par);
- }
- XMEMCPY(*pkey, data + idx, (size_t)size);
- *pkeySz = (word32)ToTraditional_ex(*pkey, (word32)size, &algId);
- }
- #ifdef WOLFSSL_DEBUG_PKCS12
- {
- byte* p;
- for (printf("\tKey = "), p = (byte*)*pkey;
- p < (byte*)*pkey + size;
- printf("%02X", *p), p++);
- printf("\n");
- }
- #endif
- idx += (word32)size;
- break;
- case WC_PKCS12_ShroudedKeyBag: /* 668 */
- {
- byte* k;
- WOLFSSL_MSG("PKCS12 Shrouded Key Bag found");
- if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if ((ret = GetLength(data, &idx, &size,
- ci->dataSz)) < 0) {
- goto exit_pk12par;
- }
- k = (byte*)XMALLOC((size_t)size, pkcs12->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (k == NULL) {
- ERROR_OUT(MEMORY_E, exit_pk12par);
- }
- XMEMCPY(k, data + idx, (size_t)size);
- /* overwrites input, be warned */
- if ((ret = ToTraditionalEnc(k, (word32)size, psw, pswSz,
- &algId)) < 0) {
- XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- goto exit_pk12par;
- }
- if (ret < size) {
- /* shrink key buffer */
- byte* tmp = (byte*)XMALLOC((size_t)ret, pkcs12->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (tmp == NULL) {
- XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- ERROR_OUT(MEMORY_E, exit_pk12par);
- }
- XMEMCPY(tmp, k, (size_t)ret);
- XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- k = tmp;
- }
- size = ret;
- if (*pkey == NULL) {
- *pkey = k;
- *pkeySz = (word32)size;
- }
- else { /* only expecting one key */
- XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- idx += (word32)size;
- #ifdef WOLFSSL_DEBUG_PKCS12
- {
- byte* p;
- for (printf("\tKey = "), p = (byte*)k;
- p < (byte*)k + ret;
- printf("%02X", *p), p++);
- printf("\n");
- }
- #endif
- }
- break;
- case WC_PKCS12_CertBag: /* 669 */
- {
- WC_DerCertList* node;
- WOLFSSL_MSG("PKCS12 Cert Bag found");
- if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) {
- goto exit_pk12par;
- }
- /* get cert bag type */
- if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) <0) {
- goto exit_pk12par;
- }
- if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType,
- ci->dataSz)) < 0) {
- goto exit_pk12par;
- }
- switch (oid) {
- case WC_PKCS12_CertBag_Type1: /* 675 */
- /* type 1 */
- WOLFSSL_MSG("PKCS12 cert bag type 1");
- if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if (tag != (ASN_CONSTRUCTED |
- ASN_CONTEXT_SPECIFIC)) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if ((ret = GetLength(data, &idx, &size, ci->dataSz))
- <= 0) {
- if (ret == 0)
- ret = ASN_PARSE_E;
- goto exit_pk12par;
- }
- if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if (tag != ASN_OCTET_STRING) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- if ((ret = GetLength(data, &idx, &size, ci->dataSz))
- < 0) {
- goto exit_pk12par;
- }
- break;
- default:
- WOLFSSL_MSG("Unknown PKCS12 cert bag type");
- }
- if (size + (int)idx > bagSz) {
- ERROR_OUT(ASN_PARSE_E, exit_pk12par);
- }
- /* list to hold all certs found */
- node = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList),
- pkcs12->heap, DYNAMIC_TYPE_PKCS);
- if (node == NULL) {
- ERROR_OUT(MEMORY_E, exit_pk12par);
- }
- XMEMSET(node, 0, sizeof(WC_DerCertList));
- node->buffer = (byte*)XMALLOC((size_t)size, pkcs12->heap,
- DYNAMIC_TYPE_PKCS);
- if (node->buffer == NULL) {
- XFREE(node, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- ERROR_OUT(MEMORY_E, exit_pk12par);
- }
- XMEMCPY(node->buffer, data + idx, (size_t)size);
- node->bufferSz = (word32)size;
- /* put the new node into the list */
- if (certList != NULL) {
- WOLFSSL_MSG("Pushing new cert onto queue");
- tailList->next = node;
- tailList = node;
- }
- else {
- certList = node;
- tailList = node;
- }
- /* on to next */
- idx += (word32)size;
- }
- break;
- case WC_PKCS12_CrlBag: /* 670 */
- WOLFSSL_MSG("PKCS12 CRL BAG not yet supported");
- break;
- case WC_PKCS12_SecretBag: /* 671 */
- WOLFSSL_MSG("PKCS12 Secret BAG not yet supported");
- break;
- case WC_PKCS12_SafeContentsBag: /* 672 */
- WOLFSSL_MSG("PKCS12 Safe Contents BAG not yet supported");
- break;
- default:
- WOLFSSL_MSG("Unknown PKCS12 BAG type found");
- }
- /* Attribute, unknown bag or unsupported */
- if ((int)idx < bagSz) {
- idx = (word32)bagSz; /* skip for now */
- }
- }
- /* free temporary buffer */
- if (buf != NULL) {
- XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- buf = NULL;
- }
- ci = ci->next;
- WOLFSSL_MSG("Done Parsing PKCS12 Content Info Container");
- }
- /* check if key pair, remove from list */
- if (*pkey != NULL) {
- ret = freeDecCertList(&certList, pkey, pkeySz, cert, certSz,
- pkcs12->heap);
- if (ret < 0)
- goto exit_pk12par;
- }
- /* if ca arg provided return certList, otherwise free it */
- if (ca != NULL) {
- *ca = certList;
- }
- else {
- /* free list, not wanted */
- wc_FreeCertList(certList, pkcs12->heap);
- }
- (void)tailList; /* not used */
- ret = 0; /* success */
- exit_pk12par:
- if (ret != 0) {
- /* failure cleanup */
- if (*pkey) {
- XFREE(*pkey, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- *pkey = NULL;
- }
- if (buf) {
- XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- buf = NULL;
- }
- wc_FreeCertList(certList, pkcs12->heap);
- }
- return ret;
- }
- /* Helper function to shroud keys.
- *
- * pkcs12 structure to use with shrouding key
- * rng random number generator used
- * out buffer to hold results
- * outSz size of out buffer
- * key key that is going to be shrouded
- * keySz size of key buffer
- * vAlgo algorithm version
- * pass password to use
- * passSz size of pass buffer
- * itt number of iterations
- *
- * returns the size of the shrouded key on success
- */
- static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng,
- byte* out, word32* outSz, byte* key, word32 keySz, int vAlgo,
- const char* pass, int passSz, int itt)
- {
- void* heap;
- word32 tmpIdx = 0;
- int vPKCS = 1; /* PKCS#12 default set to 1 */
- word32 sz;
- word32 totalSz = 0;
- int ret;
- byte* pkcs8Key = NULL;
- if (outSz == NULL || pkcs12 == NULL || rng == NULL || key == NULL ||
- pass == NULL) {
- return BAD_FUNC_ARG;
- }
- heap = wc_PKCS12_GetHeap(pkcs12);
- /* check if trying to get size */
- if (out != NULL) {
- tmpIdx += MAX_LENGTH_SZ + 1; /* save room for length and tag (+1) */
- sz = *outSz - tmpIdx;
- pkcs8Key = out + tmpIdx;
- }
- /* case of no encryption */
- if (vAlgo < 0) {
- const byte* curveOID = NULL;
- word32 oidSz = 0;
- int algoID;
- WOLFSSL_MSG("creating PKCS12 Key Bag");
- /* check key type and get OID if ECC */
- if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap))
- < 0) {
- return ret;
- }
- /* PKCS#8 wrapping around key */
- ret = wc_CreatePKCS8Key(pkcs8Key, &sz, key, keySz, algoID, curveOID,
- oidSz);
- }
- else {
- WOLFSSL_MSG("creating PKCS12 Shrouded Key Bag");
- if (vAlgo == PBE_SHA1_DES) {
- vPKCS = PKCS5;
- vAlgo = 10;
- }
- ret = UnTraditionalEnc(key, keySz, pkcs8Key, &sz, pass, passSz,
- vPKCS, vAlgo, NULL, 0, itt, rng, heap);
- }
- if (ret == LENGTH_ONLY_E) {
- *outSz = sz + MAX_LENGTH_SZ + 1;
- return LENGTH_ONLY_E;
- }
- if (ret < 0) {
- return ret;
- }
- totalSz += (word32)ret;
- /* out should not be null at this point but check before writing */
- if (out == NULL) {
- return BAD_FUNC_ARG;
- }
- /* rewind index and set tag and length */
- tmpIdx -= MAX_LENGTH_SZ + 1;
- sz = (word32)SetExplicit(0, (word32)ret, out + tmpIdx);
- tmpIdx += sz; totalSz += sz;
- XMEMMOVE(out + tmpIdx, out + MAX_LENGTH_SZ + 1, (size_t)ret);
- return (int)totalSz;
- }
- /* Helper function to create key bag.
- *
- * pkcs12 structure to use with key bag
- * rng random number generator used
- * out buffer to hold results
- * outSz size of out buffer
- * key key that is going into key bag
- * keySz size of key buffer
- * algo algorithm version
- * iter number of iterations
- * pass password to use
- * passSz size of pass buffer
- *
- * returns the size of the key bag on success
- */
- static int wc_PKCS12_create_key_bag(WC_PKCS12* pkcs12, WC_RNG* rng,
- byte* out, word32* outSz, byte* key, word32 keySz, int algo, int iter,
- char* pass, int passSz)
- {
- void* heap;
- byte* tmp;
- word32 length = 0;
- word32 idx = 0;
- word32 totalSz = 0;
- word32 sz;
- word32 i;
- word32 tmpSz;
- int ret;
- /* get max size for shrouded key */
- ret = wc_PKCS12_shroud_key(pkcs12, rng, NULL, &length, key, keySz,
- algo, pass, passSz, iter);
- if (ret != LENGTH_ONLY_E && ret < 0) {
- return ret;
- }
- if (out == NULL) {
- *outSz = MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ + 1 + MAX_LENGTH_SZ +
- length;
- return LENGTH_ONLY_E;
- }
- heap = wc_PKCS12_GetHeap(pkcs12);
- /* leave room for sequence */
- idx += MAX_SEQ_SZ;
- if (algo < 0) { /* not encrypted */
- out[idx++] = ASN_OBJECT_ID; totalSz++;
- sz = SetLength(sizeof(WC_PKCS12_KeyBag_OID), out + idx);
- idx += sz; totalSz += sz;
- for (i = 0; i < sizeof(WC_PKCS12_KeyBag_OID); i++) {
- out[idx++] = WC_PKCS12_KeyBag_OID[i]; totalSz++;
- }
- }
- else { /* encrypted */
- out[idx++] = ASN_OBJECT_ID; totalSz++;
- sz = SetLength(sizeof(WC_PKCS12_ShroudedKeyBag_OID), out + idx);
- idx += sz; totalSz += sz;
- for (i = 0; i < sizeof(WC_PKCS12_ShroudedKeyBag_OID); i++) {
- out[idx++] = WC_PKCS12_ShroudedKeyBag_OID[i]; totalSz++;
- }
- }
- /* shroud key */
- tmp = (byte*)XMALLOC(length, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (tmp == NULL) {
- return MEMORY_E;
- }
- ret = wc_PKCS12_shroud_key(pkcs12, rng, tmp, &length, key, keySz,
- algo, pass, passSz, iter);
- if (ret < 0) {
- XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
- length = (word32)ret;
- XMEMCPY(out + idx, tmp, (size_t)length);
- XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
- totalSz += length;
- /* set beginning sequence */
- tmpSz = SetSequence(totalSz, out);
- XMEMMOVE(out + tmpSz, out + MAX_SEQ_SZ, totalSz);
- (void)heap;
- return (int)(totalSz + tmpSz);
- }
- /* Helper function to create cert bag.
- *
- * pkcs12 structure to use with cert bag
- * out buffer to hold results
- * outSz size of out buffer
- * cert cert that is going into cert bag
- * certSz size of cert buffer
- *
- * returns the size of the cert bag on success
- */
- static int wc_PKCS12_create_cert_bag(WC_PKCS12* pkcs12,
- byte* out, word32* outSz, byte* cert, word32 certSz)
- {
- word32 length = 0;
- word32 idx = 0;
- word32 totalSz = 0;
- word32 sz;
- int WC_CERTBAG_OBJECT_ID = 13;
- int WC_CERTBAG1_OBJECT_ID = 12;
- word32 i;
- word32 tmpSz;
- if (out == NULL) {
- *outSz = (word32)(MAX_SEQ_SZ + WC_CERTBAG_OBJECT_ID + 1 + MAX_LENGTH_SZ +
- MAX_SEQ_SZ + WC_CERTBAG1_OBJECT_ID + 1 + MAX_LENGTH_SZ + 1 +
- MAX_LENGTH_SZ + (int)certSz);
- return LENGTH_ONLY_E;
- }
- /* check buffer size able to handle max size */
- if (*outSz < (word32)(MAX_SEQ_SZ + WC_CERTBAG_OBJECT_ID + 1 + MAX_LENGTH_SZ +
- MAX_SEQ_SZ + WC_CERTBAG1_OBJECT_ID + 1 + MAX_LENGTH_SZ + 1 +
- MAX_LENGTH_SZ + (int)certSz)) {
- return BUFFER_E;
- }
- /* save room for sequence */
- idx += MAX_SEQ_SZ;
- /* objectId WC_PKCS12_CertBag */
- out[idx++] = ASN_OBJECT_ID; totalSz++;
- sz = SetLength(sizeof(WC_PKCS12_CertBag_OID), out + idx);
- idx += sz; totalSz += sz;
- for (i = 0; i < sizeof(WC_PKCS12_CertBag_OID); i++) {
- out[idx++] = WC_PKCS12_CertBag_OID[i]; totalSz++;
- }
- /**** Cert Bag type 1 ****/
- out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); totalSz++;
- /* save room for length and sequence */
- idx += MAX_LENGTH_SZ;
- idx += MAX_SEQ_SZ;
- /* object id WC_PKCS12_CertBag_Type1 */
- out[idx++] = ASN_OBJECT_ID; length++;
- sz = SetLength(sizeof(WC_PKCS12_CertBag_Type1_OID), out + idx);
- idx += sz; length += sz;
- for (i = 0; i < sizeof(WC_PKCS12_CertBag_Type1_OID); i++) {
- out[idx++] = WC_PKCS12_CertBag_Type1_OID[i]; length++;
- }
- out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); length++;
- sz = 0;
- idx += MAX_LENGTH_SZ; /* save room for length */
- /* place the cert in the buffer */
- out[idx++] = ASN_OCTET_STRING; sz++;
- tmpSz = SetLength(certSz, out + idx);
- idx += tmpSz; sz += tmpSz;
- XMEMCPY(out + idx, cert, certSz);
- idx += certSz; sz += certSz;
- /* rewind idx and place length */
- idx -= (sz + MAX_LENGTH_SZ);
- tmpSz = SetLength(sz, out + idx);
- XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, sz);
- idx += tmpSz + sz; length += tmpSz + sz;
- /* rewind idx and set sequence */
- idx -= (length + MAX_SEQ_SZ);
- tmpSz = SetSequence(length, out + idx);
- XMEMMOVE(out + idx + tmpSz, out + idx + MAX_SEQ_SZ, length);
- length += tmpSz;
- /* place final length */
- idx -= MAX_LENGTH_SZ;
- tmpSz = SetLength(length, out + idx);
- XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length);
- length += tmpSz;
- /* place final sequence */
- totalSz += length;
- tmpSz = SetSequence(totalSz, out);
- XMEMMOVE(out + tmpSz, out + MAX_SEQ_SZ, totalSz);
- (void)pkcs12;
- return (int)(totalSz + tmpSz);
- }
- /* Helper function to encrypt content.
- *
- * pkcs12 structure to use with key bag
- * rng random number generator used
- * out buffer to hold results
- * outSz size of out buffer
- * content content to encrypt
- * contentSz size of content buffer
- * vAlgo algorithm version
- * pass password to use
- * passSz size of pass buffer
- * iter number of iterations
- * type content type i.e WC_PKCS12_ENCRYPTED_DATA or WC_PKCS12_DATA
- *
- * returns the size of result on success
- */
- static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng,
- byte* out, word32* outSz, byte* content, word32 contentSz, int vAlgo,
- const char* pass, int passSz, int iter, int type)
- {
- void* heap;
- int vPKCS = 1; /* PKCS#12 is always set to 1 */
- int ret;
- byte* tmp;
- word32 idx = 0;
- word32 totalSz = 0;
- word32 length = 0;
- word32 tmpSz;
- word32 encSz;
- byte seq[MAX_SEQ_SZ];
- WOLFSSL_MSG("encrypting PKCS12 content");
- heap = wc_PKCS12_GetHeap(pkcs12);
- /* ENCRYPTED DATA
- * ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC
- * length
- * sequence
- * short int
- * sequence
- * get object id */
- if (type == WC_PKCS12_ENCRYPTED_DATA) {
- word32 outerSz = 0;
- encSz = contentSz;
- if ((ret = EncryptContent(NULL, contentSz, NULL, &encSz,
- pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) {
- if (ret != LENGTH_ONLY_E) {
- return ret;
- }
- }
- /* calculate size */
- totalSz = (word32)SetObjectId(sizeof(WC_PKCS12_ENCRYPTED_OID), seq);
- totalSz += sizeof(WC_PKCS12_ENCRYPTED_OID);
- totalSz += ASN_TAG_SZ;
- length = (word32)SetMyVersion(0, seq, 0);
- tmpSz = (word32)SetObjectId(sizeof(WC_PKCS12_DATA_OID), seq);
- tmpSz += sizeof(WC_PKCS12_DATA_OID);
- tmpSz += encSz;
- length += SetSequence(tmpSz, seq) + tmpSz;
- outerSz = SetSequence(length, seq) + length;
- totalSz += SetLength(outerSz, seq) + outerSz;
- if (out == NULL) {
- *outSz = totalSz + SetSequence(totalSz, seq);
- return LENGTH_ONLY_E;
- }
- if (*outSz < totalSz + SetSequence(totalSz, seq)) {
- return BUFFER_E;
- }
- idx = 0;
- idx += SetSequence(totalSz, out + idx);
- idx += (word32)SetObjectId(sizeof(WC_PKCS12_ENCRYPTED_OID), out + idx);
- if (idx + sizeof(WC_PKCS12_ENCRYPTED_OID) > *outSz){
- return BUFFER_E;
- }
- XMEMCPY(out + idx, WC_PKCS12_ENCRYPTED_OID,
- sizeof(WC_PKCS12_ENCRYPTED_OID));
- idx += sizeof(WC_PKCS12_ENCRYPTED_OID);
- if (idx + 1 > *outSz){
- return BUFFER_E;
- }
- out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC);
- idx += SetLength(outerSz, out + idx);
- idx += SetSequence(length, out + idx);
- idx += (word32)SetMyVersion(0, out + idx, 0);
- tmp = (byte*)XMALLOC(encSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (tmp == NULL) {
- return MEMORY_E;
- }
- if ((ret = EncryptContent(content, contentSz, tmp, &encSz,
- pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) {
- XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
- encSz = (word32)ret;
- #ifdef WOLFSSL_DEBUG_PKCS12
- {
- byte* p;
- for (printf("(size %u) Encrypted Content = ", encSz),
- p = (byte*)tmp;
- p < (byte*)tmp + encSz;
- printf("%02X", *p), p++);
- printf("\n");
- }
- #endif
- idx += SetSequence(WC_PKCS12_DATA_OBJ_SZ + encSz, out + idx);
- idx += (word32)SetObjectId(sizeof(WC_PKCS12_DATA_OID), out + idx);
- if (idx + sizeof(WC_PKCS12_DATA_OID) > *outSz){
- WOLFSSL_MSG("Buffer not large enough for DATA OID");
- XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
- return BUFFER_E;
- }
- XMEMCPY(out + idx, WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID));
- idx += sizeof(WC_PKCS12_DATA_OID);
- /* copy over encrypted data */
- if (idx + encSz > *outSz){
- XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
- return BUFFER_E;
- }
- XMEMCPY(out + idx, tmp, encSz);
- XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
- idx += encSz;
- return (int)idx;
- }
- /* DATA
- * ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC
- * length
- * ASN_OCTET_STRING
- * length
- * sequence containing all bags */
- if (type == WC_PKCS12_DATA) {
- /* calculate size */
- totalSz = (word32)SetObjectId(sizeof(WC_PKCS12_DATA_OID), seq);
- totalSz += sizeof(WC_PKCS12_DATA_OID);
- totalSz += ASN_TAG_SZ;
- length = SetOctetString(contentSz, seq);
- length += contentSz;
- totalSz += SetLength(length, seq);
- totalSz += length;
- if (out == NULL) {
- *outSz = totalSz + SetSequence(totalSz, seq);
- return LENGTH_ONLY_E;
- }
- if (*outSz < (totalSz + SetSequence(totalSz, seq))) {
- return BUFFER_E;
- }
- /* place data in output buffer */
- idx = 0;
- idx += SetSequence(totalSz, out);
- idx += (word32)SetObjectId(sizeof(WC_PKCS12_DATA_OID), out + idx);
- if (idx + sizeof(WC_PKCS12_DATA_OID) > *outSz){
- WOLFSSL_MSG("Buffer not large enough for DATA OID");
- return BUFFER_E;
- }
- XMEMCPY(out + idx, WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID));
- idx += sizeof(WC_PKCS12_DATA_OID);
- if (idx + 1 > *outSz){
- return BUFFER_E;
- }
- out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC);
- idx += SetLength(length, out + idx);
- idx += SetOctetString(contentSz, out + idx);
- if (idx + contentSz > *outSz){
- return BUFFER_E;
- }
- XMEMCPY(out + idx, content, contentSz);
- idx += contentSz;
- return (int)idx;
- }
- WOLFSSL_MSG("Unknown/Unsupported content type");
- return BAD_FUNC_ARG;
- }
- /* helper function to create the PKCS12 key content
- * keyCiSz is output buffer size
- * returns a pointer to be free'd by caller on success and NULL on failure */
- static byte* PKCS12_create_key_content(WC_PKCS12* pkcs12, int nidKey,
- word32* keyCiSz, WC_RNG* rng, char* pass, word32 passSz,
- byte* key, word32 keySz, int iter)
- {
- byte* keyBuf;
- word32 keyBufSz = 0;
- byte* keyCi = NULL;
- word32 tmpSz;
- int ret;
- int algo;
- void* heap;
- heap = wc_PKCS12_GetHeap(pkcs12);
- *keyCiSz = 0;
- switch (nidKey) {
- case PBE_SHA1_RC4_128:
- algo = 1;
- break;
- case PBE_SHA1_DES:
- algo = 2;
- break;
- case PBE_SHA1_DES3:
- algo = 3;
- break;
- /* no encryption */
- case -1:
- algo = -1;
- break;
- default:
- WOLFSSL_MSG("Unknown/Unsupported key encryption");
- return NULL;
- }
- /* get max size for key bag */
- ret = wc_PKCS12_create_key_bag(pkcs12, rng, NULL, &keyBufSz, key, keySz,
- algo, iter, pass, (int)passSz);
- if (ret != LENGTH_ONLY_E && ret < 0) {
- WOLFSSL_MSG("Error getting key bag size");
- return NULL;
- }
- /* account for sequence around bag */
- keyBufSz += MAX_SEQ_SZ;
- keyBuf = (byte*)XMALLOC(keyBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (keyBuf == NULL) {
- WOLFSSL_MSG("Memory error creating keyBuf buffer");
- return NULL;
- }
- ret = wc_PKCS12_create_key_bag(pkcs12, rng, keyBuf + MAX_SEQ_SZ, &keyBufSz,
- key, keySz, algo, iter, pass, (int)passSz);
- if (ret < 0) {
- XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
- WOLFSSL_MSG("Error creating key bag");
- return NULL;
- }
- keyBufSz = (word32)ret;
- tmpSz = SetSequence(keyBufSz, keyBuf);
- XMEMMOVE(keyBuf + tmpSz, keyBuf + MAX_SEQ_SZ, keyBufSz);
- keyBufSz += tmpSz;
- #ifdef WOLFSSL_DEBUG_PKCS12
- {
- word32 i;
- printf("(size %u) Key Bag = ", keyBufSz);
- for (i = 0; i < keyBufSz; i++)
- printf("%02X", keyBuf[i]);
- printf("\n");
- }
- #endif
- ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, keyCiSz,
- NULL, keyBufSz, algo, pass, (int)passSz, iter, WC_PKCS12_DATA);
- if (ret != LENGTH_ONLY_E) {
- XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
- WOLFSSL_MSG("Error getting key encrypt content size");
- return NULL;
- }
- keyCi = (byte*)XMALLOC(*keyCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (keyCi == NULL) {
- XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
- ret = wc_PKCS12_encrypt_content(pkcs12, rng, keyCi, keyCiSz,
- keyBuf, keyBufSz, algo, pass, (int)passSz, iter, WC_PKCS12_DATA);
- XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (ret < 0 ) {
- XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
- WOLFSSL_MSG("Error creating key encrypt content");
- return NULL;
- }
- *keyCiSz = (word32)ret;
- #ifdef WOLFSSL_DEBUG_PKCS12
- {
- word32 i;
- printf("(size %u) Key Content Info = ", *keyCiSz);
- for (i = 0; i < *keyCiSz; i++)
- printf("%02X", keyCi[i]);
- printf("\n");
- }
- #endif
- (void)heap;
- return keyCi;
- }
- /* helper function to create the PKCS12 certificate content
- * certCiSz is output buffer size
- * returns a pointer to be free'd by caller on success and NULL on failure */
- static byte* PKCS12_create_cert_content(WC_PKCS12* pkcs12, int nidCert,
- WC_DerCertList* ca, byte* cert, word32 certSz, word32* certCiSz,
- WC_RNG* rng, char* pass, word32 passSz, int iter)
- {
- int algo;
- int ret;
- int type;
- byte* certBuf = NULL;
- word32 certBufSz;
- word32 idx;
- word32 sz;
- word32 tmpSz;
- byte* certCi;
- void* heap;
- heap = wc_PKCS12_GetHeap(pkcs12);
- switch (nidCert) {
- case PBE_SHA1_RC4_128:
- type = WC_PKCS12_ENCRYPTED_DATA;
- algo = 1;
- break;
- case PBE_SHA1_DES:
- type = WC_PKCS12_ENCRYPTED_DATA;
- algo = 2;
- break;
- case PBE_SHA1_DES3:
- type = WC_PKCS12_ENCRYPTED_DATA;
- algo = 3;
- break;
- case -1:
- type = WC_PKCS12_DATA;
- algo = -1;
- break;
- default:
- WOLFSSL_MSG("Unknown/Unsupported certificate encryption");
- return NULL;
- }
- /* get max size of buffer needed */
- ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &certBufSz, cert, certSz);
- if (ret != LENGTH_ONLY_E) {
- return NULL;
- }
- if (ca != NULL) {
- WC_DerCertList* current = ca;
- word32 curBufSz = 0;
- /* get max buffer size */
- while (current != NULL) {
- ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &curBufSz,
- current->buffer, current->bufferSz);
- if (ret != LENGTH_ONLY_E) {
- return NULL;
- }
- certBufSz += curBufSz;
- current = current->next;
- }
- }
- /* account for Sequence that holds all certificate bags */
- certBufSz += MAX_SEQ_SZ;
- /* completed getting max size, now create buffer and start adding bags */
- certBuf = (byte*)XMALLOC(certBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (certBuf == NULL) {
- WOLFSSL_MSG("Memory error creating certificate bags");
- return NULL;
- }
- idx = 0;
- idx += MAX_SEQ_SZ;
- sz = certBufSz - idx;
- if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz,
- cert, certSz)) < 0) {
- XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
- idx += (word32)ret;
- if (ca != NULL) {
- WC_DerCertList* current = ca;
- while (current != NULL) {
- sz = certBufSz - idx;
- if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz,
- current->buffer, current->bufferSz)) < 0) {
- XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
- idx += (word32)ret;
- current = current->next;
- }
- }
- /* set sequence and create encrypted content with all certificate bags */
- tmpSz = SetSequence(idx - MAX_SEQ_SZ, certBuf);
- XMEMMOVE(certBuf + tmpSz, certBuf + MAX_SEQ_SZ, idx - MAX_SEQ_SZ);
- certBufSz = tmpSz + (idx - MAX_SEQ_SZ);
- /* get buffer size needed for content info */
- ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, certCiSz,
- NULL, certBufSz, algo, pass, (int)passSz, iter, type);
- if (ret != LENGTH_ONLY_E) {
- XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
- WOLFSSL_LEAVE("wc_PKCS12_create()", ret);
- return NULL;
- }
- certCi = (byte*)XMALLOC(*certCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (certCi == NULL) {
- XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
- ret = wc_PKCS12_encrypt_content(pkcs12, rng, certCi, certCiSz,
- certBuf, certBufSz, algo, pass, (int)passSz, iter, type);
- XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (ret < 0) {
- WOLFSSL_LEAVE("wc_PKCS12_create()", ret);
- XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
- *certCiSz = (word32)ret;
- #ifdef WOLFSSL_DEBUG_PKCS12
- {
- word32 i;
- printf("(size %u) Encrypted Certificate Content Info = ", *certCiSz);
- for (i = 0; i < *certCiSz; i++)
- printf("%02X", certCi[i]);
- printf("\n");
- }
- #endif
- (void)heap;
- return certCi;
- }
- /* helper function to create the PKCS12 safe
- * returns 0 on success */
- static int PKCS12_create_safe(WC_PKCS12* pkcs12, byte* certCi, word32 certCiSz,
- byte* keyCi, word32 keyCiSz, WC_RNG* rng, char* pass, word32 passSz,
- int iter)
- {
- int length;
- int ret;
- byte seq[MAX_SEQ_SZ];
- word32 safeDataSz;
- word32 innerDataSz;
- byte *innerData = NULL;
- byte *safeData = NULL;
- word32 idx;
- innerDataSz = certCiSz + keyCiSz+SetSequence(certCiSz + keyCiSz, seq);
- /* add Content Info structs to safe, key first then cert */
- ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, &safeDataSz,
- NULL, innerDataSz, 0, NULL, 0, 0, WC_PKCS12_DATA);
- if (ret != LENGTH_ONLY_E) {
- return ret;
- }
- safeData = (byte*)XMALLOC(safeDataSz, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (safeData == NULL) {
- WOLFSSL_MSG("Error malloc'ing safe data buffer");
- return MEMORY_E;
- }
- /* create sequence of inner data */
- innerData = (byte*)XMALLOC(innerDataSz, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- if (innerData == NULL) {
- WOLFSSL_MSG("Error malloc'ing inner data buffer");
- XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
- }
- idx = 0;
- idx += SetSequence(certCiSz + keyCiSz, innerData);
- XMEMCPY(innerData + idx, certCi, certCiSz);
- XMEMCPY(innerData + idx + certCiSz, keyCi, keyCiSz);
- ret = wc_PKCS12_encrypt_content(pkcs12, rng, safeData, &safeDataSz,
- innerData, innerDataSz, 0, pass, (int)passSz, iter, WC_PKCS12_DATA);
- XFREE(innerData, pkcs12->heap, DYNAMIC_TYPE_PKCS);
- if (ret < 0 ) {
- WOLFSSL_MSG("Error setting data type for safe contents");
- XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
- idx = 0;
- ret = GetSequence(safeData, &idx, &length, safeDataSz);
- if (ret < 0) {
- WOLFSSL_MSG("Error getting first sequence of safe");
- XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
- ret = GetSafeContent(pkcs12, safeData, &idx, safeDataSz);
- XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (ret < 0) {
- WOLFSSL_MSG("Unable to create safe contents");
- return ret;
- }
- return 0;
- }
- /*
- * pass : password to use with encryption
- * passSz : size of the password buffer
- * name : friendlyName to use
- * key : DER format of key
- * keySz : size of key buffer
- * cert : DER format of certificate
- * certSz : size of the certificate buffer
- * ca : a list of extra certificates
- * nidKey : type of encryption to use on the key (-1 means no encryption)
- * nidCert : type of encryption to use on the certificate
- * (-1 means no encryption)
- * iter : number of iterations with encryption
- * macIter : number of iterations when creating MAC
- * keyType : flag for signature and/or encryption key
- * heap : pointer to allocate from memory
- *
- * returns a pointer to a new WC_PKCS12 structure on success and NULL if failed
- */
- WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name,
- byte* key, word32 keySz, byte* cert, word32 certSz, WC_DerCertList* ca,
- int nidKey, int nidCert, int iter, int macIter, int keyType, void* heap)
- {
- WC_PKCS12* pkcs12;
- WC_RNG rng;
- int ret;
- byte* certCi = NULL;
- byte* keyCi = NULL;
- word32 certCiSz;
- word32 keyCiSz;
- WOLFSSL_ENTER("wc_PKCS12_create");
- if (wc_InitRng_ex(&rng, heap, INVALID_DEVID) != 0) {
- return NULL;
- }
- if ((pkcs12 = wc_PKCS12_new()) == NULL) {
- wc_FreeRng(&rng);
- WOLFSSL_LEAVE("wc_PKCS12_create", MEMORY_E);
- return NULL;
- }
- if ((ret = wc_PKCS12_SetHeap(pkcs12, heap)) != 0) {
- wc_PKCS12_free(pkcs12);
- wc_FreeRng(&rng);
- WOLFSSL_LEAVE("wc_PKCS12_create", ret);
- (void)ret;
- return NULL;
- }
- if (iter <= 0) {
- iter = WC_PKCS12_ITT_DEFAULT;
- }
- /**** add private key bag ****/
- keyCi = PKCS12_create_key_content(pkcs12, nidKey, &keyCiSz, &rng,
- pass, passSz, key, keySz, iter);
- if (keyCi == NULL) {
- wc_PKCS12_free(pkcs12);
- wc_FreeRng(&rng);
- return NULL;
- }
- /**** add main certificate bag and extras ****/
- certCi = PKCS12_create_cert_content(pkcs12, nidCert, ca, cert, certSz,
- &certCiSz, &rng, pass, passSz, iter);
- if (certCi == NULL) {
- XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
- wc_PKCS12_free(pkcs12);
- wc_FreeRng(&rng);
- return NULL;
- }
- /**** create safe and Content Info ****/
- ret = PKCS12_create_safe(pkcs12, certCi, certCiSz, keyCi, keyCiSz, &rng,
- pass, passSz, iter);
- XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (ret != 0) {
- WOLFSSL_MSG("Unable to create PKCS12 safe");
- wc_PKCS12_free(pkcs12);
- wc_FreeRng(&rng);
- return NULL;
- }
- /* create MAC */
- if (macIter > 0) {
- MacData* mac;
- byte digest[WC_MAX_DIGEST_SIZE]; /* for MAC */
- mac = (MacData*)XMALLOC(sizeof(MacData), heap, DYNAMIC_TYPE_PKCS);
- if (mac == NULL) {
- wc_PKCS12_free(pkcs12);
- wc_FreeRng(&rng);
- WOLFSSL_MSG("Error malloc'ing mac data buffer");
- return NULL;
- }
- XMEMSET(mac, 0, sizeof(MacData));
- pkcs12->signData = mac; /* now wc_PKCS12_free will free all mac too */
- #ifndef NO_SHA256
- mac->oid = SHA256h;
- #elif !defined(NO_SHA)
- mac->oid = SHA;
- #elif defined(WOLFSSL_SHA384)
- mac->oid = SHA384;
- #elif defined(WOLFSSL_SHA512)
- mac->oid = SHA512;
- #else
- WOLFSSL_MSG("No supported hash algorithm compiled in!");
- wc_PKCS12_free(pkcs12);
- wc_FreeRng(&rng);
- return NULL;
- #endif
- /* store number of iterations */
- mac->itt = macIter;
- /* set mac salt */
- mac->saltSz = WC_PKCS12_MAC_SALT_SZ;
- mac->salt = (byte*)XMALLOC(WC_PKCS12_MAC_SALT_SZ, heap,
- DYNAMIC_TYPE_PKCS);
- if (mac->salt == NULL) {
- wc_PKCS12_free(pkcs12);
- wc_FreeRng(&rng);
- WOLFSSL_MSG("Error malloc'ing salt data buffer");
- return NULL;
- }
- if (wc_RNG_GenerateBlock(&rng, mac->salt, mac->saltSz) != 0) {
- WOLFSSL_MSG("Error generating random salt");
- wc_PKCS12_free(pkcs12);
- wc_FreeRng(&rng);
- return NULL;
- }
- ret = wc_PKCS12_create_mac(pkcs12, pkcs12->safe->data,
- pkcs12->safe->dataSz, (const byte*)pass, passSz, digest,
- WC_MAX_DIGEST_SIZE);
- if (ret < 0) {
- wc_PKCS12_free(pkcs12);
- wc_FreeRng(&rng);
- WOLFSSL_MSG("Error creating mac");
- WOLFSSL_LEAVE("wc_PKCS12_create", ret);
- return NULL;
- }
- mac->digestSz = (word32)ret;
- mac->digest = (byte*)XMALLOC((size_t)ret, heap, DYNAMIC_TYPE_PKCS);
- if (mac->digest == NULL) {
- WOLFSSL_MSG("Error malloc'ing mac digest buffer");
- wc_PKCS12_free(pkcs12);
- wc_FreeRng(&rng);
- return NULL;
- }
- XMEMCPY(mac->digest, digest, mac->digestSz);
- }
- else {
- pkcs12->signData = NULL;
- }
- wc_FreeRng(&rng);
- (void)name;
- (void)keyType;
- return pkcs12;
- }
- /* if using a specific memory heap */
- int wc_PKCS12_SetHeap(WC_PKCS12* pkcs12, void* heap)
- {
- if (pkcs12 == NULL) {
- return BAD_FUNC_ARG;
- }
- pkcs12->heap = heap;
- return 0;
- }
- /* getter for heap */
- void* wc_PKCS12_GetHeap(WC_PKCS12* pkcs12)
- {
- if (pkcs12 == NULL) {
- return NULL;
- }
- return pkcs12->heap;
- }
- #undef ERROR_OUT
- #endif /* HAVE_PKCS12 && !NO_ASN && !NO_PWDBASED && !NO_HMAC */
|