123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427 |
- /* ssl_certman.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
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <wolfssl/wolfcrypt/settings.h>
- #include <wolfssl/internal.h>
- #if !defined(WOLFSSL_SSL_CERTMAN_INCLUDED)
- #ifndef WOLFSSL_IGNORE_FILE_WARN
- #warning ssl_certman.c does not need to be compiled separately from ssl.c
- #endif
- #else
- #ifndef NO_CERTS
- /* Pick an available TLS method.
- *
- * Used when creating temporary WOLFSSL_CTX.
- *
- * @return A TLS method on success.
- * @return NULL when no TLS method built into wolfSSL.
- */
- static WC_INLINE WOLFSSL_METHOD* cm_pick_method(void* heap)
- {
- #ifndef NO_WOLFSSL_CLIENT
- #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3)
- return wolfSSLv3_client_method_ex(heap);
- #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10)
- return wolfTLSv1_client_method_ex(heap);
- #elif !defined(NO_OLD_TLS)
- return wolfTLSv1_1_client_method_ex(heap);
- #elif !defined(WOLFSSL_NO_TLS12)
- return wolfTLSv1_2_client_method_ex(heap);
- #elif defined(WOLFSSL_TLS13)
- return wolfTLSv1_3_client_method_ex(heap);
- #else
- return NULL;
- #endif
- #elif !defined(NO_WOLFSSL_SERVER)
- #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3)
- return wolfSSLv3_server_method_ex(heap);
- #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10)
- return wolfTLSv1_server_method_ex(heap);
- #elif !defined(NO_OLD_TLS)
- return wolfTLSv1_1_server_method_ex(heap);
- #elif !defined(WOLFSSL_NO_TLS12)
- return wolfTLSv1_2_server_method_ex(heap);
- #elif defined(WOLFSSL_TLS13)
- return wolfTLSv1_3_server_method_ex(heap);
- #else
- return NULL;
- #endif
- #else
- return NULL;
- #endif
- }
- /* Create a new certificate manager with a heap hint.
- *
- * @param [in] heap Heap hint.
- * @return Certificate manager object on success.
- * @return NULL on failure.
- */
- WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap)
- {
- int err = 0;
- WOLFSSL_CERT_MANAGER* cm;
- WOLFSSL_ENTER("wolfSSL_CertManagerNew");
- if (heap == NULL) {
- WOLFSSL_MSG("heap param is null");
- }
- else {
- /* Some systems may have heap in unexpected segments. (IRAM vs DRAM) */
- WOLFSSL_MSG_EX("heap param = %p", heap);
- }
- WOLFSSL_MSG_EX("DYNAMIC_TYPE_CERT_MANAGER Allocating = %d bytes",
- (word32)sizeof(WOLFSSL_CERT_MANAGER));
- /* Allocate memory for certificate manager. */
- cm = (WOLFSSL_CERT_MANAGER*)XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), heap,
- DYNAMIC_TYPE_CERT_MANAGER);
- if (cm == NULL) {
- WOLFSSL_MSG_EX("XMALLOC failed to allocate WOLFSSL_CERT_MANAGER %d "
- "bytes.", (int)sizeof(WOLFSSL_CERT_MANAGER));
- err = 1;
- }
- if (!err) {
- /* Reset all fields. */
- XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER));
- /* Create a mutex for use when modify table of stored CAs. */
- if (wc_InitMutex(&cm->caLock) != 0) {
- WOLFSSL_MSG("Bad mutex init");
- err = 1;
- }
- }
- if (!err) {
- /* Initialize reference count. */
- wolfSSL_RefInit(&cm->ref, &err);
- #ifdef WOLFSSL_REFCNT_ERROR_RETURN
- if (err != 0) {
- WOLFSSL_MSG("Bad reference count init");
- }
- #endif
- }
- #ifdef WOLFSSL_TRUST_PEER_CERT
- /* Create a mutex for use when modify table of trusted peers. */
- if ((!err) && (wc_InitMutex(&cm->tpLock) != 0)) {
- WOLFSSL_MSG("Bad mutex init");
- err = 1;
- }
- #endif
- if (!err) {
- /* Set default minimum key sizes allowed. */
- #ifndef NO_RSA
- cm->minRsaKeySz = MIN_RSAKEY_SZ;
- #endif
- #ifdef HAVE_ECC
- cm->minEccKeySz = MIN_ECCKEY_SZ;
- #endif
- #ifdef HAVE_PQC
- #ifdef HAVE_FALCON
- cm->minFalconKeySz = MIN_FALCONKEY_SZ;
- #endif /* HAVE_FALCON */
- #ifdef HAVE_DILITHIUM
- cm->minDilithiumKeySz = MIN_DILITHIUMKEY_SZ;
- #endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
- /* Set heap hint to use in certificate manager operations. */
- cm->heap = heap;
- }
- /* Dispose of certificate manager on error. */
- if (err && (cm != NULL)) {
- wolfSSL_CertManagerFree(cm);
- cm = NULL;
- }
- return cm;
- }
- /* Create a new certificate manager.
- *
- * @return Certificate manager object on success.
- * @return NULL on failure.
- */
- WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void)
- {
- /* No heap hint. */
- return wolfSSL_CertManagerNew_ex(NULL);
- }
- /* Dispose of certificate manager.
- *
- * @param [in, out] cm Certificate manager.
- */
- void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerFree");
- /* Validate parameter. */
- if (cm != NULL) {
- int doFree = 0;
- int ret;
- /* Decrement reference count and check if value is 0. */
- wolfSSL_RefDec(&cm->ref, &doFree, &ret);
- #ifdef WOLFSSL_REFCNT_ERROR_RETURN
- if (ret != 0) {
- WOLFSSL_MSG("Couldn't lock cm mutex");
- }
- #else
- (void)ret;
- #endif
- if (doFree) {
- #ifdef HAVE_CRL
- /* Dispose of CRL handler. */
- if (cm->crl != NULL) {
- /* Dispose of CRL object - indicating dynamically allocated. */
- FreeCRL(cm->crl, 1);
- }
- #endif
- #ifdef HAVE_OCSP
- /* Dispose of OCSP handler. */
- if (cm->ocsp != NULL) {
- FreeOCSP(cm->ocsp, 1);
- }
- /* Dispose of URL. */
- XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
- #if !defined(NO_WOLFSSL_SERVER) && \
- (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
- defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
- /* Dispose of OCSP stapling handler. */
- if (cm->ocsp_stapling) {
- FreeOCSP(cm->ocsp_stapling, 1);
- }
- #endif
- #endif /* HAVE_OCSP */
- /* Dispose of CA table and mutex. */
- FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
- wc_FreeMutex(&cm->caLock);
- #ifdef WOLFSSL_TRUST_PEER_CERT
- /* Dispose of trusted peer table and mutex. */
- FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
- wc_FreeMutex(&cm->tpLock);
- #endif
- /* Dispose of reference count. */
- wolfSSL_RefFree(&cm->ref);
- /* Dispose of certificate manager memory. */
- XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER);
- }
- }
- }
- /* Increase reference count on certificate manager.
- *
- * @param [in, out] cm Certificate manager.
- * @return WOLFSSL_SUCCESS on success.
- * @return 0 when cm is NULL or locking mutex fails.
- */
- int wolfSSL_CertManager_up_ref(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret = WOLFSSL_SUCCESS;
- /* Validate parameter. */
- if (cm == NULL) {
- ret = 0;
- }
- if (ret == WOLFSSL_SUCCESS) {
- int err;
- /* Increment reference. */
- wolfSSL_RefInc(&cm->ref, &err);
- #ifdef WOLFSSL_REFCNT_ERROR_RETURN
- if (err) {
- WOLFSSL_MSG("Failed to lock cm mutex");
- ret = 0;
- }
- #else
- (void)err;
- #endif
- }
- return ret;
- }
- #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM)
- #if defined(WOLFSSL_SIGNER_DER_CERT)
- static WC_INLINE int wolfssl_cm_get_certs_der(WOLFSSL_CERT_MANAGER* cm,
- DerBuffer*** buffers, int* cnt)
- {
- int err = 0;
- Signer* signers = NULL;
- DerBuffer** certBuffers = NULL;
- int i = 0;
- word32 row = 0;
- int numCerts = 0;
- /* Iterate once to get the number of certs, for memory allocation
- * purposes. */
- for (row = 0; row < CA_TABLE_SIZE; row++) {
- /* Get signer information of CAs in a row. */
- signers = cm->caTable[row];
- /* Count each signer in row that has a DER certificate buffer. */
- while ((signers != NULL) && (signers->derCert != NULL) &&
- (signers->derCert->buffer != NULL)) {
- ++numCerts;
- signers = signers->next;
- }
- }
- /* Check we found certificates. */
- if (numCerts == 0) {
- err = 1;
- }
- if (!err) {
- /* Allocate memory for pointers to each DER buffer. */
- certBuffers = (DerBuffer**)XMALLOC(
- sizeof(DerBuffer*) * (size_t)numCerts, cm->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (certBuffers == NULL) {
- err = 1;
- }
- }
- if (!err) {
- /* Reset pointers. */
- XMEMSET(certBuffers, 0, sizeof(DerBuffer*) * (size_t)numCerts);
- }
- /* Copy the certs locally so that we can release the caLock. If the lock
- * is held when wolfSSL_d2i_X509 is called, GetCA will also try to get
- * the lock, leading to deadlock. */
- for (row = 0; (!err) && (row < CA_TABLE_SIZE); row++) {
- /* Get signer information of CAs in a row. */
- signers = cm->caTable[row];
- /* Copy each DER certificate buffer of signers in a row. */
- while ((signers != NULL) && (signers->derCert != NULL) &&
- (signers->derCert->buffer != NULL)) {
- /* Allocate memory to hold DER certificate buffer. */
- int ret = AllocDer(&certBuffers[i], signers->derCert->length,
- CA_TYPE, cm->heap);
- if (ret < 0) {
- err = 1;
- break;
- }
- /* Copy buffer into array element. */
- XMEMCPY(certBuffers[i]->buffer, signers->derCert->buffer,
- signers->derCert->length);
- certBuffers[i]->length = signers->derCert->length;
- /* Store in next index. */
- ++i;
- /* Move on to next signer in row. */
- signers = signers->next;
- }
- }
- *buffers = certBuffers;
- *cnt = numCerts;
- return err;
- }
- /* Retrieve stack of X509 certificates in a certificate manager (CM).
- *
- * @param [in] cm Certificate manager.
- *
- * @return Stack of X509 certs on success
- * @return NULL on failure.
- */
- WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm)
- {
- WOLFSSL_STACK* sk = NULL;
- int numCerts = 0;
- DerBuffer** certBuffers = NULL;
- int i = 0;
- int err = 0;
- WOLFSSL_ENTER("wolfSSL_CertManagerGetCerts");
- /* Validate parameter. */
- if (cm == NULL) {
- err = 1;
- }
- if (!err) {
- /* Create an empty certificate stack to return. */
- sk = wolfSSL_sk_X509_new_null();
- if (sk == NULL) {
- err = 1;
- }
- }
- /* Lock CA table. */
- if ((!err) && (wc_LockMutex(&cm->caLock) != 0)) {
- err = 1;
- }
- if (!err) {
- err = wolfssl_cm_get_certs_der(cm, &certBuffers, &numCerts);
- /* Release CA lock. */
- wc_UnLockMutex(&cm->caLock);
- }
- /* Put each DER certificate buffer into a stack of WOLFSSL_X509 */
- for (i = 0; (!err) && (i < numCerts); ++i) {
- const byte* derBuffer = NULL;
- WOLFSSL_X509* x509 = NULL;
- /* Get pointer to DER encoding of certificate. */
- derBuffer = certBuffers[i]->buffer;
- /* Decode certificate. */
- wolfSSL_d2i_X509(&x509, &derBuffer, (int)certBuffers[i]->length);
- if (x509 == NULL) {
- err = 1;
- }
- /* Decode certificate. */
- if ((!err) && (wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS)) {
- wolfSSL_X509_free(x509);
- err = 1;
- }
- }
- if (certBuffers != NULL) {
- /* Dispose of temporary cert storage (for access outside of lock). */
- for (i = 0; i < numCerts && certBuffers[i] != NULL; ++i) {
- FreeDer(&certBuffers[i]);
- }
- XFREE(certBuffers, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- /* Dispose of stack of certificates on error. */
- if (err && (sk != NULL)) {
- wolfSSL_sk_X509_pop_free(sk, NULL);
- sk = NULL;
- }
- return sk;
- }
- #endif /* WOLFSSL_SIGNER_DER_CERT */
- #endif /* OPENSSL_EXTRA && !NO_FILESYSTEM */
- /* Unload the CA signer table.
- *
- * @param [in] cm Certificate manager.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm is NULL.
- * @return BAD_MUTEX_E when locking fails.
- */
- int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerUnloadCAs");
- /* Validate parameter. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- /* Lock CA table. */
- if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
- ret = BAD_MUTEX_E;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Dispose of CA table. */
- FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
- /* Unlock CA table. */
- wc_UnLockMutex(&cm->caLock);
- }
- return ret;
- }
- int wolfSSL_CertManagerUnloadIntermediateCerts(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerUnloadIntermediateCerts");
- /* Validate parameter. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- /* Lock CA table. */
- if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
- ret = BAD_MUTEX_E;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Dispose of CA table. */
- FreeSignerTableType(cm->caTable, CA_TABLE_SIZE, WOLFSSL_CHAIN_CA,
- cm->heap);
- /* Unlock CA table. */
- wc_UnLockMutex(&cm->caLock);
- }
- return ret;
- }
- #ifdef WOLFSSL_TRUST_PEER_CERT
- /* Unload the trusted peers table.
- *
- * @param [in] cm Certificate manager.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm is NULL.
- * @return BAD_MUTEX_E when locking fails.
- */
- int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerUnload_trust_peers");
- /* Validate parameter. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- /* Lock trusted peers table. */
- if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->tpLock) != 0)) {
- ret = BAD_MUTEX_E;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Dispose of trusted peers table. */
- FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
- /* Unlock trusted peers table. */
- wc_UnLockMutex(&cm->tpLock);
- }
- return ret;
- }
- #endif /* WOLFSSL_TRUST_PEER_CERT */
- /* Load certificate/s from buffer with flags.
- *
- * @param [in] cm Certificate manager.
- * @param [in] buff Buffer holding encoding of certificate.
- * @param [in] sz Length in bytes of data in buffer.
- * @param [in] format Format of encoding. Valid values:
- * WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
- * @param [in] userChain Indicates buffer holds chain of certificates.
- * @param [in] flags Flags to modify behaviour of loading. Valid flags:
- * WOLFSSL_LOAD_FLAG_IGNORE_ERR,
- * WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY,
- * WOLFSSL_LOAD_FLAG_PEM_CA_ONLY,
- * WOLFSSL_LOAD_FLAG_IGNORE_BAD_PATH_ERR, and
- * WOLFSSL_LOAD_FLAG_IGNORE_ZEROFILE.
- * @return WOLFSSL_SUCCESS on success.
- * @return WOLFSSL_FATAL_ERROR when cm is NULL or failed create WOLFSSL_CTX.
- * @return Other values on loading failure.
- */
- int wolfSSL_CertManagerLoadCABuffer_ex(WOLFSSL_CERT_MANAGER* cm,
- const unsigned char* buff, long sz, int format, int userChain, word32 flags)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_CTX* tmp = NULL;
- WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABuffer_ex");
- /* Validate parameters. */
- if (cm == NULL) {
- WOLFSSL_MSG("No CertManager error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* Allocate a temporary WOLFSSL_CTX to load with. */
- if ((ret == WOLFSSL_SUCCESS) && ((tmp =
- wolfSSL_CTX_new_ex(cm_pick_method(cm->heap), cm->heap)) == NULL)) {
- WOLFSSL_MSG("CTX new failed");
- ret = WOLFSSL_FATAL_ERROR;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Some configurations like OPENSSL_COMPATIBLE_DEFAULTS may turn off
- * verification by default. Let's restore our desired defaults. */
- wolfSSL_CTX_set_verify(tmp, WOLFSSL_VERIFY_DEFAULT, NULL);
- /* Replace certificate manager with one to load certificate/s into. */
- wolfSSL_CertManagerFree(tmp->cm);
- tmp->cm = cm;
- /* Load certificate buffer. */
- ret = wolfSSL_CTX_load_verify_buffer_ex(tmp, buff, sz, format,
- userChain, flags);
- /* Clear certificate manager in WOLFSSL_CTX so it won't be freed. */
- tmp->cm = NULL;
- }
- /* Dispose of temporary WOLFSSL_CTX. */
- wolfSSL_CTX_free(tmp);
- return ret;
- }
- /* Load certificate/s from buffer into table.
- *
- * Uses default load verification flags and is not a user chain.
- *
- * @param [in] cm Certificate manager.
- * @param [in] buff Buffer holding encoding of certificate.
- * @param [in] sz Length in bytes of data in buffer.
- * @param [in] format Format of encoding. Valid values:
- * WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
- * @return WOLFSSL_SUCCESS on success.
- * @return WOLFSSL_FATAL_ERROR when cm is NULL or failed create WOLFSSL_CTX.
- * @return Other values on loading failure.
- */
- int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER* cm,
- const unsigned char* buff, long sz, int format)
- {
- return wolfSSL_CertManagerLoadCABuffer_ex(cm, buff, sz, format, 0,
- WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
- }
- #ifndef NO_WOLFSSL_CM_VERIFY
- /* Set the verification callback into certificate manager.
- *
- * @param [in] cm Certificate manager.
- * @param [in] vc Verification callback.
- */
- void wolfSSL_CertManagerSetVerify(WOLFSSL_CERT_MANAGER* cm, VerifyCallback vc)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerSetVerify");
- if (cm != NULL) {
- cm->verifyCallback = vc;
- }
- }
- #endif /* NO_WOLFSSL_CM_VERIFY */
- #if defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ASN_TEMPLATE) \
- && defined(HAVE_OID_DECODING)
- void wolfSSL_CertManagerSetUnknownExtCallback(WOLFSSL_CERT_MANAGER* cm,
- wc_UnknownExtCallback cb)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerSetUnknownExtCallback");
- if (cm != NULL) {
- cm->unknownExtCallback = cb;
- }
- }
- #endif /* WOLFSSL_CUSTOM_OID && WOLFSSL_ASN_TEMPLATE && HAVE_OID_DECODING */
- #if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
- /* Verify the certificate.
- *
- * Uses the verification callback if available.
- *
- * @param [in] cm Certificate manager.
- * @param [in] buff Buffer holding encoded certificate.
- * @param [in] sz Size in bytes of data in buffer.
- * @param [in] format Format of encoding. Valid values:
- * WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
- * @param [in] prev_err Previous error. Passed to callback.
- * @return WOLFSSL_SUCCESS on success.
- * @return MEMORY_E when dynamic memory allocation fails.
- * @return NOT_COMPILED_IN when converting from PEM to DER is not a feature of
- * the wolfSSL build.
- */
- int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const unsigned char* buff,
- long sz, int format, int prev_err)
- {
- int ret = 0;
- int fatal = 0;
- DerBuffer* der = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert = NULL;
- #else
- DecodedCert cert[1];
- #endif
- WOLFSSL_ENTER("CM_VerifyBuffer_ex");
- (void)prev_err;
- #ifdef WOLFSSL_SMALL_STACK
- /* Allocate memory for decoded certificate. */
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL) {
- ret = MEMORY_E;
- fatal = 1;
- }
- if (ret == 0)
- #endif
- {
- /* Reset fields of decoded certificate. */
- XMEMSET(cert, 0, sizeof(DecodedCert));
- if (format == WOLFSSL_FILETYPE_PEM) {
- #ifndef WOLFSSL_PEM_TO_DER
- ret = NOT_COMPILED_IN;
- fatal = 1;
- #else
- /* Convert to DER from PEM. */
- ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, NULL, NULL);
- if (ret != 0) {
- fatal = 1;
- }
- else {
- /* Replace buffer pointer and size with DER buffer. */
- buff = der->buffer;
- sz = (long)der->length;
- }
- #endif
- }
- }
- if (ret == 0) {
- /* Create a decoded certificate with DER buffer. */
- InitDecodedCert(cert, buff, (word32)sz, cm->heap);
- #if defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ASN_TEMPLATE) \
- && defined(HAVE_OID_DECODING)
- if (cm->unknownExtCallback != NULL)
- wc_SetUnknownExtCallback(cert, cm->unknownExtCallback);
- #endif
- /* Parse DER into decoded certificate fields and verify signature
- * against a known CA. */
- ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, cm);
- }
- #ifdef HAVE_CRL
- if ((ret == 0) && cm->crlEnabled) {
- /* Check for a CRL for the CA and check validity of certificate. */
- ret = CheckCertCRL(cm->crl, cert);
- }
- #endif
- (void)fatal;
- #ifndef NO_WOLFSSL_CM_VERIFY
- /* Use callback to perform verification too if available. */
- if ((!fatal) && cm->verifyCallback) {
- #ifdef WOLFSSL_SMALL_STACK
- ProcPeerCertArgs* args;
- #else
- ProcPeerCertArgs args[1];
- #endif
- buffer certBuf;
- #ifdef WOLFSSL_SMALL_STACK
- /* Allocate memory for object to hold arguments for callback. */
- args = (ProcPeerCertArgs*)XMALLOC(sizeof(ProcPeerCertArgs), cm->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (args == NULL) {
- ret = MEMORY_E;
- fatal = 1;
- }
- if (!fatal)
- #endif
- {
- XMEMSET(args, 0, sizeof(ProcPeerCertArgs));
- /* DER encoding. */
- certBuf.buffer = (byte*)buff;
- certBuf.length = (unsigned int)sz;
- /* One certificate available. */
- args->totalCerts = 1;
- args->certs = &certBuf;
- args->dCert = cert;
- args->dCertInit = 1;
- /* Replace value in ret with an error value passed in. */
- if (prev_err != 0) {
- ret = prev_err;
- }
- /* Use callback to verify certificate. */
- ret = DoVerifyCallback(cm, NULL, ret, args);
- }
- #ifdef WOLFSSL_SMALL_STACK
- /* Dispose of allocated callback args. */
- XFREE(args, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- }
- #endif
- /* Dispose of allocated memory. */
- FreeDecodedCert(cert);
- FreeDer(&der);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
- #endif
- /* Convert the ret value to a return value. */
- return (ret == 0) ? WOLFSSL_SUCCESS : ret;
- }
- /* Verify the certificate.
- *
- * Uses the verification callback if available.
- *
- * @param [in] cm Certificate manager.
- * @param [in] buff Buffer holding encoded certificate.
- * @param [in] sz Size in bytes of data in buffer.
- * @param [in] format Format of encoding. Valid values:
- * WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
- * @param [in] prev_err Previous error. Passed to callback.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm or buff is NULL or sz is negative or zero.
- * @return WOLFSSL_BAD_FILETYPE when format is invalid.
- * @return MEMORY_E when dynamic memory allocation fails.
- * @return NOT_COMPILED_IN when converting from PEM to DER is not a feature of
- * the wolfSSL build.
- */
- int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm,
- const unsigned char* buff, long sz, int format)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_CertManagerVerifyBuffer");
- /* Validate parameters. */
- if ((cm == NULL) || (buff == NULL) || (sz <= 0)) {
- ret = BAD_FUNC_ARG;
- }
- else if ((format != WOLFSSL_FILETYPE_ASN1) &&
- (format != WOLFSSL_FILETYPE_PEM)) {
- ret = WOLFSSL_BAD_FILETYPE;
- }
- else {
- /* No previous error. */
- ret = CM_VerifyBuffer_ex(cm, buff, sz, format, 0);
- }
- return ret;
- }
- #endif /* !NO_WOLFSSL_CLIENT || !WOLFSSL_NO_CLIENT_AUTH */
- #ifndef NO_FILESYSTEM
- #if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
- /* Verify the certificate loaded from a file.
- *
- * Uses the verification callback if available.
- *
- * @param [in] cm Certificate manager.
- * @param [in] format Format of encoding. Valid values:
- * WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
- * @param [in] prev_err Previous error. Passed to callback.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm or buff is NULL or sz is negative.
- * @return WOLFSSL_BAD_FILETYPE when format is invalid.
- * @return WOLFSSL_BAD_FILE when reading the certificate file fails.
- * @return MEMORY_E when dynamic memory allocation fails.
- * @return NOT_COMPILED_IN when converting from PEM to DER is not a feature of
- * the wolfSSL build.
- */
- int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname,
- int format)
- {
- int ret = WOLFSSL_SUCCESS;
- #ifndef WOLFSSL_SMALL_STACK
- byte staticBuffer[FILE_BUFFER_SIZE];
- #endif
- byte* buff = NULL;
- long sz = 0;
- XFILE file = XBADFILE;
- WOLFSSL_ENTER("wolfSSL_CertManagerVerify");
- #ifndef WOLFSSL_SMALL_STACK
- buff = staticBuffer;
- #endif
- /* Validate parameters. cm and format validated in:
- * wolfSSL_CertManagerVerifyBuffer */
- if ((cm == NULL) || (fname == NULL)) {
- ret = BAD_FUNC_ARG;
- }
- /* Open the file containing a certificate. */
- if ((ret == WOLFSSL_SUCCESS) &&
- ((file = XFOPEN(fname, "rb")) == XBADFILE)) {
- ret = WOLFSSL_BAD_FILE;
- }
- /* Get the length of the file. */
- if (ret == WOLFSSL_SUCCESS) {
- ret = wolfssl_file_len(file, &sz);
- if (ret == 0) {
- ret = WOLFSSL_SUCCESS;
- }
- }
- /* Allocate dynamic memory for file contents if no static buffer or too
- * small. */
- #ifndef WOLFSSL_SMALL_STACK
- if ((ret == WOLFSSL_SUCCESS) && (sz > (long)sizeof(staticBuffer)))
- #else
- if (ret == WOLFSSL_SUCCESS)
- #endif
- {
- WOLFSSL_MSG("Getting dynamic buffer");
- buff = (byte*)XMALLOC((size_t)sz, cm->heap, DYNAMIC_TYPE_FILE);
- if (buff == NULL) {
- ret = WOLFSSL_BAD_FILE;
- }
- }
- /* Read all the file into buffer. */
- if ((ret == WOLFSSL_SUCCESS) && (XFREAD(buff, 1, (size_t)sz, file) !=
- (size_t)sz)) {
- ret = WOLFSSL_BAD_FILE;
- }
- /* Close file if opened. */
- if (file != XBADFILE) {
- XFCLOSE(file);
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Verify the certificate read. */
- ret = wolfSSL_CertManagerVerifyBuffer(cm, buff, sz, format);
- }
- /* Dispose of buffer if it was allocated. */
- #ifndef WOLFSSL_SMALL_STACK
- if (buff != staticBuffer)
- #endif
- {
- if (cm != NULL) {
- XFREE(buff, cm->heap, DYNAMIC_TYPE_FILE);
- }
- }
- return ret;
- }
- #endif
- /* Load the CA file and/or certificate files in a path.
- *
- * @param [in] cm Certificate manager.
- * @param [in] file Name of CA file.
- * @param [in] path Path to a directory containing certificates.
- * @return WOLFSSL_SUCCESS on success.
- * @return WOLFSSL_FATAL_ERROR when cm is NULL or unable to create WOLFSSL_CTX.
- * @return Otherwise failure.
- */
- int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* file,
- const char* path)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_CTX* tmp = NULL;
- WOLFSSL_ENTER("wolfSSL_CertManagerLoadCA");
- /* Validate parameters. file and path validated in:
- * wolfSSL_CTX_load_verify_locations*/
- if (cm == NULL) {
- WOLFSSL_MSG("No CertManager error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* Create temporary WOLFSSL_CTX. */
- if ((ret == WOLFSSL_SUCCESS) && ((tmp =
- wolfSSL_CTX_new_ex(cm_pick_method(cm->heap), cm->heap)) == NULL)) {
- WOLFSSL_MSG("CTX new failed");
- ret = WOLFSSL_FATAL_ERROR;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Some configurations like OPENSSL_COMPATIBLE_DEFAULTS may turn off
- * verification by default. Let's restore our desired defaults. */
- wolfSSL_CTX_set_verify(tmp, WOLFSSL_VERIFY_DEFAULT, NULL);
- /* Replace certificate manager with one to load certificate/s into. */
- wolfSSL_CertManagerFree(tmp->cm);
- tmp->cm = cm;
- /* Load certificate from file and path. */
- ret = wolfSSL_CTX_load_verify_locations(tmp, file, path);
- /* Clear certificate manager in WOLFSSL_CTX so it won't be freed. */
- tmp->cm = NULL;
- }
- /* Dispose of temporary WOLFSSL_CTX. */
- wolfSSL_CTX_free(tmp);
- return ret;
- }
- #endif /* NO_FILESYSTEM */
- #if defined(PERSIST_CERT_CACHE)
- /* Version of layout of cache of CA certificates. */
- #define WOLFSSL_CACHE_CERT_VERSION 1
- /* CA certificates cache information. */
- typedef struct {
- /* Cache certificate layout version id. */
- int version;
- /* Number of hash table rows. Maximum of CA_TABLE_SIZE. */
- int rows;
- /* Number of columns per row. */
- int columns[CA_TABLE_SIZE];
- /* Size of Signer object. */
- int signerSz;
- } CertCacheHeader;
- /* current cert persistence layout is:
- 1) CertCacheHeader
- 2) caTable
- update WOLFSSL_CERT_CACHE_VERSION if change layout for the following
- PERSIST_CERT_CACHE functions
- */
- /* Return number of bytes of memory needed to persist this signer.
- *
- * Assumes we have locked CA table.
- *
- * @param [in] Signer Signer entry in CA table.
- * @return Number of bytes.
- */
- static WC_INLINE int cm_get_signer_memory(Signer* signer)
- {
- int sz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID)
- + sizeof(signer->nameLen) + sizeof(signer->subjectNameHash);
- #if !defined(NO_SKID)
- sz += (int)sizeof(signer->subjectKeyIdHash);
- #endif
- /* Add dynamic bytes needed. */
- sz += (int)signer->pubKeySize;
- sz += signer->nameLen;
- return sz;
- }
- /* Return number of bytes of memory needed to persist this row.
- *
- * Assumes we have locked CA table.
- *
- * @param [in] row A row of signers from the CA table.
- * @return Number of bytes.
- */
- static WC_INLINE int cm_get_cert_cache_row_memory(Signer* row)
- {
- int sz = 0;
- /* Each signer in row. */
- while (row != NULL) {
- /* Add in size of this signer. */
- sz += cm_get_signer_memory(row);
- row = row->next;
- }
- return sz;
- }
- /* Return the number of bytes of memory to persist cert cache.
- *
- * Assumes we have locked CA table.
- *
- * @param [in] cm Certificate manager.
- * @return Number of bytes.
- */
- static WC_INLINE int cm_get_cert_cache_mem_size(WOLFSSL_CERT_MANAGER* cm)
- {
- int sz;
- int i;
- sz = sizeof(CertCacheHeader);
- /* Each row in table. */
- for (i = 0; i < CA_TABLE_SIZE; i++) {
- /* Add in size of this row. */
- sz += cm_get_cert_cache_row_memory(cm->caTable[i]);
- }
- return sz;
- }
- /* Get count of columns for each row.
- *
- * Assumes we have locked CA table.
- *
- * @param [in] cm Certificate manager.
- * @param [in] columns Array of row counts.
- */
- static WC_INLINE void cm_set_cert_header_Columns(WOLFSSL_CERT_MANAGER* cm,
- int* columns)
- {
- int i;
- Signer* row;
- /* Each row in table. */
- for (i = 0; i < CA_TABLE_SIZE; i++) {
- int count = 0;
- /* Get row from table. */
- row = cm->caTable[i];
- /* Each entry in row. */
- while (row != NULL) {
- /* Update count. */
- ++count;
- row = row->next;
- }
- /* Store row count. */
- columns[i] = count;
- }
- }
- /* Restore whole cert row from memory,
- *
- * Assumes we have locked CA table.
- *
- * @param [in] cm Certificate manager.
- * @param [in] current Buffer containing rows.
- * @param [in] row Row number being restored.
- * @param [in] listSz Number of entries in row.
- * @param [in] end End of data in buffer.
- * @return Number of bytes consumed on success.
- * @return PARSE_ERROR when listSz is less than zero.
- * @return BUFFER_E when buffer is too small.
- * @return MEMORY_E when dynamic memory allocation fails.
- * @return Negative value on error.
- */
- static WC_INLINE int cm_restore_cert_row(WOLFSSL_CERT_MANAGER* cm,
- byte* current, int row, int listSz, const byte* end)
- {
- int ret = 0;
- int idx = 0;
- /* Validate parameters. */
- if (listSz < 0) {
- WOLFSSL_MSG("Row header corrupted, negative value");
- ret = PARSE_ERROR;
- }
- /* Process all entries. */
- while ((ret == 0) && (listSz > 0)) {
- Signer* signer = NULL;
- byte* publicKey;
- byte* start = current + idx; /* for end checks on this signer */
- int minSz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID) +
- sizeof(signer->nameLen) + sizeof(signer->subjectNameHash);
- #ifndef NO_SKID
- minSz += (int)sizeof(signer->subjectKeyIdHash);
- #endif
- /* Check minimal size of bytes available. */
- if (start + minSz > end) {
- WOLFSSL_MSG("Would overread restore buffer");
- ret = BUFFER_E;
- }
- /* Make a new signer. */
- if ((ret == 0) && ((signer = MakeSigner(cm->heap)) == NULL)) {
- ret = MEMORY_E;
- }
- if (ret == 0) {
- /* Copy in public key size. */
- XMEMCPY(&signer->pubKeySize, current + idx,
- sizeof(signer->pubKeySize));
- idx += (int)sizeof(signer->pubKeySize);
- /* Copy in public key OID. */
- XMEMCPY(&signer->keyOID, current + idx, sizeof(signer->keyOID));
- idx += (int)sizeof(signer->keyOID);
- /* Check bytes available for public key. */
- if (start + minSz + signer->pubKeySize > end) {
- WOLFSSL_MSG("Would overread restore buffer");
- ret = BUFFER_E;
- }
- }
- if (ret == 0) {
- /* Allocate memory for public key to be stored in. */
- publicKey = (byte*)XMALLOC(signer->pubKeySize, cm->heap,
- DYNAMIC_TYPE_KEY);
- if (publicKey == NULL) {
- ret = MEMORY_E;
- }
- }
- if (ret == 0) {
- /* Copy in public key. */
- XMEMCPY(publicKey, current + idx, signer->pubKeySize);
- signer->publicKey = publicKey;
- idx += (int)signer->pubKeySize;
- /* Copy in certificate name length. */
- XMEMCPY(&signer->nameLen, current + idx, sizeof(signer->nameLen));
- idx += (int)sizeof(signer->nameLen);
- /* Check bytes available for certificate name. */
- if (start + minSz + signer->pubKeySize + signer->nameLen > end) {
- WOLFSSL_MSG("Would overread restore buffer");
- ret = BUFFER_E;
- }
- }
- if (ret == 0) {
- /* Allocate memory for public key to be stored in. */
- signer->name = (char*)XMALLOC((size_t)signer->nameLen, cm->heap,
- DYNAMIC_TYPE_SUBJECT_CN);
- if (signer->name == NULL) {
- ret = MEMORY_E;
- }
- }
- if (ret == 0) {
- /* Copy in certificate name. */
- XMEMCPY(signer->name, current + idx, (size_t)signer->nameLen);
- idx += signer->nameLen;
- /* Copy in hash of subject name. */
- XMEMCPY(signer->subjectNameHash, current + idx, SIGNER_DIGEST_SIZE);
- idx += SIGNER_DIGEST_SIZE;
- #ifndef NO_SKID
- /* Copy in hash of subject key. */
- XMEMCPY(signer->subjectKeyIdHash, current + idx,SIGNER_DIGEST_SIZE);
- idx += SIGNER_DIGEST_SIZE;
- #endif
- /* Make next Signer the head of the row. */
- signer->next = cm->caTable[row];
- /* Add Signer to start of row. */
- cm->caTable[row] = signer;
- /* Done one more Signer. */
- --listSz;
- }
- if ((ret != 0) && (signer != NULL)) {
- /* Dispose of allocated signer. */
- FreeSigner(signer, cm->heap);
- }
- }
- if (ret == 0) {
- /* Return the number of bytes used on success. */
- ret = idx;
- }
- return ret;
- }
- /* Store whole CA certificate row into memory.
- *
- * Assumes we have locked CA table.
- *
- * @param [in] cm Certificate manager.
- * @param [in] current Buffer to write to.
- * @param [in] row Row number being stored.
- * @return Number of bytes added.
- */
- static WC_INLINE int cm_store_cert_row(WOLFSSL_CERT_MANAGER* cm, byte* current,
- int row)
- {
- int added = 0;
- Signer* list;
- /* Get the row - a linked list. */
- list = cm->caTable[row];
- /* Each certificate in row. */
- while (list != NULL) {
- /* Public key size. */
- XMEMCPY(current + added, &list->pubKeySize, sizeof(list->pubKeySize));
- added += (int)sizeof(list->pubKeySize);
- /* Public key OID. */
- XMEMCPY(current + added, &list->keyOID, sizeof(list->keyOID));
- added += (int)sizeof(list->keyOID);
- /* Public key. */
- XMEMCPY(current + added, list->publicKey, (size_t)list->pubKeySize);
- added += (int)list->pubKeySize;
- /* Certificate name length. */
- XMEMCPY(current + added, &list->nameLen, sizeof(list->nameLen));
- added += (int)sizeof(list->nameLen);
- /* Certificate name. */
- XMEMCPY(current + added, list->name, (size_t)list->nameLen);
- added += list->nameLen;
- /* Hash of subject name. */
- XMEMCPY(current + added, list->subjectNameHash, SIGNER_DIGEST_SIZE);
- added += SIGNER_DIGEST_SIZE;
- #ifndef NO_SKID
- /* Hash of public key. */
- XMEMCPY(current + added, list->subjectKeyIdHash,SIGNER_DIGEST_SIZE);
- added += SIGNER_DIGEST_SIZE;
- #endif
- /* Next certificate in row. */
- list = list->next;
- }
- return added;
- }
- /* Persist CA certificate cache to memory.
- *
- * Assumes we have locked CA table.
- *
- * @param [in] cm Certificate manager.
- * @param [in] mem Memory to persist into.
- * @param [in] sz Size in bytes of memory.
- * @return WOLFSSL_SUCCESS on success.
- * @return BUFFER_E when memory is too small.
- */
- static WC_INLINE int cm_do_mem_save_cert_cache(WOLFSSL_CERT_MANAGER* cm,
- void* mem, int sz)
- {
- int ret = WOLFSSL_SUCCESS;
- int realSz;
- int i;
- WOLFSSL_ENTER("cm_do_mem_save_cert_cache");
- /* Calculate amount of memory required to store CA certificate table. */
- realSz = cm_get_cert_cache_mem_size(cm);
- if (realSz > sz) {
- WOLFSSL_MSG("Mem output buffer too small");
- ret = BUFFER_E;
- }
- if (ret == WOLFSSL_SUCCESS) {
- byte* current;
- CertCacheHeader hdr;
- /* Create header for storage. */
- hdr.version = WOLFSSL_CACHE_CERT_VERSION;
- hdr.rows = CA_TABLE_SIZE;
- cm_set_cert_header_Columns(cm, hdr.columns);
- hdr.signerSz = (int)sizeof(Signer);
- /* Copy header into memory. */
- XMEMCPY(mem, &hdr, sizeof(CertCacheHeader));
- current = (byte*)mem + sizeof(CertCacheHeader);
- /* Each row of table. */
- for (i = 0; i < CA_TABLE_SIZE; ++i) {
- /* Append row to memory. */
- current += cm_store_cert_row(cm, current, i);
- }
- }
- return ret;
- }
- #if !defined(NO_FILESYSTEM)
- /* Persist CA certificate cache to file.
- *
- * Locks CA table.
- *
- * @param [in] cm Certificate manager.
- * @param [in] fname File name to write to.
- * @return WOLFSSL_SUCCESS on success.
- * @return WOLFSSL_BAD_FILE when opening file fails.
- * @return BAD_MUTEX_E when locking fails.
- * @return MEMORY_E when dynamic memory allocation fails.
- * @return FWRITE_ERROR when writing to file fails.
- */
- int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
- {
- XFILE file;
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("CM_SaveCertCache");
- /* Open file for writing. */
- file = XFOPEN(fname, "w+b");
- if (file == XBADFILE) {
- WOLFSSL_MSG("Couldn't open cert cache save file");
- ret = WOLFSSL_BAD_FILE;
- }
- /* Lock CA table. */
- if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
- WOLFSSL_MSG("wc_LockMutex on caLock failed");
- ret = BAD_MUTEX_E;
- }
- if (ret == WOLFSSL_SUCCESS) {
- byte* mem;
- /* Calculate size of memory required to store CA table. */
- size_t memSz = (size_t)cm_get_cert_cache_mem_size(cm);
- /* Allocate memory to hold CA table. */
- mem = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- WOLFSSL_MSG("Alloc for tmp buffer failed");
- ret = MEMORY_E;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Store CA table in memory. */
- ret = cm_do_mem_save_cert_cache(cm, mem, (int)memSz);
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Write memory to file. */
- int sz = (int)XFWRITE(mem, memSz, 1, file);
- if (sz != 1) {
- WOLFSSL_MSG("Cert cache file write failed");
- ret = FWRITE_ERROR;
- }
- }
- if (mem != NULL) {
- XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- /* Unlock CA table. */
- wc_UnLockMutex(&cm->caLock);
- }
- /* Close file. */
- if (file != XBADFILE) {
- XFCLOSE(file);
- }
- return ret;
- }
- /* Restore CA certificate cache from file.
- *
- * @param [in] cm Certificate manager.
- * @param [in] fname File name to write to.
- * @return WOLFSSL_SUCCESS on success.
- * @return WOLFSSL_BAD_FILE when opening or using file fails.
- * @return MEMORY_E when dynamic memory allocation fails.
- * @return FREAD_ERROR when reading from file fails.
- */
- int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
- {
- XFILE file;
- int ret = WOLFSSL_SUCCESS;
- int memSz = 0;
- byte* mem = NULL;
- WOLFSSL_ENTER("CM_RestoreCertCache");
- /* Open file for reading. */
- file = XFOPEN(fname, "rb");
- if (file == XBADFILE) {
- WOLFSSL_MSG("Couldn't open cert cache save file");
- ret = WOLFSSL_BAD_FILE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Read file into allocated memory. */
- ret = wolfssl_read_file(file, (char**)&mem, &memSz);
- if (ret == 0) {
- ret = WOLFSSL_SUCCESS;
- }
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Create the CA certificate table from memory. */
- ret = CM_MemRestoreCertCache(cm, mem, memSz);
- if (ret != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Mem restore cert cache failed");
- }
- }
- /* Dispose of dynamic memory read into. */
- XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
- /* Close file. */
- if (file != XBADFILE) {
- XFCLOSE(file);
- }
- return ret;
- }
- #endif /* NO_FILESYSTEM */
- /* Persist CA certificate cache to memory.
- *
- * Locks CA table.
- *
- * @param [in] cm Certificate manager.
- * @param [in] mem Memory to persist into.
- * @param [in] sz Size in bytes of memory.
- * @param [out] used Number of bytes used when persisting cache.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_MUTEX_E when locking fails.
- * @return BUFFER_E when memory is too small.
- */
- int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("CM_MemSaveCertCache");
- /* Lock CA table. */
- if (wc_LockMutex(&cm->caLock) != 0) {
- WOLFSSL_MSG("wc_LockMutex on caLock failed");
- ret = BAD_MUTEX_E;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Save CA table into memory. */
- ret = cm_do_mem_save_cert_cache(cm, mem, sz);
- if (ret == WOLFSSL_SUCCESS) {
- /* Get the number of bytes used. */
- *used = cm_get_cert_cache_mem_size(cm);
- }
- /* Unlock CA table. */
- wc_UnLockMutex(&cm->caLock);
- }
- return ret;
- }
- /* Restore CA certificate table from memory,
- *
- * Locks CA table.
- *
- * @param [in] cm Certificate manager.
- * @param [in] mem Buffer containing rows.
- * @param [in] sz Size in bytes of data in buffer.
- * @return WOLFSSL_SUCCESS on success.
- * @return BUFFER_E when buffer is too small.
- * @return BAD_MUTEX_E when locking fails.
- * @return MEMORY_E when dynamic memory allocation fails.
- */
- int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz)
- {
- int ret = WOLFSSL_SUCCESS;
- int i;
- CertCacheHeader* hdr = (CertCacheHeader*)mem;
- byte* current = (byte*)mem + sizeof(CertCacheHeader);
- byte* end = (byte*)mem + sz; /* don't go over */
- WOLFSSL_ENTER("CM_MemRestoreCertCache");
- /* Check memory available is bigger than cache header. */
- if (current > end) {
- WOLFSSL_MSG("Cert Cache Memory buffer too small");
- ret = BUFFER_E;
- }
- /* Validate the cache header. */
- if ((ret == WOLFSSL_SUCCESS) &&
- ((hdr->version != WOLFSSL_CACHE_CERT_VERSION) ||
- (hdr->rows != CA_TABLE_SIZE) ||
- (hdr->signerSz != (int)sizeof(Signer)))) {
- WOLFSSL_MSG("Cert Cache Memory header mismatch");
- ret = CACHE_MATCH_ERROR;
- }
- /* Lock CA table. */
- if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
- WOLFSSL_MSG("wc_LockMutex on caLock failed");
- ret = BAD_MUTEX_E;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Dispose of current CA certificate table. */
- FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
- /* Each row. */
- for (i = 0; i < CA_TABLE_SIZE; ++i) {
- /* Restore a row from memory. */
- int added = cm_restore_cert_row(cm, current, i, hdr->columns[i],
- end);
- /* Bail on error. */
- if (added < 0) {
- WOLFSSL_MSG("cm_restore_cert_row error");
- ret = added;
- break;
- }
- /* Update pointer to data of next row. */
- current += added;
- }
- /* Unlock CA table. */
- wc_UnLockMutex(&cm->caLock);
- }
- return ret;
- }
- /* Calculate size of CA certificate cache when persisted to memory.
- *
- * Locks CA table.
- *
- * @param [in] cm Certificate manager.
- * @return Number of bytes on success.
- * @return BAD_MUTEX_E when locking fails.
- */
- int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret;
- WOLFSSL_ENTER("CM_GetCertCacheMemSize");
- /* Lock CA table. */
- if (wc_LockMutex(&cm->caLock) != 0) {
- WOLFSSL_MSG("wc_LockMutex on caLock failed");
- ret = BAD_MUTEX_E;
- }
- else {
- /* Calculate memory size. */
- ret = cm_get_cert_cache_mem_size(cm);
- /* Unlock CA table. */
- wc_UnLockMutex(&cm->caLock);
- }
- return ret;
- }
- #endif /* PERSIST_CERT_CACHE */
- /*******************************************************************************
- * CRL handling
- ******************************************************************************/
- /* Enables/disables the use of CRLs when validating certificates.
- *
- * @param [in] cm Certificate manager.
- * @param [in] options Options for using CRLs. Valid flags:
- * WOLFSSL_CRL_CHECKALL, WOLFSSL_CRL_CHECK.
- * @return WOLFSSL_SUCCESS on success.
- * @return WOLFSSL_FAILURE when initializing the CRL object fails.
- * @return BAD_FUNC_ARG when cm is NULL.
- * @return MEMORY_E when dynamic memory allocation fails.
- * @return NOT_COMPILED_IN when the CRL feature is disabled.
- */
- int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerEnableCRL");
- (void)options;
- /* Validate parameters. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- #if defined(OPENSSL_COMPATIBLE_DEFAULTS)
- /* If disabling then don't worry about whether CRL feature is enabled. */
- if ((ret == WOLFSSL_SUCCESS) && (options == 0)) {
- /* Disable leaf CRL check. */
- cm->crlEnabled = 0;
- /* Disable all CRL checks. */
- cm->crlCheckAll = 0;
- }
- else
- #endif
- if (ret == WOLFSSL_SUCCESS) {
- #ifndef HAVE_CRL
- /* CRL feature not enabled. */
- ret = NOT_COMPILED_IN;
- #else
- /* Create CRL object if not present. */
- if (cm->crl == NULL) {
- /* Allocate memory for CRL object. */
- cm->crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap,
- DYNAMIC_TYPE_CRL);
- if (cm->crl == NULL) {
- ret = MEMORY_E;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Reset fields of CRL object. */
- XMEMSET(cm->crl, 0, sizeof(WOLFSSL_CRL));
- /* Initialize CRL object. */
- if (InitCRL(cm->crl, cm) != 0) {
- WOLFSSL_MSG("Init CRL failed");
- /* Dispose of CRL object - indicating dynamically allocated.
- */
- FreeCRL(cm->crl, 1);
- cm->crl = NULL;
- ret = WOLFSSL_FAILURE;
- }
- }
- }
- if (ret == WOLFSSL_SUCCESS) {
- #if defined(HAVE_CRL_IO) && defined(USE_WOLFSSL_IO)
- /* Use built-in callback to lookup CRL from URL. */
- cm->crl->crlIOCb = EmbedCrlLookup;
- #endif
- #if defined(OPENSSL_COMPATIBLE_DEFAULTS)
- if ((options & WOLFSSL_CRL_CHECKALL) ||
- (options & WOLFSSL_CRL_CHECK))
- #endif
- {
- /* Enable leaf CRL check. */
- cm->crlEnabled = 1;
- if (options & WOLFSSL_CRL_CHECKALL) {
- /* Enable all CRL check. */
- cm->crlCheckAll = 1;
- }
- }
- }
- #endif
- }
- return ret;
- }
- /* Disables the CRL checks.
- *
- * @param [in] cm Certificate manager.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm is NULL.
- */
- int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerDisableCRL");
- /* Validate parameter. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Disable CRL checking. */
- cm->crlEnabled = 0;
- cm->crlCheckAll = 0;
- }
- return ret;
- }
- #ifdef HAVE_CRL
- /* Load CRL for use.
- *
- * @param [in] cm Certificate manager.
- * @param [in] buff Buffer holding CRL.
- * @param [in] sz Size in bytes of CRL in buffer.
- * @param [in] type Format of encoding. Valid values:
- * WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm or buff is NULL or sz is negative or zero.
- * @return WOLFSSL_FATAL_ERROR when creating CRL object fails.
- */
- int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm,
- const unsigned char* buff, long sz, int type)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLBuffer");
- /* Validate parameters. */
- if ((cm == NULL) || (buff == NULL) || (sz <= 0)) {
- ret = BAD_FUNC_ARG;
- }
- /* Create a CRL object if not available and enable CRL checking. */
- if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
- (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
- WOLFSSL_SUCCESS)) {
- WOLFSSL_MSG("Enable CRL failed");
- ret = WOLFSSL_FATAL_ERROR;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Load CRL into CRL object of the certificate manager. */
- ret = BufferLoadCRL(cm->crl, buff, sz, type, VERIFY);
- }
- return ret;
- }
- /* Free the CRL object of the certificate manager.
- *
- * @param [in] cm Certificate manager.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm is NULL.
- */
- int wolfSSL_CertManagerFreeCRL(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerFreeCRL");
- /* Validate parameter. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- /* Check whether CRL object exists. */
- if ((ret == WOLFSSL_SUCCESS) && (cm->crl != NULL)) {
- /* Dispose of CRL object - indicating dynamically allocated. */
- FreeCRL(cm->crl, 1);
- cm->crl = NULL;
- }
- return ret;
- }
- /* Check DER encoded certificate against CRLs if checking enabled.
- *
- * @param [in] cm Certificate manager.
- * @param [in] der DER encode certificate.
- * @param [in] sz Size in bytes of DER encode certificate.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm or der is NULL or sz is negative or zero.
- * @return MEMORY_E when dynamic memory allocation fails.
- */
- int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm,
- const unsigned char* der, int sz)
- {
- int ret = 0;
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert = NULL;
- #else
- DecodedCert cert[1];
- #endif
- WOLFSSL_ENTER("wolfSSL_CertManagerCheckCRL");
- /* Validate parameters. */
- if ((cm == NULL) || (der == NULL) || (sz <= 0)) {
- ret = BAD_FUNC_ARG;
- }
- /* Check if CRL checking enabled. */
- if ((ret == 0) && cm->crlEnabled) {
- #ifdef WOLFSSL_SMALL_STACK
- /* Allocate memory for decoded certificate. */
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL)
- ret = MEMORY_E;
- if (ret == 0)
- #endif
- {
- /* Initialize decoded certificate with buffer. */
- InitDecodedCert(cert, der, (word32)sz, NULL);
- /* Parse certificate and perform CRL checks. */
- ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_CRL, cm);
- if (ret != 0) {
- WOLFSSL_MSG("ParseCert failed");
- }
- /* Do CRL checks with decoded certificate. */
- else if ((ret = CheckCertCRL(cm->crl, cert)) != 0) {
- WOLFSSL_MSG("CheckCertCRL failed");
- }
- /* Dispose of dynamically allocated memory. */
- FreeDecodedCert(cert);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
- #endif
- }
- }
- return (ret == 0) ? WOLFSSL_SUCCESS : ret;
- }
- /* Set the missing CRL callback.
- *
- * @param [in] cm Certificate manager.
- * @param [in] cb Missing CRL callback.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm is NULL.
- */
- int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, CbMissingCRL cb)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerSetCRL_Cb");
- /* Validate parameters. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Store callback. */
- cm->cbMissingCRL = cb;
- }
- return ret;
- }
- #ifdef HAVE_CRL_IO
- /* Set the CRL I/O callback.
- *
- * @param [in] cm Certificate manager.
- * @param [in] cb CRL I/O callback.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm is NULL.
- */
- int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm, CbCrlIO cb)
- {
- int ret = WOLFSSL_SUCCESS;
- /* Validate parameters. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- if ((ret == WOLFSSL_SUCCESS) && (cm->crl != NULL)) {
- /* Store callback. */
- cm->crl->crlIOCb = cb;
- }
- return ret;
- }
- #endif
- #ifndef NO_FILESYSTEM
- /* Load CRL/s from path with the option of monitoring for changes.
- *
- * @param [in] cm Certificate manager.
- * @param [in] path Path to a directory containing CRLs.
- * @param [in] type Format of encoding. Valid values:
- * WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
- * @param [in] monitor Whether to monitor path for changes to files.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm or path is NULL.
- * @return WOLFSSL_FATAL_ERROR when enabling CRLs fails.
- */
- int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path,
- int type, int monitor)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRL");
- /* Validate parameters. */
- if ((cm == NULL) || (path == NULL)) {
- ret = BAD_FUNC_ARG;
- }
- /* Create a CRL object if not available. */
- if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
- (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
- WOLFSSL_SUCCESS)) {
- WOLFSSL_MSG("Enable CRL failed");
- ret = WOLFSSL_FATAL_ERROR;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Load CRLs from path into CRL object of certificate manager. */
- ret = LoadCRL(cm->crl, path, type, monitor);
- }
- return ret;
- }
- /* Load CRL from file.
- *
- * @param [in] cm Certificate manager.
- * @param [in] file Path to a directory containing CRLs.
- * @param [in] type Format of encoding. Valid values:
- * WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm or file is NULL.
- * @return WOLFSSL_FATAL_ERROR when enabling CRLs fails.
- */
- int wolfSSL_CertManagerLoadCRLFile(WOLFSSL_CERT_MANAGER* cm, const char* file,
- int type)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLFile");
- /* Validate parameters. */
- if ((cm == NULL) || (file == NULL)) {
- ret = BAD_FUNC_ARG;
- }
- /* Create a CRL object if not available. */
- if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
- (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
- WOLFSSL_SUCCESS)) {
- WOLFSSL_MSG("Enable CRL failed");
- ret = WOLFSSL_FATAL_ERROR;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Load CRL file into CRL object of certificate manager. */
- ret = ProcessFile(NULL, file, type, CRL_TYPE, NULL, 0, cm->crl, VERIFY);
- }
- return ret;
- }
- #endif /* !NO_FILESYSTEM */
- #endif /* HAVE_CRL */
- /*******************************************************************************
- * OCSP handling
- ******************************************************************************/
- /* Enables OCSP when validating certificates and sets options.
- *
- * @param [in] cm Certificate manager.
- * @param [in] options Options for using OCSP. Valid flags:
- * WOLFSSL_OCSP_URL_OVERRIDE, WOLFSSL_OCSP_NO_NONCE,
- * WOLFSSL_OCSP_CHECKALL.
- * @return WOLFSSL_SUCCESS on success.
- * @return 0 when initializing the OCSP object fails.
- * @return BAD_FUNC_ARG when cm is NULL.
- * @return MEMORY_E when dynamic memory allocation fails.
- * @return NOT_COMPILED_IN when the OCSP feature is disabled.
- */
- int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
- {
- int ret = WOLFSSL_SUCCESS;
- (void)options;
- WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSP");
- /* Validate parameters. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- #ifndef HAVE_OCSP
- if (ret == WOLFSSL_SUCCESS) {
- /* OCSP feature not enabled. */
- ret = NOT_COMPILED_IN;
- }
- #else
- if (ret == WOLFSSL_SUCCESS) {
- /* Check whether OCSP object is available. */
- if (cm->ocsp == NULL) {
- /* Allocate memory for OCSP object. */
- cm->ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm->heap,
- DYNAMIC_TYPE_OCSP);
- if (cm->ocsp == NULL) {
- ret = MEMORY_E;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Reset the fields of the OCSP object. */
- XMEMSET(cm->ocsp, 0, sizeof(WOLFSSL_OCSP));
- /* Initialize the OCSP object. */
- if (InitOCSP(cm->ocsp, cm) != 0) {
- WOLFSSL_MSG("Init OCSP failed");
- /* Dispose of OCSP object - indicating dynamically allocated.
- */
- FreeOCSP(cm->ocsp, 1);
- cm->ocsp = NULL;
- ret = 0;
- }
- }
- }
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Enable OCSP checking. */
- cm->ocspEnabled = 1;
- /* Enable URL override if requested. */
- if (options & WOLFSSL_OCSP_URL_OVERRIDE) {
- cm->ocspUseOverrideURL = 1;
- }
- /* Set nonce option for creating OCSP requests. */
- cm->ocspSendNonce = (options & WOLFSSL_OCSP_NO_NONCE) !=
- WOLFSSL_OCSP_NO_NONCE;
- /* Set all OCSP checks on if requested. */
- if (options & WOLFSSL_OCSP_CHECKALL) {
- cm->ocspCheckAll = 1;
- }
- #ifndef WOLFSSL_USER_IO
- /* Set built-in OCSP lookup. */
- cm->ocspIOCb = EmbedOcspLookup;
- cm->ocspRespFreeCb = EmbedOcspRespFree;
- cm->ocspIOCtx = cm->heap;
- #endif /* WOLFSSL_USER_IO */
- }
- #endif /* HAVE_OCSP */
- return ret;
- }
- /* Disables the OCSP checks.
- *
- * @param [in] cm Certificate manager.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm is NULL.
- */
- int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSP");
- /* Validate parameter. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Disable use of OCSP with certificate validation. */
- cm->ocspEnabled = 0;
- }
- return ret;
- }
- /* Enables OCSP stapling with certificates in manager.
- *
- * @param [in] cm Certificate manager.
- * @param [in] options Options for using OCSP. Valid flags:
- * WOLFSSL_OCSP_URL_OVERRIDE, WOLFSSL_OCSP_NO_NONCE,
- * WOLFSSL_OCSP_CHECKALL.
- * @return WOLFSSL_SUCCESS on success.
- * @return 0 when initializing the OCSP stapling object fails.
- * @return BAD_FUNC_ARG when cm is NULL.
- * @return MEMORY_E when dynamic memory allocation fails.
- * @return NOT_COMPILED_IN when the OCSP stapling feature is disabled.
- */
- int wolfSSL_CertManagerEnableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPStapling");
- /* Validate parameters. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- #if !defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \
- !defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- if (ret == WOLFSSL_SUCCESS) {
- /* OCSP stapling feature not enabled. */
- ret = NOT_COMPILED_IN;
- }
- #else
- #ifndef NO_WOLFSSL_SERVER
- if (ret == WOLFSSL_SUCCESS) {
- /* Check whether OCSP object is available. */
- if (cm->ocsp_stapling == NULL) {
- /* Allocate memory for OCSP stapling object. */
- cm->ocsp_stapling = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP),
- cm->heap, DYNAMIC_TYPE_OCSP);
- if (cm->ocsp_stapling == NULL) {
- ret = MEMORY_E;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Reset the fields of the OCSP object. */
- XMEMSET(cm->ocsp_stapling, 0, sizeof(WOLFSSL_OCSP));
- /* Initialize the OCSP stapling object. */
- if (InitOCSP(cm->ocsp_stapling, cm) != 0) {
- WOLFSSL_MSG("Init OCSP failed");
- /* Dispose of OCSP stapling object - indicating dynamically
- * allocated. */
- FreeOCSP(cm->ocsp_stapling, 1);
- cm->ocsp_stapling = NULL;
- ret = 0;
- }
- }
- }
- }
- #ifndef WOLFSSL_USER_IO
- if (ret == WOLFSSL_SUCCESS) {
- /* Set built-in OCSP lookup. */
- cm->ocspIOCb = EmbedOcspLookup;
- cm->ocspRespFreeCb = EmbedOcspRespFree;
- cm->ocspIOCtx = cm->heap;
- }
- #endif /* WOLFSSL_USER_IO */
- #endif /* NO_WOLFSSL_SERVER */
- if (ret == WOLFSSL_SUCCESS) {
- /* Enable OCSP stapling. */
- cm->ocspStaplingEnabled = 1;
- }
- #endif /* HAVE_CERTIFICATE_STATUS_REQUEST ||
- * HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
- return ret;
- }
- /* Disables OCSP Stapling.
- *
- * @param [in] cm Certificate manager.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm is NULL.
- */
- int wolfSSL_CertManagerDisableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPStapling");
- /* Validate parameter. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == WOLFSSL_SUCCESS) {
- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
- defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- /* Disable use of OCSP Stapling. */
- cm->ocspStaplingEnabled = 0;
- #else
- /* OCSP stapling feature not enabled. */
- ret = NOT_COMPILED_IN;
- #endif
- }
- return ret;
- }
- /* Enable the must use OCSP Stapling option.
- *
- * @param [in] cm Certificate manager.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm is NULL.
- */
- int wolfSSL_CertManagerEnableOCSPMustStaple(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPMustStaple");
- /* Validate parameter. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == WOLFSSL_SUCCESS) {
- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
- defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- #ifndef NO_WOLFSSL_CLIENT
- /* Enable must use OCSP Stapling option. */
- cm->ocspMustStaple = 1;
- #endif
- #else
- /* OCSP stapling feature not enabled. */
- ret = NOT_COMPILED_IN;
- #endif
- }
- return ret;
- }
- /* Disable the must use OCSP Stapling option.
- *
- * @param [in] cm Certificate manager.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm is NULL.
- */
- int wolfSSL_CertManagerDisableOCSPMustStaple(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPMustStaple");
- /* Validate parameter. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == WOLFSSL_SUCCESS) {
- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
- defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- #ifndef NO_WOLFSSL_CLIENT
- /* Disable must use OCSP Stapling option. */
- cm->ocspMustStaple = 0;
- #endif
- #else
- /* OCSP stapling feature not enabled. */
- ret = NOT_COMPILED_IN;
- #endif
- }
- return ret;
- }
- #ifdef HAVE_OCSP
- /* Check DER encoded certificate against with OCSP if checking enabled.
- *
- * @param [in] cm Certificate manager.
- * @param [in] der DER encode certificate.
- * @param [in] sz Size in bytes of DER encode certificate.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm or der is NULL or sz is negative or 0.
- * @return MEMORY_E when dynamic memory allocation fails.
- */
- int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm,
- const unsigned char* der, int sz)
- {
- int ret = 0;
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert = NULL;
- #else
- DecodedCert cert[1];
- #endif
- WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP");
- /* Validate parameters. */
- if ((cm == NULL) || (der == NULL) || (sz <= 0)) {
- ret = BAD_FUNC_ARG;
- }
- /* Check if OCSP checking enabled. */
- if ((ret == 0) && cm->ocspEnabled) {
- #ifdef WOLFSSL_SMALL_STACK
- /* Allocate memory for decoded certificate. */
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL) {
- ret = MEMORY_E;
- }
- if (ret == 0)
- #endif
- {
- /* Initialize decoded certificate with buffer. */
- InitDecodedCert(cert, der, (word32)sz, NULL);
- /* Parse certificate and perform CRL checks. */
- ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm);
- if (ret != 0) {
- WOLFSSL_MSG("ParseCert failed");
- }
- /* Do OCSP checks with decoded certificate. */
- else if ((ret = CheckCertOCSP(cm->ocsp, cert)) != 0) {
- WOLFSSL_MSG("CheckCertOCSP failed");
- }
- /* Dispose of dynamically allocated memory. */
- FreeDecodedCert(cert);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
- #endif
- }
- }
- return (ret == 0) ? WOLFSSL_SUCCESS : ret;
- }
- /* Check OCSP response.
- *
- * @param [in] cm Certificate manager.
- * @param [in] response Buffer holding OCSP response.
- * @param [in] responseSz Size in bytes of OCSP response.
- * @param [in] responseBuffer Buffer to copy response into.
- * @param [in] status Place to store certificate status.
- * @param [in] entry Place to store OCSP entry.
- * @param [in] ocspRequest OCSP request to match with response.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm or response is NULL.
- */
- int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *cm,
- byte *response, int responseSz, buffer *responseBuffer,
- CertStatus *status, OcspEntry *entry, OcspRequest *ocspRequest)
- {
- int ret = 0;
- WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSPResponse");
- /* Validate parameters. */
- if ((cm == NULL) || (response == NULL)) {
- ret = BAD_FUNC_ARG;
- }
- if ((ret == 0) && cm->ocspEnabled) {
- /* Check OCSP response with OCSP object from certificate manager. */
- ret = CheckOcspResponse(cm->ocsp, response, responseSz, responseBuffer,
- status, entry, ocspRequest, NULL);
- }
- return (ret == 0) ? WOLFSSL_SUCCESS : ret;
- }
- /* Set the OCSP override URL.
- *
- * @param [in] cm Certificate manager.
- * @param [in] url URL to get an OCSP response from.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm is NULL.
- * @return MEMORY_E when dynamic memory allocation fails.
- */
- int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm,
- const char* url)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSPOverrideURL");
- /* Validate parameters. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Dispose of old URL. */
- XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
- if (url != NULL) {
- /* Calculate size of URL string. Include terminator character. */
- int urlSz = (int)XSTRLEN(url) + 1;
- /* Allocate memory for URL to be copied into. */
- cm->ocspOverrideURL = (char*)XMALLOC((size_t)urlSz, cm->heap,
- DYNAMIC_TYPE_URL);
- if (cm->ocspOverrideURL == NULL) {
- ret = MEMORY_E;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Copy URL into certificate manager. */
- XMEMCPY(cm->ocspOverrideURL, url, (size_t)urlSz);
- }
- }
- else {
- /* No URL to set so make it NULL. */
- cm->ocspOverrideURL = NULL;
- }
- }
- return ret;
- }
- /* Set the OCSP I/O callback, OCSP response free callback and related data.
- *
- * @param [in] cm Certificate manager.
- * @param [in] ioCb OCSP callback.
- * @param [in] respFreeCb Callback to free OCSP response buffer.
- * @param [in] ioCbCtx Context data to pass to OCSP callbacks.
- * @return WOLFSSL_SUCCESS on success.
- * @return BAD_FUNC_ARG when cm is NULL.
- */
- int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm, CbOCSPIO ioCb,
- CbOCSPRespFree respFreeCb, void* ioCbCtx)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSP_Cb");
- /* Validate parameters. */
- if (cm == NULL) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Set callbacks and data into certificate manager. */
- cm->ocspIOCb = ioCb;
- cm->ocspRespFreeCb = respFreeCb;
- cm->ocspIOCtx = ioCbCtx;
- }
- return ret;
- }
- #endif /* HAVE_OCSP */
- #endif /* NO_CERTS */
- #endif /* !WOLFSSL_SSL_CERTMAN_INCLUDED */
|