1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122 |
- /* ssl_p7p12.c
- *
- * Copyright (C) 2006-2024 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
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <wolfssl/wolfcrypt/settings.h>
- #if defined(OPENSSL_EXTRA) && (defined(HAVE_FIPS) || defined(HAVE_SELFTEST))
- #include <wolfssl/wolfcrypt/pkcs7.h>
- #endif
- #if defined(OPENSSL_ALL) && defined(HAVE_PKCS7)
- #include <wolfssl/openssl/pkcs7.h>
- #endif
- #if !defined(WOLFSSL_SSL_P7P12_INCLUDED)
- #ifndef WOLFSSL_IGNORE_FILE_WARN
- #warning ssl_p7p12.c does not need to be compiled separately from ssl.c
- #endif
- #else
- #if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
- /*******************************************************************************
- * START OF PKCS7 APIs
- ******************************************************************************/
- #ifdef HAVE_PKCS7
- #ifdef OPENSSL_ALL
- PKCS7* wolfSSL_PKCS7_new(void)
- {
- WOLFSSL_PKCS7* pkcs7;
- int ret = 0;
- pkcs7 = (WOLFSSL_PKCS7*)XMALLOC(sizeof(WOLFSSL_PKCS7), NULL,
- DYNAMIC_TYPE_PKCS7);
- if (pkcs7 != NULL) {
- XMEMSET(pkcs7, 0, sizeof(WOLFSSL_PKCS7));
- ret = wc_PKCS7_Init(&pkcs7->pkcs7, NULL, INVALID_DEVID);
- }
- if (ret != 0 && pkcs7 != NULL) {
- XFREE(pkcs7, NULL, DYNAMIC_TYPE_PKCS7);
- pkcs7 = NULL;
- }
- return (PKCS7*)pkcs7;
- }
- /******************************************************************************
- * wolfSSL_PKCS7_SIGNED_new - allocates PKCS7 and initialize it for a signed data
- *
- * RETURNS:
- * returns pointer to the PKCS7 structure on success, otherwise returns NULL
- */
- PKCS7_SIGNED* wolfSSL_PKCS7_SIGNED_new(void)
- {
- byte signedData[]= { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02};
- PKCS7* pkcs7 = NULL;
- if ((pkcs7 = wolfSSL_PKCS7_new()) == NULL)
- return NULL;
- pkcs7->contentOID = SIGNED_DATA;
- if ((wc_PKCS7_SetContentType(pkcs7, signedData, sizeof(signedData))) < 0) {
- if (pkcs7) {
- wolfSSL_PKCS7_free(pkcs7);
- return NULL;
- }
- }
- return pkcs7;
- }
- void wolfSSL_PKCS7_free(PKCS7* pkcs7)
- {
- WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
- if (p7 != NULL) {
- if (p7->data != NULL)
- XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7);
- wc_PKCS7_Free(&p7->pkcs7);
- if (p7->certs)
- wolfSSL_sk_pop_free(p7->certs, NULL);
- XFREE(p7, NULL, DYNAMIC_TYPE_PKCS7);
- }
- }
- void wolfSSL_PKCS7_SIGNED_free(PKCS7_SIGNED* p7)
- {
- wolfSSL_PKCS7_free(p7);
- return;
- }
- /**
- * Convert DER/ASN.1 encoded signedData structure to internal PKCS7
- * structure. Note, does not support detached content.
- *
- * p7 - pointer to set to address of newly created PKCS7 structure on return
- * in - pointer to pointer of DER/ASN.1 data
- * len - length of input data, bytes
- *
- * Returns newly allocated and populated PKCS7 structure or NULL on error.
- */
- PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, int len)
- {
- return wolfSSL_d2i_PKCS7_ex(p7, in, len, NULL, 0);
- }
- /* This internal function is only decoding and setting up the PKCS7 struct. It
- * does not verify the PKCS7 signature.
- *
- * RETURNS:
- * returns pointer to a PKCS7 structure on success, otherwise returns NULL
- */
- static PKCS7* wolfSSL_d2i_PKCS7_only(PKCS7** p7, const unsigned char** in,
- int len, byte* content, word32 contentSz)
- {
- WOLFSSL_PKCS7* pkcs7 = NULL;
- WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_ex");
- if (in == NULL || *in == NULL || len < 0)
- return NULL;
- if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)
- return NULL;
- pkcs7->len = len;
- pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7);
- if (pkcs7->data == NULL) {
- wolfSSL_PKCS7_free((PKCS7*)pkcs7);
- return NULL;
- }
- XMEMCPY(pkcs7->data, *in, pkcs7->len);
- if (content != NULL) {
- pkcs7->pkcs7.content = content;
- pkcs7->pkcs7.contentSz = contentSz;
- }
- if (p7 != NULL)
- *p7 = (PKCS7*)pkcs7;
- *in += pkcs7->len;
- return (PKCS7*)pkcs7;
- }
- /*****************************************************************************
- * wolfSSL_d2i_PKCS7_ex - Converts the given unsigned char buffer of size len
- * into a PKCS7 object. Optionally, accepts a byte buffer of content which
- * is stored as the PKCS7 object's content, to support detached signatures.
- * @param content The content which is signed, in case the signature is
- * detached. Ignored if NULL.
- * @param contentSz The size of the passed in content.
- *
- * RETURNS:
- * returns pointer to a PKCS7 structure on success, otherwise returns NULL
- */
- PKCS7* wolfSSL_d2i_PKCS7_ex(PKCS7** p7, const unsigned char** in, int len,
- byte* content, word32 contentSz)
- {
- WOLFSSL_PKCS7* pkcs7 = NULL;
- WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_ex");
- if (in == NULL || *in == NULL || len < 0)
- return NULL;
- pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_d2i_PKCS7_only(p7, in, len, content,
- contentSz);
- if (pkcs7 != NULL) {
- if (wc_PKCS7_VerifySignedData(&pkcs7->pkcs7, pkcs7->data, pkcs7->len)
- != 0) {
- WOLFSSL_MSG("wc_PKCS7_VerifySignedData failed");
- wolfSSL_PKCS7_free((PKCS7*)pkcs7);
- if (p7 != NULL) {
- *p7 = NULL;
- }
- return NULL;
- }
- }
- return (PKCS7*)pkcs7;
- }
- /**
- * This API was added as a helper function for libest. It
- * extracts a stack of certificates from the pkcs7 object.
- * @param pkcs7 PKCS7 parameter object
- * @return WOLFSSL_STACK_OF(WOLFSSL_X509)*
- */
- WOLFSSL_STACK* wolfSSL_PKCS7_to_stack(PKCS7* pkcs7)
- {
- int i;
- WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
- WOLF_STACK_OF(WOLFSSL_X509)* ret = NULL;
- WOLFSSL_ENTER("wolfSSL_PKCS7_to_stack");
- if (!p7) {
- WOLFSSL_MSG("Bad parameter");
- return NULL;
- }
- if (p7->certs)
- return p7->certs;
- for (i = 0; i < MAX_PKCS7_CERTS && p7->pkcs7.cert[i]; i++) {
- WOLFSSL_X509* x509 = wolfSSL_X509_d2i_ex(NULL, p7->pkcs7.cert[i],
- p7->pkcs7.certSz[i], pkcs7->heap);
- if (!ret)
- ret = wolfSSL_sk_X509_new_null();
- if (x509) {
- if (wolfSSL_sk_X509_push(ret, x509) != WOLFSSL_SUCCESS) {
- wolfSSL_X509_free(x509);
- WOLFSSL_MSG("wolfSSL_sk_X509_push error");
- goto error;
- }
- }
- else {
- WOLFSSL_MSG("wolfSSL_X509_d2i error");
- goto error;
- }
- }
- /* Save stack to free later */
- if (p7->certs)
- wolfSSL_sk_pop_free(p7->certs, NULL);
- p7->certs = ret;
- return ret;
- error:
- if (ret) {
- wolfSSL_sk_pop_free(ret, NULL);
- }
- return NULL;
- }
- /**
- * Return stack of signers contained in PKCS7 cert.
- * Notes:
- * - Currently only PKCS#7 messages with a single signer cert is supported.
- * - Returned WOLFSSL_STACK must be freed by caller.
- *
- * pkcs7 - PKCS7 struct to retrieve signer certs from.
- * certs - currently unused
- * flags - flags to control function behavior.
- *
- * Return WOLFSSL_STACK of signers on success, NULL on error.
- */
- WOLFSSL_STACK* wolfSSL_PKCS7_get0_signers(PKCS7* pkcs7, WOLFSSL_STACK* certs,
- int flags)
- {
- WOLFSSL_X509* x509 = NULL;
- WOLFSSL_STACK* signers = NULL;
- WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
- if (p7 == NULL)
- return NULL;
- /* Only PKCS#7 messages with a single cert that is the verifying certificate
- * is supported.
- */
- if (flags & PKCS7_NOINTERN) {
- WOLFSSL_MSG("PKCS7_NOINTERN flag not supported");
- return NULL;
- }
- signers = wolfSSL_sk_X509_new_null();
- if (signers == NULL)
- return NULL;
- if (wolfSSL_d2i_X509(&x509, (const byte**)&p7->pkcs7.singleCert,
- p7->pkcs7.singleCertSz) == NULL) {
- wolfSSL_sk_X509_pop_free(signers, NULL);
- return NULL;
- }
- if (wolfSSL_sk_X509_push(signers, x509) != WOLFSSL_SUCCESS) {
- wolfSSL_sk_X509_pop_free(signers, NULL);
- return NULL;
- }
- (void)certs;
- return signers;
- }
- #ifndef NO_BIO
- PKCS7* wolfSSL_d2i_PKCS7_bio(WOLFSSL_BIO* bio, PKCS7** p7)
- {
- WOLFSSL_PKCS7* pkcs7;
- int ret;
- WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_bio");
- if (bio == NULL)
- return NULL;
- if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)
- return NULL;
- pkcs7->len = wolfSSL_BIO_get_len(bio);
- pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7);
- if (pkcs7->data == NULL) {
- wolfSSL_PKCS7_free((PKCS7*)pkcs7);
- return NULL;
- }
- if ((ret = wolfSSL_BIO_read(bio, pkcs7->data, pkcs7->len)) <= 0) {
- wolfSSL_PKCS7_free((PKCS7*)pkcs7);
- return NULL;
- }
- /* pkcs7->len may change if using b64 for example */
- pkcs7->len = ret;
- if (wc_PKCS7_VerifySignedData(&pkcs7->pkcs7, pkcs7->data, pkcs7->len)
- != 0) {
- WOLFSSL_MSG("wc_PKCS7_VerifySignedData failed");
- wolfSSL_PKCS7_free((PKCS7*)pkcs7);
- return NULL;
- }
- if (p7 != NULL)
- *p7 = (PKCS7*)pkcs7;
- return (PKCS7*)pkcs7;
- }
- int wolfSSL_i2d_PKCS7(PKCS7 *p7, unsigned char **out)
- {
- byte* output = NULL;
- int localBuf = 0;
- int len;
- WC_RNG rng;
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_i2d_PKCS7");
- if (!out || !p7) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- if (!p7->rng) {
- if (wc_InitRng(&rng) != 0) {
- WOLFSSL_MSG("wc_InitRng error");
- return WOLFSSL_FAILURE;
- }
- p7->rng = &rng; /* cppcheck-suppress autoVariables
- */
- }
- if ((len = wc_PKCS7_EncodeSignedData(p7, NULL, 0)) < 0) {
- WOLFSSL_MSG("wc_PKCS7_EncodeSignedData error");
- goto cleanup;
- }
- if (*out == NULL) {
- output = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (!output) {
- WOLFSSL_MSG("malloc error");
- goto cleanup;
- }
- localBuf = 1;
- }
- else {
- output = *out;
- }
- if ((len = wc_PKCS7_EncodeSignedData(p7, output, (word32)len)) < 0) {
- WOLFSSL_MSG("wc_PKCS7_EncodeSignedData error");
- goto cleanup;
- }
- ret = len;
- cleanup:
- if (p7->rng == &rng) {
- wc_FreeRng(&rng);
- p7->rng = NULL;
- }
- if (ret == WOLFSSL_FAILURE && localBuf && output)
- XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (ret != WOLFSSL_FAILURE)
- *out = output;
- return ret;
- }
- int wolfSSL_i2d_PKCS7_bio(WOLFSSL_BIO *bio, PKCS7 *p7)
- {
- byte* output = NULL;
- int len;
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_i2d_PKCS7_bio");
- if (!bio || !p7) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- if ((len = wolfSSL_i2d_PKCS7(p7, &output)) == WOLFSSL_FAILURE) {
- WOLFSSL_MSG("wolfSSL_i2d_PKCS7 error");
- goto cleanup;
- }
- if (wolfSSL_BIO_write(bio, output, len) <= 0) {
- WOLFSSL_MSG("wolfSSL_BIO_write error");
- goto cleanup;
- }
- ret = WOLFSSL_SUCCESS;
- cleanup:
- if (output)
- XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
- /**
- * Creates and returns a PKCS7 signedData structure.
- *
- * Inner content type is set to DATA to match OpenSSL behavior.
- *
- * signer - certificate to sign bundle with
- * pkey - private key matching signer
- * certs - optional additional set of certificates to include
- * in - input data to be signed
- * flags - optional set of flags to control sign behavior
- *
- * PKCS7_BINARY - Do not translate input data to MIME canonical
- * format (\r\n line endings), thus preventing corruption of
- * binary content.
- * PKCS7_TEXT - Prepend MIME headers for text/plain to content.
- * PKCS7_DETACHED - Set signature detached, omit content from output bundle.
- * PKCS7_STREAM - initialize PKCS7 struct for signing, do not read data.
- *
- * Flags not currently supported:
- * PKCS7_NOCERTS - Do not include the signer cert in the output bundle.
- * PKCS7_PARTIAL - Allow for PKCS7_sign() to be only partially set up,
- * then signers etc to be added separately before
- * calling PKCS7_final().
- *
- * Returns valid PKCS7 structure pointer, or NULL if an error occurred.
- */
- PKCS7* wolfSSL_PKCS7_sign(WOLFSSL_X509* signer, WOLFSSL_EVP_PKEY* pkey,
- WOLFSSL_STACK* certs, WOLFSSL_BIO* in, int flags)
- {
- int err = 0;
- WOLFSSL_PKCS7* p7 = NULL;
- WOLFSSL_STACK* cert = certs;
- WOLFSSL_ENTER("wolfSSL_PKCS7_sign");
- if (flags & PKCS7_NOCERTS) {
- WOLFSSL_MSG("PKCS7_NOCERTS flag not yet supported");
- err = 1;
- }
- if (flags & PKCS7_PARTIAL) {
- WOLFSSL_MSG("PKCS7_PARTIAL flag not yet supported");
- err = 1;
- }
- if ((err == 0) && (signer == NULL || signer->derCert == NULL ||
- signer->derCert->length == 0)) {
- WOLFSSL_MSG("Bad function arg, signer is NULL or incomplete");
- err = 1;
- }
- if ((err == 0) && (pkey == NULL || pkey->pkey.ptr == NULL ||
- pkey->pkey_sz <= 0)) {
- WOLFSSL_MSG("Bad function arg, pkey is NULL or incomplete");
- err = 1;
- }
- if ((err == 0) && (in == NULL) && !(flags & PKCS7_STREAM)) {
- WOLFSSL_MSG("input data required unless PKCS7_STREAM used");
- err = 1;
- }
- if ((err == 0) && ((p7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)) {
- WOLFSSL_MSG("Error allocating new WOLFSSL_PKCS7");
- err = 1;
- }
- /* load signer certificate */
- if (err == 0) {
- if (wc_PKCS7_InitWithCert(&p7->pkcs7, signer->derCert->buffer,
- signer->derCert->length) != 0) {
- WOLFSSL_MSG("Failed to load signer certificate");
- err = 1;
- }
- }
- /* set signer private key, data types, defaults */
- if (err == 0) {
- p7->pkcs7.privateKey = (byte*)pkey->pkey.ptr;
- p7->pkcs7.privateKeySz = (word32)pkey->pkey_sz;
- p7->pkcs7.contentOID = DATA; /* inner content default is DATA */
- p7->pkcs7.hashOID = SHA256h; /* default to SHA-256 hash type */
- p7->type = SIGNED_DATA; /* PKCS7_final switches on type */
- }
- /* add additional chain certs if provided */
- while (cert && (err == 0)) {
- if (cert->data.x509 != NULL && cert->data.x509->derCert != NULL) {
- if (wc_PKCS7_AddCertificate(&p7->pkcs7,
- cert->data.x509->derCert->buffer,
- cert->data.x509->derCert->length) != 0) {
- WOLFSSL_MSG("Error in wc_PKCS7_AddCertificate");
- err = 1;
- }
- }
- cert = cert->next;
- }
- if ((err == 0) && (flags & PKCS7_DETACHED)) {
- if (wc_PKCS7_SetDetached(&p7->pkcs7, 1) != 0) {
- WOLFSSL_MSG("Failed to set signature detached");
- err = 1;
- }
- }
- if ((err == 0) && (flags & PKCS7_STREAM)) {
- /* if streaming, return before finalizing */
- return (PKCS7*)p7;
- }
- if ((err == 0) && (wolfSSL_PKCS7_final((PKCS7*)p7, in, flags) != 1)) {
- WOLFSSL_MSG("Error calling wolfSSL_PKCS7_final");
- err = 1;
- }
- if ((err != 0) && (p7 != NULL)) {
- wolfSSL_PKCS7_free((PKCS7*)p7);
- p7 = NULL;
- }
- return (PKCS7*)p7;
- }
- #ifdef HAVE_SMIME
- #ifndef MAX_MIME_LINE_LEN
- #define MAX_MIME_LINE_LEN 1024
- #endif
- /**
- * Copy input BIO to output BIO, but convert all line endings to CRLF (\r\n),
- * used by PKCS7_final().
- *
- * in - input WOLFSSL_BIO to be converted
- * out - output WOLFSSL_BIO to hold copy of in, with line endings adjusted
- *
- * Return 0 on success, negative on error
- */
- static int wolfSSL_BIO_to_MIME_crlf(WOLFSSL_BIO* in, WOLFSSL_BIO* out)
- {
- int ret = 0;
- int lineLen = 0;
- word32 canonLineLen = 0;
- char* canonLine = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- char* line = NULL;
- #else
- char line[MAX_MIME_LINE_LEN];
- #endif
- if (in == NULL || out == NULL) {
- return BAD_FUNC_ARG;
- }
- #ifdef WOLFSSL_SMALL_STACK
- line = (char*)XMALLOC(MAX_MIME_LINE_LEN, in->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (line == NULL) {
- return MEMORY_E;
- }
- #endif
- XMEMSET(line, 0, MAX_MIME_LINE_LEN);
- while ((lineLen = wolfSSL_BIO_gets(in, line, MAX_MIME_LINE_LEN)) > 0) {
- if (line[lineLen - 1] == '\r' || line[lineLen - 1] == '\n') {
- canonLineLen = (word32)lineLen;
- if ((canonLine = wc_MIME_single_canonicalize(
- line, &canonLineLen)) == NULL) {
- ret = -1;
- break;
- }
- /* remove trailing null */
- if (canonLineLen >= 1 && canonLine[canonLineLen-1] == '\0') {
- canonLineLen--;
- }
- if (wolfSSL_BIO_write(out, canonLine, (int)canonLineLen) < 0) {
- ret = -1;
- break;
- }
- XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7);
- canonLine = NULL;
- }
- else {
- /* no line ending in current line, write direct to out */
- if (wolfSSL_BIO_write(out, line, lineLen) < 0) {
- ret = -1;
- break;
- }
- }
- }
- if (canonLine != NULL) {
- XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7);
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(line, in->heap, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return ret;
- }
- #endif /* HAVE_SMIME */
- /* Used by both PKCS7_final() and PKCS7_verify() */
- static const char contTypeText[] = "Content-Type: text/plain\r\n\r\n";
- /**
- * Finalize PKCS7 structure, currently supports signedData only.
- *
- * Does not generate final bundle (ie: signedData), but finalizes
- * the PKCS7 structure in preparation for a output function to be called next.
- *
- * pkcs7 - initialized PKCS7 structure, populated with signer, etc
- * in - input data
- * flags - flags to control PKCS7 behavior. Other flags except those noted
- * below are ignored:
- *
- * PKCS7_BINARY - Do not translate input data to MIME canonical
- * format (\r\n line endings), thus preventing corruption of
- * binary content.
- * PKCS7_TEXT - Prepend MIME headers for text/plain to content.
- *
- * Returns 1 on success, 0 on error
- */
- int wolfSSL_PKCS7_final(PKCS7* pkcs7, WOLFSSL_BIO* in, int flags)
- {
- int ret = 1;
- int memSz = 0;
- unsigned char* mem = NULL;
- WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
- WOLFSSL_BIO* data = NULL;
- WOLFSSL_ENTER("wolfSSL_PKCS7_final");
- if (p7 == NULL || in == NULL) {
- WOLFSSL_MSG("Bad input args to PKCS7_final");
- ret = 0;
- }
- if (ret == 1) {
- if ((data = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())) == NULL) {
- WOLFSSL_MSG("Error in wolfSSL_BIO_new");
- ret = 0;
- }
- }
- /* prepend Content-Type header if PKCS7_TEXT */
- if ((ret == 1) && (flags & PKCS7_TEXT)) {
- if (wolfSSL_BIO_write(data, contTypeText,
- (int)XSTR_SIZEOF(contTypeText)) < 0) {
- WOLFSSL_MSG("Error prepending Content-Type header");
- ret = 0;
- }
- }
- /* convert line endings to CRLF if !PKCS7_BINARY */
- if (ret == 1) {
- if (flags & PKCS7_BINARY) {
- /* no CRLF conversion, direct copy content */
- if ((memSz = wolfSSL_BIO_get_len(in)) <= 0) {
- ret = 0;
- }
- if (ret == 1) {
- mem = (unsigned char*)XMALLOC(memSz, in->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- WOLFSSL_MSG("Failed to allocate memory for input data");
- ret = 0;
- }
- }
- if (ret == 1) {
- if (wolfSSL_BIO_read(in, mem, memSz) != memSz) {
- WOLFSSL_MSG("Error reading from input BIO");
- ret = 0;
- }
- else if (wolfSSL_BIO_write(data, mem, memSz) < 0) {
- ret = 0;
- }
- }
- if (mem != NULL) {
- XFREE(mem, in->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- }
- else {
- #ifdef HAVE_SMIME
- /* convert content line endings to CRLF */
- if (wolfSSL_BIO_to_MIME_crlf(in, data) != 0) {
- WOLFSSL_MSG("Error converting line endings to CRLF");
- ret = 0;
- }
- else {
- p7->pkcs7.contentCRLF = 1;
- }
- #else
- WOLFSSL_MSG("Without PKCS7_BINARY requires wolfSSL to be built "
- "with HAVE_SMIME");
- ret = 0;
- #endif
- }
- }
- if ((ret == 1) && ((memSz = wolfSSL_BIO_get_mem_data(data, &mem)) < 0)) {
- WOLFSSL_MSG("Error in wolfSSL_BIO_get_mem_data");
- ret = 0;
- }
- if (ret == 1) {
- if (p7->data != NULL) {
- XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7);
- }
- p7->data = (byte*)XMALLOC(memSz, NULL, DYNAMIC_TYPE_PKCS7);
- if (p7->data == NULL) {
- ret = 0;
- }
- else {
- XMEMCPY(p7->data, mem, memSz);
- p7->len = memSz;
- }
- }
- if (ret == 1) {
- p7->pkcs7.content = p7->data;
- p7->pkcs7.contentSz = (word32)p7->len;
- }
- if (data != NULL) {
- wolfSSL_BIO_free(data);
- }
- return ret;
- }
- int wolfSSL_PKCS7_verify(PKCS7* pkcs7, WOLFSSL_STACK* certs,
- WOLFSSL_X509_STORE* store, WOLFSSL_BIO* in, WOLFSSL_BIO* out, int flags)
- {
- int i, ret = 0;
- unsigned char* mem = NULL;
- int memSz = 0;
- WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
- int contTypeLen;
- WOLFSSL_X509* signer = NULL;
- WOLFSSL_STACK* signers = NULL;
- WOLFSSL_ENTER("wolfSSL_PKCS7_verify");
- if (pkcs7 == NULL)
- return WOLFSSL_FAILURE;
- if (in != NULL) {
- if ((memSz = wolfSSL_BIO_get_mem_data(in, &mem)) < 0)
- return WOLFSSL_FAILURE;
- p7->pkcs7.content = mem;
- p7->pkcs7.contentSz = (word32)memSz;
- }
- /* certs is the list of certificates to find the cert with issuer/serial. */
- (void)certs;
- /* store is the certificate store to use to verify signer certificate
- * associated with the signers.
- */
- (void)store;
- ret = wc_PKCS7_VerifySignedData(&p7->pkcs7, p7->data, p7->len);
- if (ret != 0)
- return WOLFSSL_FAILURE;
- if ((flags & PKCS7_NOVERIFY) != PKCS7_NOVERIFY) {
- /* Verify signer certificates */
- if (store == NULL || store->cm == NULL) {
- WOLFSSL_MSG("No store or store certs, but PKCS7_NOVERIFY not set");
- return WOLFSSL_FAILURE;
- }
- signers = wolfSSL_PKCS7_get0_signers(pkcs7, certs, flags);
- if (signers == NULL) {
- WOLFSSL_MSG("No signers found to verify");
- return WOLFSSL_FAILURE;
- }
- for (i = 0; i < wolfSSL_sk_X509_num(signers); i++) {
- signer = wolfSSL_sk_X509_value(signers, i);
- if (wolfSSL_CertManagerVerifyBuffer(store->cm,
- signer->derCert->buffer,
- signer->derCert->length,
- WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Failed to verify signer certificate");
- wolfSSL_sk_X509_pop_free(signers, NULL);
- return WOLFSSL_FAILURE;
- }
- }
- wolfSSL_sk_X509_pop_free(signers, NULL);
- }
- if (flags & PKCS7_TEXT) {
- /* strip MIME header for text/plain, otherwise error */
- contTypeLen = XSTR_SIZEOF(contTypeText);
- if ((p7->pkcs7.contentSz < (word32)contTypeLen) ||
- (XMEMCMP(p7->pkcs7.content, contTypeText, contTypeLen) != 0)) {
- WOLFSSL_MSG("Error PKCS7 Content-Type not found with PKCS7_TEXT");
- return WOLFSSL_FAILURE;
- }
- p7->pkcs7.content += contTypeLen;
- p7->pkcs7.contentSz -= contTypeLen;
- }
- if (out != NULL) {
- wolfSSL_BIO_write(out, p7->pkcs7.content, p7->pkcs7.contentSz);
- }
- WOLFSSL_LEAVE("wolfSSL_PKCS7_verify", WOLFSSL_SUCCESS);
- return WOLFSSL_SUCCESS;
- }
- /**
- * This API was added as a helper function for libest. It
- * encodes a stack of certificates to pkcs7 format.
- * @param pkcs7 PKCS7 parameter object
- * @param certs WOLFSSL_STACK_OF(WOLFSSL_X509)*
- * @param out Output bio
- * @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
- */
- int wolfSSL_PKCS7_encode_certs(PKCS7* pkcs7, WOLFSSL_STACK* certs,
- WOLFSSL_BIO* out)
- {
- int ret;
- WOLFSSL_PKCS7* p7;
- WOLFSSL_ENTER("wolfSSL_PKCS7_encode_certs");
- if (!pkcs7 || !certs || !out) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- p7 = (WOLFSSL_PKCS7*)pkcs7;
- /* take ownership of certs */
- p7->certs = certs;
- /* TODO: takes ownership even on failure below but not on above failure. */
- if (pkcs7->certList) {
- WOLFSSL_MSG("wolfSSL_PKCS7_encode_certs called multiple times on same "
- "struct");
- return WOLFSSL_FAILURE;
- }
- if (certs) {
- /* Save some of the values */
- int hashOID = pkcs7->hashOID;
- byte version = pkcs7->version;
- if (!certs->data.x509 || !certs->data.x509->derCert) {
- WOLFSSL_MSG("Missing cert");
- return WOLFSSL_FAILURE;
- }
- if (wc_PKCS7_InitWithCert(pkcs7, certs->data.x509->derCert->buffer,
- certs->data.x509->derCert->length) != 0) {
- WOLFSSL_MSG("wc_PKCS7_InitWithCert error");
- return WOLFSSL_FAILURE;
- }
- certs = certs->next;
- pkcs7->hashOID = hashOID;
- pkcs7->version = version;
- }
- /* Add the certs to the PKCS7 struct */
- while (certs) {
- if (!certs->data.x509 || !certs->data.x509->derCert) {
- WOLFSSL_MSG("Missing cert");
- return WOLFSSL_FAILURE;
- }
- if (wc_PKCS7_AddCertificate(pkcs7, certs->data.x509->derCert->buffer,
- certs->data.x509->derCert->length) != 0) {
- WOLFSSL_MSG("wc_PKCS7_AddCertificate error");
- return WOLFSSL_FAILURE;
- }
- certs = certs->next;
- }
- if (wc_PKCS7_SetSignerIdentifierType(pkcs7, DEGENERATE_SID) != 0) {
- WOLFSSL_MSG("wc_PKCS7_SetSignerIdentifierType error");
- return WOLFSSL_FAILURE;
- }
- ret = wolfSSL_i2d_PKCS7_bio(out, pkcs7);
- return ret;
- }
- /******************************************************************************
- * wolfSSL_PEM_write_bio_PKCS7 - writes the PKCS7 data to BIO
- *
- * RETURNS:
- * returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE
- */
- int wolfSSL_PEM_write_bio_PKCS7(WOLFSSL_BIO* bio, PKCS7* p7)
- {
- #ifdef WOLFSSL_SMALL_STACK
- byte* outputHead;
- byte* outputFoot;
- #else
- byte outputHead[2048];
- byte outputFoot[2048];
- #endif
- word32 outputHeadSz = 2048;
- word32 outputFootSz = 2048;
- word32 outputSz = 0;
- byte* output = NULL;
- byte* pem = NULL;
- int pemSz = -1;
- enum wc_HashType hashType;
- byte hashBuf[WC_MAX_DIGEST_SIZE];
- word32 hashSz = -1;
- WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PKCS7");
- if (bio == NULL || p7 == NULL)
- return WOLFSSL_FAILURE;
- #ifdef WOLFSSL_SMALL_STACK
- outputHead = (byte*)XMALLOC(outputHeadSz, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (outputHead == NULL)
- return MEMORY_E;
- outputFoot = (byte*)XMALLOC(outputFootSz, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (outputFoot == NULL)
- goto error;
- #endif
- XMEMSET(hashBuf, 0, WC_MAX_DIGEST_SIZE);
- XMEMSET(outputHead, 0, outputHeadSz);
- XMEMSET(outputFoot, 0, outputFootSz);
- hashType = wc_OidGetHash(p7->hashOID);
- hashSz = (word32)wc_HashGetDigestSize(hashType);
- if (hashSz > WC_MAX_DIGEST_SIZE)
- goto error;
- /* only SIGNED_DATA is supported */
- switch (p7->contentOID) {
- case SIGNED_DATA:
- break;
- default:
- WOLFSSL_MSG("Unknown PKCS#7 Type");
- goto error;
- };
- if ((wc_PKCS7_EncodeSignedData_ex(p7, hashBuf, hashSz,
- outputHead, &outputHeadSz, outputFoot, &outputFootSz)) != 0)
- goto error;
- outputSz = outputHeadSz + p7->contentSz + outputFootSz;
- output = (byte*)XMALLOC(outputSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (!output)
- goto error;
- XMEMSET(output, 0, outputSz);
- outputSz = 0;
- XMEMCPY(&output[outputSz], outputHead, outputHeadSz);
- outputSz += outputHeadSz;
- XMEMCPY(&output[outputSz], p7->content, p7->contentSz);
- outputSz += p7->contentSz;
- XMEMCPY(&output[outputSz], outputFoot, outputFootSz);
- outputSz += outputFootSz;
- /* get PEM size */
- pemSz = wc_DerToPemEx(output, outputSz, NULL, 0, NULL, CERT_TYPE);
- if (pemSz < 0)
- goto error;
- pemSz++; /* for '\0'*/
- /* create PEM buffer and convert from DER to PEM*/
- if ((pem = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER))
- == NULL)
- goto error;
- XMEMSET(pem, 0, pemSz);
- if (wc_DerToPemEx(output, outputSz, pem, (word32)pemSz, NULL, CERT_TYPE) < 0) {
- goto error;
- }
- if ((wolfSSL_BIO_write(bio, pem, pemSz) == pemSz)) {
- XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return WOLFSSL_SUCCESS;
- }
- error:
- #ifdef WOLFSSL_SMALL_STACK
- if (outputHead) {
- XFREE(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- if (outputFoot) {
- XFREE(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- if (output) {
- XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- if (pem) {
- XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- return WOLFSSL_FAILURE;
- }
- #ifdef HAVE_SMIME
- /*****************************************************************************
- * wolfSSL_SMIME_read_PKCS7 - Reads the given S/MIME message and parses it into
- * a PKCS7 object. In case of a multipart message, stores the signed data in
- * bcont.
- *
- * RETURNS:
- * returns pointer to a PKCS7 structure on success, otherwise returns NULL
- */
- PKCS7* wolfSSL_SMIME_read_PKCS7(WOLFSSL_BIO* in,
- WOLFSSL_BIO** bcont)
- {
- MimeHdr* allHdrs = NULL;
- MimeHdr* curHdr = NULL;
- MimeParam* curParam = NULL;
- int inLen = 0;
- byte* bcontMem = NULL;
- int bcontMemSz = 0;
- int sectionLen = 0;
- int ret = -1;
- char* section = NULL;
- char* canonLine = NULL;
- char* canonSection = NULL;
- PKCS7* pkcs7 = NULL;
- word32 outLen = 0;
- word32 canonLineLen = 0;
- byte* out = NULL;
- byte* outHead = NULL;
- int canonPos = 0;
- int lineLen = 0;
- int remainLen = 0;
- byte isEnd = 0;
- size_t canonSize = 0;
- size_t boundLen = 0;
- char* boundary = NULL;
- static const char kContType[] = "Content-Type";
- static const char kCTE[] = "Content-Transfer-Encoding";
- static const char kMultSigned[] = "multipart/signed";
- static const char kAppPkcsSign[] = "application/pkcs7-signature";
- static const char kAppXPkcsSign[] = "application/x-pkcs7-signature";
- static const char kAppPkcs7Mime[] = "application/pkcs7-mime";
- static const char kAppXPkcs7Mime[] = "application/x-pkcs7-mime";
- WOLFSSL_ENTER("wolfSSL_SMIME_read_PKCS7");
- if (in == NULL || bcont == NULL) {
- goto error;
- }
- inLen = wolfSSL_BIO_get_len(in);
- if (inLen <= 0) {
- goto error;
- }
- remainLen = wolfSSL_BIO_get_len(in);
- if (remainLen <= 0) {
- goto error;
- }
- section = (char*)XMALLOC(remainLen+1, NULL, DYNAMIC_TYPE_PKCS7);
- if (section == NULL) {
- goto error;
- }
- lineLen = wolfSSL_BIO_gets(in, section, remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- while (isEnd == 0 && remainLen > 0) {
- sectionLen += lineLen;
- remainLen -= lineLen;
- lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- /* Line with just newline signals end of headers. */
- if ((lineLen==2 && !XSTRNCMP(§ion[sectionLen],
- "\r\n", 2)) ||
- (lineLen==1 && (section[sectionLen] == '\r' ||
- section[sectionLen] == '\n'))) {
- isEnd = 1;
- }
- }
- section[sectionLen] = '\0';
- ret = wc_MIME_parse_headers(section, sectionLen, &allHdrs);
- if (ret < 0) {
- WOLFSSL_MSG("Parsing MIME headers failed.");
- goto error;
- }
- isEnd = 0;
- section[0] = '\0';
- sectionLen = 0;
- curHdr = wc_MIME_find_header_name(kContType, allHdrs);
- if (curHdr && !XSTRNCMP(curHdr->body, kMultSigned,
- XSTR_SIZEOF(kMultSigned))) {
- curParam = wc_MIME_find_param_attr("protocol", curHdr->params);
- if (curParam && (!XSTRNCMP(curParam->value, kAppPkcsSign,
- XSTR_SIZEOF(kAppPkcsSign)) ||
- !XSTRNCMP(curParam->value, kAppXPkcsSign,
- XSTR_SIZEOF(kAppXPkcsSign)))) {
- curParam = wc_MIME_find_param_attr("boundary", curHdr->params);
- if (curParam == NULL) {
- goto error;
- }
- boundLen = XSTRLEN(curParam->value) + 2;
- boundary = (char*)XMALLOC(boundLen+1, NULL, DYNAMIC_TYPE_PKCS7);
- if (boundary == NULL) {
- goto error;
- }
- XMEMSET(boundary, 0, (word32)(boundLen+1));
- boundary[0] = boundary[1] = '-';
- XSTRNCPY(&boundary[2], curParam->value, boundLen-2);
- /* Parse up to first boundary, ignore everything here. */
- lineLen = wolfSSL_BIO_gets(in, section, remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- while (XSTRNCMP(§ion[sectionLen], boundary, boundLen) &&
- remainLen > 0) {
- sectionLen += lineLen;
- remainLen -= lineLen;
- lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen],
- remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- }
- section[0] = '\0';
- sectionLen = 0;
- canonSize = (size_t)remainLen + 1;
- canonSection = (char*)XMALLOC(canonSize, NULL,
- DYNAMIC_TYPE_PKCS7);
- if (canonSection == NULL) {
- goto error;
- }
- lineLen = wolfSSL_BIO_gets(in, section, remainLen);
- if (lineLen < 0) {
- goto error;
- }
- while (XSTRNCMP(§ion[sectionLen], boundary, boundLen) &&
- remainLen > 0) {
- canonLineLen = (word32)lineLen;
- canonLine = wc_MIME_single_canonicalize(§ion[sectionLen],
- &canonLineLen);
- if (canonLine == NULL) {
- goto error;
- }
- /* If line endings were added, the initial length may be
- * exceeded. */
- if ((canonPos + canonLineLen) >= canonSize) {
- canonSize = canonPos + canonLineLen;
- canonSection = (char*)XREALLOC(canonSection, canonSize,
- NULL, DYNAMIC_TYPE_PKCS7);
- if (canonSection == NULL) {
- goto error;
- }
- }
- XMEMCPY(&canonSection[canonPos], canonLine,
- (int)canonLineLen - 1);
- canonPos += canonLineLen - 1;
- XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7);
- canonLine = NULL;
- sectionLen += lineLen;
- remainLen -= lineLen;
- lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen],
- remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- }
- if (canonPos > 0) {
- canonPos--;
- }
- /* Strip the final trailing newline. Support \r, \n or \r\n. */
- if (canonSection[canonPos] == '\n') {
- if (canonPos > 0) {
- canonPos--;
- }
- }
- if (canonSection[canonPos] == '\r') {
- if (canonPos > 0) {
- canonPos--;
- }
- }
- canonSection[canonPos+1] = '\0';
- *bcont = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
- ret = wolfSSL_BIO_write(*bcont, canonSection,
- canonPos + 1);
- if (ret != (canonPos+1)) {
- goto error;
- }
- if ((bcontMemSz = wolfSSL_BIO_get_mem_data(*bcont, &bcontMem))
- < 0) {
- goto error;
- }
- XFREE(canonSection, NULL, DYNAMIC_TYPE_PKCS7);
- canonSection = NULL;
- wc_MIME_free_hdrs(allHdrs);
- allHdrs = NULL;
- section[0] = '\0';
- sectionLen = 0;
- lineLen = wolfSSL_BIO_gets(in, section, remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- while (isEnd == 0 && remainLen > 0) {
- sectionLen += lineLen;
- remainLen -= lineLen;
- lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen],
- remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- /* Line with just newline signals end of headers. */
- if ((lineLen==2 && !XSTRNCMP(§ion[sectionLen],
- "\r\n", 2)) ||
- (lineLen==1 && (section[sectionLen] == '\r' ||
- section[sectionLen] == '\n'))) {
- isEnd = 1;
- }
- }
- section[sectionLen] = '\0';
- ret = wc_MIME_parse_headers(section, sectionLen, &allHdrs);
- if (ret < 0) {
- WOLFSSL_MSG("Parsing MIME headers failed.");
- goto error;
- }
- curHdr = wc_MIME_find_header_name(kContType, allHdrs);
- if (curHdr == NULL || (XSTRNCMP(curHdr->body, kAppPkcsSign,
- XSTR_SIZEOF(kAppPkcsSign)) &&
- XSTRNCMP(curHdr->body, kAppXPkcsSign,
- XSTR_SIZEOF(kAppXPkcsSign)))) {
- WOLFSSL_MSG("S/MIME headers not found inside "
- "multipart message.\n");
- goto error;
- }
- section[0] = '\0';
- sectionLen = 0;
- lineLen = wolfSSL_BIO_gets(in, section, remainLen);
- while (XSTRNCMP(§ion[sectionLen], boundary, boundLen) &&
- remainLen > 0) {
- sectionLen += lineLen;
- remainLen -= lineLen;
- lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen],
- remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- }
- XFREE(boundary, NULL, DYNAMIC_TYPE_PKCS7);
- boundary = NULL;
- }
- }
- else if (curHdr && (!XSTRNCMP(curHdr->body, kAppPkcs7Mime,
- XSTR_SIZEOF(kAppPkcs7Mime)) ||
- !XSTRNCMP(curHdr->body, kAppXPkcs7Mime,
- XSTR_SIZEOF(kAppXPkcs7Mime)))) {
- sectionLen = wolfSSL_BIO_get_len(in);
- if (sectionLen <= 0) {
- goto error;
- }
- ret = wolfSSL_BIO_read(in, section, sectionLen);
- if (ret < 0 || ret != sectionLen) {
- WOLFSSL_MSG("Error reading input BIO.");
- goto error;
- }
- }
- else {
- WOLFSSL_MSG("S/MIME headers not found.");
- goto error;
- }
- curHdr = wc_MIME_find_header_name(kCTE, allHdrs);
- if (curHdr == NULL) {
- WOLFSSL_MSG("Content-Transfer-Encoding header not found, "
- "assuming base64 encoding.");
- }
- else if (XSTRNCMP(curHdr->body, "base64", XSTRLEN("base64"))) {
- WOLFSSL_MSG("S/MIME encodings other than base64 are not "
- "currently supported.\n");
- goto error;
- }
- if (section == NULL || sectionLen <= 0) {
- goto error;
- }
- outLen = (word32)((sectionLen*3+3)/4)+1;
- out = (byte*)XMALLOC(outLen*sizeof(byte), NULL, DYNAMIC_TYPE_PKCS7);
- outHead = out;
- if (outHead == NULL) {
- goto error;
- }
- /* Strip trailing newlines. */
- while ((sectionLen > 0) &&
- (section[sectionLen-1] == '\r' || section[sectionLen-1] == '\n')) {
- sectionLen--;
- }
- section[sectionLen] = '\0';
- ret = Base64_Decode((const byte*)section, (word32)sectionLen, out, &outLen);
- if (ret < 0) {
- WOLFSSL_MSG("Error base64 decoding S/MIME message.");
- goto error;
- }
- pkcs7 = wolfSSL_d2i_PKCS7_only(NULL, (const unsigned char**)&out, (int)outLen,
- bcontMem, (word32)bcontMemSz);
- wc_MIME_free_hdrs(allHdrs);
- XFREE(outHead, NULL, DYNAMIC_TYPE_PKCS7);
- XFREE(section, NULL, DYNAMIC_TYPE_PKCS7);
- return pkcs7;
- error:
- wc_MIME_free_hdrs(allHdrs);
- XFREE(boundary, NULL, DYNAMIC_TYPE_PKCS7);
- XFREE(outHead, NULL, DYNAMIC_TYPE_PKCS7);
- XFREE(section, NULL, DYNAMIC_TYPE_PKCS7);
- if (canonSection != NULL)
- XFREE(canonSection, NULL, DYNAMIC_TYPE_PKCS7);
- if (canonLine != NULL)
- XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7);
- if (bcont) {
- wolfSSL_BIO_free(*bcont);
- *bcont = NULL; /* reset 'bcount' pointer to NULL on failure */
- }
- return NULL;
- }
- /* Convert hash algo OID (from Hash_Sum in asn.h) to SMIME string equivalent.
- * Returns hash algorithm string or "unknown" if not found */
- static const char* wolfSSL_SMIME_HashOIDToString(int hashOID)
- {
- switch (hashOID) {
- case MD5h:
- return "md5";
- case SHAh:
- return "sha1";
- case SHA224h:
- return "sha-224";
- case SHA256h:
- return "sha-256";
- case SHA384h:
- return "sha-384";
- case SHA512h:
- return "sha-512";
- case SHA3_224h:
- return "sha3-224";
- case SHA3_384h:
- return "sha3-384";
- case SHA3_512h:
- return "sha3-512";
- default:
- break;
- }
- return "unknown";
- }
- /* Convert PKCS#7 type (from PKCS7_TYPES in pkcs7.h) to SMIME string.
- * RFC2633 only defines signed-data, enveloped-data, certs-only.
- * Returns string on success, NULL on unknown type. */
- static const char* wolfSSL_SMIME_PKCS7TypeToString(int type)
- {
- switch (type) {
- case SIGNED_DATA:
- return "signed-data";
- case ENVELOPED_DATA:
- return "enveloped-data";
- default:
- break;
- }
- return NULL;
- }
- /**
- * Convert PKCS7 structure to SMIME format, adding necessary headers.
- *
- * Handles generation of PKCS7 bundle (ie: signedData). PKCS7 structure
- * should be set up beforehand with PKCS7_sign/final/etc. Output is always
- * Base64 encoded.
- *
- * out - output BIO for SMIME formatted data to be placed
- * pkcs7 - input PKCS7 structure, initialized and set up
- * in - input content to be encoded into PKCS7
- * flags - flags to control behavior of PKCS7 generation
- *
- * Returns 1 on success, 0 or negative on failure
- */
- int wolfSSL_SMIME_write_PKCS7(WOLFSSL_BIO* out, PKCS7* pkcs7, WOLFSSL_BIO* in,
- int flags)
- {
- int i;
- int ret = 1;
- WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
- byte* p7out = NULL;
- int len = 0;
- char boundary[33]; /* 32 chars + \0 */
- byte* sigBase64 = NULL;
- word32 sigBase64Len = 0;
- const char* p7TypeString = NULL;
- static const char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- if (out == NULL || p7 == NULL) {
- WOLFSSL_MSG("Bad function arguments");
- return 0;
- }
- if (in != NULL && (p7->pkcs7.content == NULL || p7->pkcs7.contentSz == 0 ||
- p7->pkcs7.contentCRLF == 0)) {
- /* store and adjust content line endings for CRLF if needed */
- if (wolfSSL_PKCS7_final((PKCS7*)p7, in, flags) != 1) {
- ret = 0;
- }
- }
- if (ret > 0) {
- /* Generate signedData bundle, DER in output (dynamic) */
- if ((len = wolfSSL_i2d_PKCS7((PKCS7*)p7, &p7out)) == WOLFSSL_FAILURE) {
- WOLFSSL_MSG("Error in wolfSSL_i2d_PKCS7");
- ret = 0;
- }
- }
- /* Base64 encode signedData bundle */
- if (ret > 0) {
- if (Base64_Encode(p7out, (word32)len, NULL, &sigBase64Len) != LENGTH_ONLY_E) {
- ret = 0;
- }
- else {
- sigBase64 = (byte*)XMALLOC(sigBase64Len, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (sigBase64 == NULL) {
- ret = 0;
- }
- }
- }
- if (ret > 0) {
- XMEMSET(sigBase64, 0, sigBase64Len);
- if (Base64_Encode(p7out, (word32)len, sigBase64, &sigBase64Len) < 0) {
- WOLFSSL_MSG("Error in Base64_Encode of signature");
- ret = 0;
- }
- }
- /* build up SMIME message */
- if (ret > 0) {
- if (flags & PKCS7_DETACHED) {
- /* generate random boundary */
- if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("No RNG to use");
- ret = 0;
- }
- /* no need to generate random byte for null terminator (size-1) */
- if ((ret > 0) && (wc_RNG_GenerateBlock(&globalRNG, (byte*)boundary,
- sizeof(boundary) - 1 ) != 0)) {
- WOLFSSL_MSG("Error in wc_RNG_GenerateBlock");
- ret = 0;
- }
- if (ret > 0) {
- for (i = 0; i < (int)sizeof(boundary) - 1; i++) {
- boundary[i] =
- alphanum[boundary[i] % XSTR_SIZEOF(alphanum)];
- }
- boundary[sizeof(boundary)-1] = 0;
- }
- if (ret > 0) {
- /* S/MIME header beginning */
- ret = wolfSSL_BIO_printf(out,
- "MIME-Version: 1.0\n"
- "Content-Type: multipart/signed; "
- "protocol=\"application/x-pkcs7-signature\"; "
- "micalg=\"%s\"; "
- "boundary=\"----%s\"\n\n"
- "This is an S/MIME signed message\n\n"
- "------%s\n",
- wolfSSL_SMIME_HashOIDToString(p7->pkcs7.hashOID),
- boundary, boundary);
- }
- if (ret > 0) {
- /* S/MIME content */
- ret = wolfSSL_BIO_write(out,
- p7->pkcs7.content, p7->pkcs7.contentSz);
- }
- if (ret > 0) {
- /* S/SMIME header end boundary */
- ret = wolfSSL_BIO_printf(out,
- "\n------%s\n", boundary);
- }
- if (ret > 0) {
- /* Signature and header */
- ret = wolfSSL_BIO_printf(out,
- "Content-Type: application/x-pkcs7-signature; "
- "name=\"smime.p7s\"\n"
- "Content-Transfer-Encoding: base64\n"
- "Content-Disposition: attachment; "
- "filename=\"smime.p7s\"\n\n"
- "%.*s\n" /* Base64 encoded signature */
- "------%s--\n\n",
- sigBase64Len, sigBase64,
- boundary);
- }
- }
- else {
- p7TypeString = wolfSSL_SMIME_PKCS7TypeToString(p7->type);
- if (p7TypeString == NULL) {
- WOLFSSL_MSG("Unsupported PKCS7 SMIME type");
- ret = 0;
- }
- if (ret > 0) {
- /* not detached */
- ret = wolfSSL_BIO_printf(out,
- "MIME-Version: 1.0\n"
- "Content-Disposition: attachment; "
- "filename=\"smime.p7m\"\n"
- "Content-Type: application/x-pkcs7-mime; "
- "smime-type=%s; name=\"smime.p7m\"\n"
- "Content-Transfer-Encoding: base64\n\n"
- "%.*s\n" /* signature */,
- p7TypeString, sigBase64Len, sigBase64);
- }
- }
- }
- if (p7out != NULL) {
- XFREE(p7out, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- if (sigBase64 != NULL) {
- XFREE(sigBase64, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- if (ret > 0) {
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- #endif /* HAVE_SMIME */
- #endif /* !NO_BIO */
- #endif /* OPENSSL_ALL */
- #endif /* HAVE_PKCS7 */
- /*******************************************************************************
- * END OF PKCS7 APIs
- ******************************************************************************/
- /*******************************************************************************
- * START OF PKCS12 APIs
- ******************************************************************************/
- #ifdef OPENSSL_EXTRA
- /* no-op function. Was initially used for adding encryption algorithms available
- * for PKCS12 */
- void wolfSSL_PKCS12_PBE_add(void)
- {
- WOLFSSL_ENTER("wolfSSL_PKCS12_PBE_add");
- }
- #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
- WOLFSSL_X509_PKCS12 *wolfSSL_d2i_PKCS12_fp(XFILE fp,
- WOLFSSL_X509_PKCS12 **pkcs12)
- {
- WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_fp");
- return (WOLFSSL_X509_PKCS12 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)pkcs12,
- PKCS12_TYPE);
- }
- #endif /* !NO_FILESYSTEM */
- #endif /* OPENSSL_EXTRA */
- #if defined(HAVE_PKCS12)
- #ifdef OPENSSL_EXTRA
- #if !defined(NO_ASN) && !defined(NO_PWDBASED)
- #ifndef NO_BIO
- WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12)
- {
- WC_PKCS12* localPkcs12 = NULL;
- unsigned char* mem = NULL;
- long memSz;
- int ret = -1;
- WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio");
- if (bio == NULL) {
- WOLFSSL_MSG("Bad Function Argument bio is NULL");
- return NULL;
- }
- memSz = wolfSSL_BIO_get_len(bio);
- if (memSz <= 0) {
- return NULL;
- }
- mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- return NULL;
- }
- if (mem != NULL) {
- localPkcs12 = wc_PKCS12_new_ex(bio->heap);
- if (localPkcs12 == NULL) {
- WOLFSSL_MSG("Memory error");
- }
- }
- if (mem != NULL && localPkcs12 != NULL) {
- if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) {
- ret = wc_d2i_PKCS12(mem, (word32)memSz, localPkcs12);
- if (ret < 0) {
- WOLFSSL_MSG("Failed to get PKCS12 sequence");
- }
- }
- else {
- WOLFSSL_MSG("Failed to get data from bio struct");
- }
- }
- /* cleanup */
- if (mem != NULL)
- XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (ret < 0 && localPkcs12 != NULL) {
- wc_PKCS12_free(localPkcs12);
- localPkcs12 = NULL;
- }
- if (pkcs12 != NULL)
- *pkcs12 = localPkcs12;
- return localPkcs12;
- }
- /* Converts the PKCS12 to DER format and outputs it into bio.
- *
- * bio is the structure to hold output DER
- * pkcs12 structure to create DER from
- *
- * return 1 for success or 0 if an error occurs
- */
- int wolfSSL_i2d_PKCS12_bio(WOLFSSL_BIO *bio, WC_PKCS12 *pkcs12)
- {
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_i2d_PKCS12_bio");
- if ((bio != NULL) && (pkcs12 != NULL)) {
- word32 certSz = 0;
- byte *certDer = NULL;
- certSz = (word32)wc_i2d_PKCS12(pkcs12, &certDer, NULL);
- if ((certSz > 0) && (certDer != NULL)) {
- if (wolfSSL_BIO_write(bio, certDer, (int)certSz) == (int)certSz) {
- ret = WOLFSSL_SUCCESS;
- }
- }
- if (certDer != NULL) {
- XFREE(certDer, NULL, DYNAMIC_TYPE_PKCS);
- }
- }
- return ret;
- }
- #endif /* !NO_BIO */
- /* Creates a new WC_PKCS12 structure
- *
- * pass password to use
- * name friendlyName to use
- * pkey private key to go into PKCS12 bundle
- * cert certificate to go into PKCS12 bundle
- * ca extra certificates that can be added to bundle. Can be NULL
- * keyNID type of encryption to use on the key (-1 means no encryption)
- * certNID type of encryption to use on the certificate
- * itt number of iterations with encryption
- * macItt number of iterations with mac creation
- * keyType flag for signature and/or encryption key
- *
- * returns a pointer to a new WC_PKCS12 structure on success and NULL on fail
- */
- WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name, WOLFSSL_EVP_PKEY* pkey,
- WOLFSSL_X509* cert, WOLF_STACK_OF(WOLFSSL_X509)* ca, int keyNID,
- int certNID, int itt, int macItt, int keyType)
- {
- WC_PKCS12* pkcs12;
- WC_DerCertList* list = NULL;
- word32 passSz;
- byte* keyDer = NULL;
- word32 keyDerSz;
- byte* certDer;
- int certDerSz;
- WOLFSSL_ENTER("wolfSSL_PKCS12_create");
- if (pass == NULL || pkey == NULL || cert == NULL) {
- WOLFSSL_LEAVE("wolfSSL_PKCS12_create", BAD_FUNC_ARG);
- return NULL;
- }
- passSz = (word32)XSTRLEN(pass);
- keyDer = (byte*)pkey->pkey.ptr;
- keyDerSz = (word32)pkey->pkey_sz;
- certDer = (byte*)wolfSSL_X509_get_der(cert, &certDerSz);
- if (certDer == NULL) {
- return NULL;
- }
- if (ca != NULL) {
- unsigned long numCerts = ca->num;
- WOLFSSL_STACK* sk = ca;
- while (numCerts > 0 && sk != NULL) {
- byte* curDer;
- WC_DerCertList* cur;
- int curDerSz = 0;
- cur = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), NULL,
- DYNAMIC_TYPE_PKCS);
- if (cur == NULL) {
- wc_FreeCertList(list, NULL);
- return NULL;
- }
- curDer = (byte*)wolfSSL_X509_get_der(sk->data.x509, &curDerSz);
- if (curDer == NULL || curDerSz < 0) {
- XFREE(cur, NULL, DYNAMIC_TYPE_PKCS);
- wc_FreeCertList(list, NULL);
- return NULL;
- }
- cur->buffer = (byte*)XMALLOC(curDerSz, NULL, DYNAMIC_TYPE_PKCS);
- if (cur->buffer == NULL) {
- XFREE(cur, NULL, DYNAMIC_TYPE_PKCS);
- wc_FreeCertList(list, NULL);
- return NULL;
- }
- XMEMCPY(cur->buffer, curDer, curDerSz);
- cur->bufferSz = (word32)curDerSz;
- cur->next = list;
- list = cur;
- sk = sk->next;
- numCerts--;
- }
- }
- pkcs12 = wc_PKCS12_create(pass, passSz, name, keyDer, keyDerSz,
- certDer, (word32)certDerSz, list, keyNID, certNID, itt, macItt,
- keyType, NULL);
- if (ca != NULL) {
- wc_FreeCertList(list, NULL);
- }
- return pkcs12;
- }
- /* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure */
- int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
- WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert,
- WOLF_STACK_OF(WOLFSSL_X509)** ca)
- {
- void* heap = NULL;
- int ret;
- byte* certData = NULL;
- word32 certDataSz;
- byte* pk = NULL;
- word32 pkSz;
- WC_DerCertList* certList = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert *DeCert;
- #else
- DecodedCert DeCert[1];
- #endif
- WOLFSSL_ENTER("wolfSSL_PKCS12_parse");
- /* make sure we init return args */
- if (pkey) *pkey = NULL;
- if (cert) *cert = NULL;
- if (ca) *ca = NULL;
- if (pkcs12 == NULL || psw == NULL || pkey == NULL || cert == NULL) {
- WOLFSSL_MSG("Bad argument value");
- return WOLFSSL_FAILURE;
- }
- heap = wc_PKCS12_GetHeap(pkcs12);
- if (ca == NULL) {
- ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
- NULL);
- }
- else {
- ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
- &certList);
- }
- if (ret < 0) {
- WOLFSSL_LEAVE("wolfSSL_PKCS12_parse", ret);
- return WOLFSSL_FAILURE;
- }
- #ifdef WOLFSSL_SMALL_STACK
- DeCert = (DecodedCert *)XMALLOC(sizeof(*DeCert), heap,
- DYNAMIC_TYPE_DCERT);
- if (DeCert == NULL) {
- WOLFSSL_MSG("out of memory");
- return WOLFSSL_FAILURE;
- }
- #endif
- /* Decode cert and place in X509 stack struct */
- if (certList != NULL) {
- WC_DerCertList* current = certList;
- *ca = (WOLF_STACK_OF(WOLFSSL_X509)*)XMALLOC(
- sizeof(WOLF_STACK_OF(WOLFSSL_X509)), heap, DYNAMIC_TYPE_X509);
- if (*ca == NULL) {
- if (pk != NULL) {
- XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- if (certData != NULL) {
- XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
- }
- /* Free up WC_DerCertList and move on */
- while (current != NULL) {
- WC_DerCertList* next = current->next;
- XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
- XFREE(current, heap, DYNAMIC_TYPE_PKCS);
- current = next;
- }
- ret = WOLFSSL_FAILURE;
- goto out;
- }
- XMEMSET(*ca, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509)));
- /* add list of DER certs as X509's to stack */
- while (current != NULL) {
- WC_DerCertList* toFree = current;
- WOLFSSL_X509* x509;
- x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
- DYNAMIC_TYPE_X509);
- InitX509(x509, 1, heap);
- InitDecodedCert(DeCert, current->buffer, current->bufferSz, heap);
- if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
- WOLFSSL_MSG("Issue with parsing certificate");
- FreeDecodedCert(DeCert);
- wolfSSL_X509_free(x509);
- }
- else {
- if (CopyDecodedToX509(x509, DeCert) != 0) {
- WOLFSSL_MSG("Failed to copy decoded cert");
- FreeDecodedCert(DeCert);
- wolfSSL_X509_free(x509);
- wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
- if (pk != NULL) {
- XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- if (certData != NULL) {
- XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
- }
- /* Free up WC_DerCertList */
- while (current != NULL) {
- WC_DerCertList* next = current->next;
- XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
- XFREE(current, heap, DYNAMIC_TYPE_PKCS);
- current = next;
- }
- ret = WOLFSSL_FAILURE;
- goto out;
- }
- FreeDecodedCert(DeCert);
- if (wolfSSL_sk_X509_push(*ca, x509) != 1) {
- WOLFSSL_MSG("Failed to push x509 onto stack");
- wolfSSL_X509_free(x509);
- wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
- if (pk != NULL) {
- XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- if (certData != NULL) {
- XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
- }
- /* Free up WC_DerCertList */
- while (current != NULL) {
- WC_DerCertList* next = current->next;
- XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
- XFREE(current, heap, DYNAMIC_TYPE_PKCS);
- current = next;
- }
- ret = WOLFSSL_FAILURE;
- goto out;
- }
- }
- current = current->next;
- XFREE(toFree->buffer, heap, DYNAMIC_TYPE_PKCS);
- XFREE(toFree, heap, DYNAMIC_TYPE_PKCS);
- }
- }
- /* Decode cert and place in X509 struct */
- if (certData != NULL) {
- *cert = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
- DYNAMIC_TYPE_X509);
- if (*cert == NULL) {
- if (pk != NULL) {
- XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- if (ca != NULL) {
- wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
- }
- XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
- ret = WOLFSSL_FAILURE;
- goto out;
- }
- InitX509(*cert, 1, heap);
- InitDecodedCert(DeCert, certData, certDataSz, heap);
- if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
- WOLFSSL_MSG("Issue with parsing certificate");
- }
- if (CopyDecodedToX509(*cert, DeCert) != 0) {
- WOLFSSL_MSG("Failed to copy decoded cert");
- FreeDecodedCert(DeCert);
- if (pk != NULL) {
- XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- if (ca != NULL) {
- wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
- }
- wolfSSL_X509_free(*cert); *cert = NULL;
- XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
- ret = WOLFSSL_FAILURE;
- goto out;
- }
- FreeDecodedCert(DeCert);
- XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
- }
- /* get key type */
- ret = BAD_STATE_E;
- if (pk != NULL) { /* decode key if present */
- *pkey = wolfSSL_EVP_PKEY_new_ex(heap);
- if (*pkey == NULL) {
- wolfSSL_X509_free(*cert); *cert = NULL;
- if (ca != NULL) {
- wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
- }
- XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- ret = WOLFSSL_FAILURE;
- goto out;
- }
- #ifndef NO_RSA
- {
- const unsigned char* pt = pk;
- if (wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, pkey, &pt, pkSz) !=
- NULL) {
- ret = 0;
- }
- }
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- if (ret != 0) { /* if is in fail state check if ECC key */
- const unsigned char* pt = pk;
- if (wolfSSL_d2i_PrivateKey(EVP_PKEY_EC, pkey, &pt, pkSz) !=
- NULL) {
- ret = 0;
- }
- }
- #endif /* HAVE_ECC */
- if (pk != NULL)
- XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
- if (ret != 0) { /* if is in fail state and no PKEY then fail */
- wolfSSL_X509_free(*cert); *cert = NULL;
- if (ca != NULL) {
- wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
- }
- wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
- WOLFSSL_MSG("Bad PKCS12 key format");
- ret = WOLFSSL_FAILURE;
- goto out;
- }
- if (pkey != NULL && *pkey != NULL) {
- (*pkey)->save_type = 0;
- }
- }
- (void)ret;
- (void)ca;
- ret = WOLFSSL_SUCCESS;
- out:
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(DeCert, heap, DYNAMIC_TYPE_DCERT);
- #endif
- return ret;
- }
- int wolfSSL_PKCS12_verify_mac(WC_PKCS12 *pkcs12, const char *psw,
- int pswLen)
- {
- WOLFSSL_ENTER("wolfSSL_PKCS12_verify_mac");
- if (!pkcs12) {
- return WOLFSSL_FAILURE;
- }
- return wc_PKCS12_verify_ex(pkcs12, (const byte*)psw, (word32)pswLen) == 0 ?
- WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
- }
- #endif /* !NO_ASN && !NO_PWDBASED */
- #endif /* OPENSSL_EXTRA */
- #endif /* HAVE_PKCS12 */
- /*******************************************************************************
- * END OF PKCS12 APIs
- ******************************************************************************/
- #endif /* !WOLFCRYPT_ONLY && !NO_CERTS */
- #endif /* !WOLFSSL_SSL_P7P12_INCLUDED */
|