wolf SSL / wolfSSL

Dependents:   CyaSSL-Twitter-OAuth4Tw Example-client-tls-cert TwitterReader TweetTest ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers crl.c Source File

crl.c

00001 /* crl.c
00002  *
00003  * Copyright (C) 2006-2020 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023   /* Name change compatibility layer no longer needs included here */
00024 
00025 #ifdef HAVE_CONFIG_H
00026     #include <config.h>
00027 #endif
00028 
00029 #include <wolfssl/wolfcrypt/settings.h>
00030 
00031 #ifndef WOLFCRYPT_ONLY
00032 #ifdef HAVE_CRL
00033 
00034 #include <wolfssl/internal.h>
00035 #include <wolfssl/error-ssl.h>
00036 
00037 #include <string.h>
00038 
00039 #ifdef HAVE_CRL_MONITOR
00040     #if (defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__))
00041         static int StopMonitor(int mfd);
00042     #else
00043         #error "CRL monitor only currently supported on linux or mach"
00044     #endif
00045 #endif /* HAVE_CRL_MONITOR */
00046 
00047 
00048 /* Initialize CRL members */
00049 int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm)
00050 {
00051     WOLFSSL_ENTER("InitCRL");
00052     if(cm != NULL)
00053         crl->heap = cm->heap;
00054     else
00055         crl->heap = NULL;
00056     crl->cm = cm;
00057     crl->crlList = NULL;
00058     crl->monitors[0].path = NULL;
00059     crl->monitors[1].path = NULL;
00060 #ifdef HAVE_CRL_MONITOR
00061     crl->tid   =  0;
00062     crl->mfd   = -1;    /* mfd for bsd is kqueue fd, eventfd for linux */
00063     crl->setup = 0;     /* thread setup done predicate */
00064     if (pthread_cond_init(&crl->cond, 0) != 0) {
00065         WOLFSSL_MSG("Pthread condition init failed");
00066         return BAD_COND_E;
00067     }
00068 #endif
00069     if (wc_InitMutex(&crl->crlLock) != 0) {
00070         WOLFSSL_MSG("Init Mutex failed");
00071         return BAD_MUTEX_E;
00072     }
00073 
00074     return 0;
00075 }
00076 
00077 
00078 /* Initialize CRL Entry */
00079 static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
00080                          int verified, void* heap)
00081 {
00082     WOLFSSL_ENTER("InitCRL_Entry");
00083 
00084     XMEMCPY(crle->issuerHash, dcrl->issuerHash, CRL_DIGEST_SIZE);
00085     /* XMEMCPY(crle->crlHash, dcrl->crlHash, CRL_DIGEST_SIZE);
00086      * copy the hash here if needed for optimized comparisons */
00087     XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE);
00088     XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE);
00089     crle->lastDateFormat = dcrl->lastDateFormat;
00090     crle->nextDateFormat = dcrl->nextDateFormat;
00091 
00092     crle->certs = dcrl->certs;   /* take ownsership */
00093     dcrl->certs = NULL;
00094     crle->totalCerts = dcrl->totalCerts;
00095     crle->verified = verified;
00096     if (!verified) {
00097         crle->tbsSz = dcrl->sigIndex - dcrl->certBegin;
00098         crle->signatureSz = dcrl->sigLength;
00099         crle->signatureOID = dcrl->signatureOID;
00100         crle->toBeSigned = (byte*)XMALLOC(crle->tbsSz, heap,
00101                                           DYNAMIC_TYPE_CRL_ENTRY);
00102         if (crle->toBeSigned == NULL)
00103             return -1;
00104         crle->signature = (byte*)XMALLOC(crle->signatureSz, heap,
00105                                          DYNAMIC_TYPE_CRL_ENTRY);
00106         if (crle->signature == NULL) {
00107             XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_CRL_ENTRY);
00108             return -1;
00109         }
00110         XMEMCPY(crle->toBeSigned, buff + dcrl->certBegin, crle->tbsSz);
00111         XMEMCPY(crle->signature, dcrl->signature, crle->signatureSz);
00112     #ifndef NO_SKID
00113         crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet;
00114         if (crle->extAuthKeyIdSet)
00115             XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE);
00116     #endif
00117     }
00118     else {
00119         crle->toBeSigned = NULL;
00120         crle->signature = NULL;
00121     }
00122 
00123     (void)verified;
00124     (void)heap;
00125 
00126     return 0;
00127 }
00128 
00129 
00130 /* Free all CRL Entry resources */
00131 static void FreeCRL_Entry(CRL_Entry* crle, void* heap)
00132 {
00133     RevokedCert* tmp = crle->certs;
00134     RevokedCert* next;
00135 
00136     WOLFSSL_ENTER("FreeCRL_Entry");
00137 
00138     while (tmp) {
00139         next = tmp->next;
00140         XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED);
00141         tmp = next;
00142     }
00143     if (crle->signature != NULL)
00144         XFREE(crle->signature, heap, DYNAMIC_TYPE_REVOKED);
00145     if (crle->toBeSigned != NULL)
00146         XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_REVOKED);
00147 
00148     (void)heap;
00149 }
00150 
00151 
00152 
00153 /* Free all CRL resources */
00154 void FreeCRL(WOLFSSL_CRL* crl, int dynamic)
00155 {
00156     CRL_Entry* tmp = crl->crlList;
00157 
00158     WOLFSSL_ENTER("FreeCRL");
00159     if (crl->monitors[0].path)
00160         XFREE(crl->monitors[0].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
00161 
00162     if (crl->monitors[1].path)
00163         XFREE(crl->monitors[1].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
00164 
00165     while(tmp) {
00166         CRL_Entry* next = tmp->next;
00167         FreeCRL_Entry(tmp, crl->heap);
00168         XFREE(tmp, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
00169         tmp = next;
00170     }
00171 
00172 #ifdef HAVE_CRL_MONITOR
00173     if (crl->tid != 0) {
00174         WOLFSSL_MSG("stopping monitor thread");
00175         if (StopMonitor(crl->mfd) == 0)
00176             pthread_join(crl->tid, NULL);
00177         else {
00178             WOLFSSL_MSG("stop monitor failed");
00179         }
00180     }
00181     pthread_cond_destroy(&crl->cond);
00182 #endif
00183     wc_FreeMutex(&crl->crlLock);
00184     if (dynamic)   /* free self */
00185         XFREE(crl, crl->heap, DYNAMIC_TYPE_CRL);
00186 }
00187 
00188 
00189 static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntry)
00190 {
00191     CRL_Entry* crle;
00192     int        foundEntry = 0;
00193     int        ret = 0;
00194 
00195     if (wc_LockMutex(&crl->crlLock) != 0) {
00196         WOLFSSL_MSG("wc_LockMutex failed");
00197         return BAD_MUTEX_E;
00198     }
00199 
00200     crle = crl->crlList;
00201 
00202     while (crle) {
00203         if (XMEMCMP(crle->issuerHash, cert->issuerHash, CRL_DIGEST_SIZE) == 0) {
00204             WOLFSSL_MSG("Found CRL Entry on list");
00205 
00206             if (crle->verified == 0) {
00207                 Signer* ca = NULL;
00208             #ifndef NO_SKID
00209                 byte extAuthKeyId[KEYID_SIZE];
00210             #endif
00211                 byte issuerHash[CRL_DIGEST_SIZE];
00212                 byte* tbs;
00213                 word32 tbsSz = crle->tbsSz;
00214                 byte* sig = NULL;
00215                 word32 sigSz = crle->signatureSz;
00216                 word32 sigOID = crle->signatureOID;
00217                 SignatureCtx sigCtx;
00218 
00219                 tbs = (byte*)XMALLOC(tbsSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
00220                 if (tbs == NULL) {
00221                     wc_UnLockMutex(&crl->crlLock);
00222                     return MEMORY_E;
00223                 }
00224                 sig = (byte*)XMALLOC(sigSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
00225                 if (sig == NULL) {
00226                     XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
00227                     wc_UnLockMutex(&crl->crlLock);
00228                     return MEMORY_E;
00229                 }
00230 
00231                 XMEMCPY(tbs, crle->toBeSigned, tbsSz);
00232                 XMEMCPY(sig, crle->signature, sigSz);
00233             #ifndef NO_SKID
00234                 XMEMCPY(extAuthKeyId, crle->extAuthKeyId,
00235                                                           sizeof(extAuthKeyId));
00236             #endif
00237                 XMEMCPY(issuerHash, crle->issuerHash, sizeof(issuerHash));
00238 
00239                 wc_UnLockMutex(&crl->crlLock);
00240 
00241             #ifndef NO_SKID
00242                 if (crle->extAuthKeyIdSet)
00243                     ca = GetCA(crl->cm, extAuthKeyId);
00244                 if (ca == NULL)
00245                     ca = GetCAByName(crl->cm, issuerHash);
00246             #else /* NO_SKID */
00247                 ca = GetCA(crl->cm, issuerHash);
00248             #endif /* NO_SKID */
00249                 if (ca == NULL) {
00250                     XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
00251                     XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
00252                     WOLFSSL_MSG("Did NOT find CRL issuer CA");
00253                     return ASN_CRL_NO_SIGNER_E;
00254                 }
00255 
00256                 ret = VerifyCRL_Signature(&sigCtx, tbs, tbsSz, sig, sigSz,
00257                                           sigOID, ca, crl->heap);
00258 
00259                 XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
00260                 XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
00261 
00262                 if (wc_LockMutex(&crl->crlLock) != 0) {
00263                     WOLFSSL_MSG("wc_LockMutex failed");
00264                     return BAD_MUTEX_E;
00265                 }
00266 
00267                 crle = crl->crlList;
00268                 while (crle) {
00269                     if (XMEMCMP(crle->issuerHash, cert->issuerHash,
00270                         CRL_DIGEST_SIZE) == 0) {
00271 
00272                         if (ret == 0)
00273                             crle->verified = 1;
00274                         else
00275                             crle->verified = ret;
00276 
00277                         XFREE(crle->toBeSigned, crl->heap,
00278                                                         DYNAMIC_TYPE_CRL_ENTRY);
00279                         crle->toBeSigned = NULL;
00280                         XFREE(crle->signature, crl->heap,
00281                                                         DYNAMIC_TYPE_CRL_ENTRY);
00282                         crle->signature = NULL;
00283                         break;
00284                     }
00285                     crle = crle->next;
00286                 }
00287                 if (crle == NULL || crle->verified < 0)
00288                     break;
00289             }
00290             else if (crle->verified < 0) {
00291                 WOLFSSL_MSG("Cannot use CRL as it didn't verify");
00292                 ret = crle->verified;
00293                 break;
00294             }
00295 
00296             WOLFSSL_MSG("Checking next date validity");
00297 
00298         #ifdef WOLFSSL_NO_CRL_NEXT_DATE
00299             if (crle->nextDateFormat != ASN_OTHER_TYPE)
00300         #endif
00301             {
00302             #ifndef NO_ASN_TIME
00303                 if (!XVALIDATE_DATE(crle->nextDate,crle->nextDateFormat, AFTER)) {
00304                     WOLFSSL_MSG("CRL next date is no longer valid");
00305                     ret = ASN_AFTER_DATE_E;
00306                 }
00307             #endif
00308             }
00309             if (ret == 0) {
00310                 foundEntry = 1;
00311             }
00312             break;
00313         }
00314         crle = crle->next;
00315     }
00316 
00317     if (foundEntry) {
00318         RevokedCert* rc = crle->certs;
00319 
00320         while (rc) {
00321             if (rc->serialSz == cert->serialSz &&
00322                    XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
00323                 WOLFSSL_MSG("Cert revoked");
00324                 ret = CRL_CERT_REVOKED;
00325                 break;
00326             }
00327             rc = rc->next;
00328         }
00329     }
00330 
00331     wc_UnLockMutex(&crl->crlLock);
00332 
00333     *pFoundEntry = foundEntry;
00334 
00335     return ret;
00336 }
00337 
00338 /* Is the cert ok with CRL, return 0 on success */
00339 int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert)
00340 {
00341     int        foundEntry = 0;
00342     int        ret = 0;
00343 
00344     WOLFSSL_ENTER("CheckCertCRL");
00345 
00346     ret = CheckCertCRLList(crl, cert, &foundEntry);
00347 
00348 #ifdef HAVE_CRL_IO
00349     if (foundEntry == 0) {
00350         /* perform embedded lookup */
00351         if (crl->crlIOCb) {
00352             ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo,
00353                                                         cert->extCrlInfoSz);
00354             if (ret == WOLFSSL_CBIO_ERR_WANT_READ) {
00355                 ret = WANT_READ;
00356             }
00357             else if (ret >= 0) {
00358                 /* try again */
00359                 ret = CheckCertCRLList(crl, cert, &foundEntry);
00360             }
00361         }
00362     }
00363 #endif
00364 
00365     if (foundEntry == 0) {
00366         WOLFSSL_MSG("Couldn't find CRL for status check");
00367         ret = CRL_MISSING;
00368 
00369         if (crl->cm->cbMissingCRL) {
00370             char url[256];
00371 
00372             WOLFSSL_MSG("Issuing missing CRL callback");
00373             url[0] = '\0';
00374             if (cert->extCrlInfo) {
00375                 if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) {
00376                     XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz);
00377                     url[cert->extCrlInfoSz] = '\0';
00378                 }
00379                 else  {
00380                     WOLFSSL_MSG("CRL url too long");
00381                 }
00382             }
00383 
00384             crl->cm->cbMissingCRL(url);
00385         }
00386     }
00387 
00388     return ret;
00389 }
00390 
00391 
00392 /* Add Decoded CRL, 0 on success */
00393 static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff,
00394                   int verified)
00395 {
00396     CRL_Entry* crle;
00397 
00398     WOLFSSL_ENTER("AddCRL");
00399 
00400     crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
00401     if (crle == NULL) {
00402         WOLFSSL_MSG("alloc CRL Entry failed");
00403         return -1;
00404     }
00405 
00406     if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) {
00407         WOLFSSL_MSG("Init CRL Entry failed");
00408         XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
00409         return -1;
00410     }
00411 
00412     if (wc_LockMutex(&crl->crlLock) != 0) {
00413         WOLFSSL_MSG("wc_LockMutex failed");
00414         FreeCRL_Entry(crle, crl->heap);
00415         XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
00416         return BAD_MUTEX_E;
00417     }
00418     crle->next = crl->crlList;
00419     crl->crlList = crle;
00420     wc_UnLockMutex(&crl->crlLock);
00421 
00422     return 0;
00423 }
00424 
00425 
00426 /* Load CRL File of type, WOLFSSL_SUCCESS on ok */
00427 int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type,
00428                   int verify)
00429 {
00430     int          ret = WOLFSSL_SUCCESS;
00431     const byte*  myBuffer = buff;    /* if DER ok, otherwise switch */
00432     DerBuffer*   der = NULL;
00433 #ifdef WOLFSSL_SMALL_STACK
00434     DecodedCRL*  dcrl;
00435 #else
00436     DecodedCRL   dcrl[1];
00437 #endif
00438 
00439     WOLFSSL_ENTER("BufferLoadCRL");
00440 
00441     if (crl == NULL || buff == NULL || sz == 0)
00442         return BAD_FUNC_ARG;
00443 
00444     if (type == WOLFSSL_FILETYPE_PEM) {
00445     #ifdef WOLFSSL_PEM_TO_DER
00446         ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, NULL, NULL);
00447         if (ret == 0) {
00448             myBuffer = der->buffer;
00449             sz = der->length;
00450         }
00451         else {
00452             WOLFSSL_MSG("Pem to Der failed");
00453             FreeDer(&der);
00454             return -1;
00455         }
00456     #else
00457         ret = NOT_COMPILED_IN;
00458     #endif
00459     }
00460 
00461 #ifdef WOLFSSL_SMALL_STACK
00462     dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
00463     if (dcrl == NULL) {
00464         FreeDer(&der);
00465         return MEMORY_E;
00466     }
00467 #endif
00468 
00469     InitDecodedCRL(dcrl, crl->heap);
00470     ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm);
00471     if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && verify == NO_VERIFY)) {
00472         WOLFSSL_MSG("ParseCRL error");
00473     }
00474     else {
00475         ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E);
00476         if (ret != 0) {
00477             WOLFSSL_MSG("AddCRL error");
00478         }
00479     }
00480 
00481     FreeDecodedCRL(dcrl);
00482 
00483 #ifdef WOLFSSL_SMALL_STACK
00484     XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00485 #endif
00486 
00487     FreeDer(&der);
00488 
00489     return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */
00490 }
00491 
00492 #if defined(OPENSSL_EXTRA) && defined(HAVE_CRL)
00493 int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newcrl)
00494 {
00495     CRL_Entry   *crle;
00496     WOLFSSL_CRL *crl;
00497 
00498     WOLFSSL_ENTER("wolfSSL_X509_STORE_add_crl");
00499     if (store == NULL || newcrl == NULL)
00500         return BAD_FUNC_ARG;
00501 
00502     crl = store->crl;
00503     crle = newcrl->crlList;
00504 
00505     if (wc_LockMutex(&crl->crlLock) != 0)
00506     {
00507         WOLFSSL_MSG("wc_LockMutex failed");
00508         return BAD_MUTEX_E;
00509     }
00510     crle->next = crl->crlList;
00511     crl->crlList = crle;
00512     newcrl->crlList = NULL;
00513     wc_UnLockMutex(&crl->crlLock);
00514 
00515     WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_crl", WOLFSSL_SUCCESS);
00516 
00517     return WOLFSSL_SUCCESS;
00518 }
00519 #endif
00520 
00521 #ifdef HAVE_CRL_MONITOR
00522 
00523 
00524 /* Signal Monitor thread is setup, save status to setup flag, 0 on success */
00525 static int SignalSetup(WOLFSSL_CRL* crl, int status)
00526 {
00527     int ret;
00528 
00529     /* signal to calling thread we're setup */
00530     if (wc_LockMutex(&crl->crlLock) != 0) {
00531         WOLFSSL_MSG("wc_LockMutex crlLock failed");
00532         return BAD_MUTEX_E;
00533     }
00534 
00535         crl->setup = status;
00536         ret = pthread_cond_signal(&crl->cond);
00537 
00538     wc_UnLockMutex(&crl->crlLock);
00539 
00540     if (ret != 0)
00541         return BAD_COND_E;
00542 
00543     return 0;
00544 }
00545 
00546 
00547 /* read in new CRL entries and save new list */
00548 static int SwapLists(WOLFSSL_CRL* crl)
00549 {
00550     int        ret;
00551     CRL_Entry* newList;
00552 #ifdef WOLFSSL_SMALL_STACK
00553     WOLFSSL_CRL* tmp;
00554 #else
00555     WOLFSSL_CRL tmp[1];
00556 #endif
00557 
00558 #ifdef WOLFSSL_SMALL_STACK
00559     tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
00560     if (tmp == NULL)
00561         return MEMORY_E;
00562 #endif
00563 
00564     if (InitCRL(tmp, crl->cm) < 0) {
00565         WOLFSSL_MSG("Init tmp CRL failed");
00566 #ifdef WOLFSSL_SMALL_STACK
00567         XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00568 #endif
00569         return -1;
00570     }
00571 
00572     if (crl->monitors[0].path) {
00573         ret = LoadCRL(tmp, crl->monitors[0].path, WOLFSSL_FILETYPE_PEM, 0);
00574         if (ret != WOLFSSL_SUCCESS) {
00575             WOLFSSL_MSG("PEM LoadCRL on dir change failed");
00576             FreeCRL(tmp, 0);
00577 #ifdef WOLFSSL_SMALL_STACK
00578             XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00579 #endif
00580             return -1;
00581         }
00582     }
00583 
00584     if (crl->monitors[1].path) {
00585         ret = LoadCRL(tmp, crl->monitors[1].path, WOLFSSL_FILETYPE_ASN1, 0);
00586         if (ret != WOLFSSL_SUCCESS) {
00587             WOLFSSL_MSG("DER LoadCRL on dir change failed");
00588             FreeCRL(tmp, 0);
00589 #ifdef WOLFSSL_SMALL_STACK
00590             XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00591 #endif
00592             return -1;
00593         }
00594     }
00595 
00596     if (wc_LockMutex(&crl->crlLock) != 0) {
00597         WOLFSSL_MSG("wc_LockMutex failed");
00598         FreeCRL(tmp, 0);
00599 #ifdef WOLFSSL_SMALL_STACK
00600         XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00601 #endif
00602         return -1;
00603     }
00604 
00605     newList = tmp->crlList;
00606 
00607     /* swap lists */
00608     tmp->crlList  = crl->crlList;
00609     crl->crlList = newList;
00610 
00611     wc_UnLockMutex(&crl->crlLock);
00612 
00613     FreeCRL(tmp, 0);
00614 
00615 #ifdef WOLFSSL_SMALL_STACK
00616     XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00617 #endif
00618 
00619     return 0;
00620 }
00621 
00622 
00623 #if (defined(__MACH__) || defined(__FreeBSD__))
00624 
00625 #include <sys/types.h>
00626 #include <sys/event.h>
00627 #include <sys/time.h>
00628 #include <fcntl.h>
00629 #include <unistd.h>
00630 
00631 #ifdef __MACH__
00632     #define XEVENT_MODE O_EVTONLY
00633 #elif defined(__FreeBSD__)
00634     #define XEVENT_MODE EVFILT_VNODE
00635 #endif
00636 
00637 
00638 /* we need a unique kqueue user filter fd for crl in case user is doing custom
00639  * events too */
00640 #ifndef CRL_CUSTOM_FD
00641     #define CRL_CUSTOM_FD 123456
00642 #endif
00643 
00644 
00645 /* shutdown monitor thread, 0 on success */
00646 static int StopMonitor(int mfd)
00647 {
00648     struct kevent change;
00649 
00650     /* trigger custom shutdown */
00651     EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL);
00652     if (kevent(mfd, &change, 1, NULL, 0, NULL) < 0) {
00653         WOLFSSL_MSG("kevent trigger customer event failed");
00654         return -1;
00655     }
00656 
00657     return 0;
00658 }
00659 
00660 
00661 /* OS X  monitoring */
00662 static void* DoMonitor(void* arg)
00663 {
00664     int fPEM, fDER;
00665     struct kevent change;
00666 
00667     WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
00668 
00669     WOLFSSL_ENTER("DoMonitor");
00670 
00671     crl->mfd = kqueue();
00672     if (crl->mfd == -1) {
00673         WOLFSSL_MSG("kqueue failed");
00674         SignalSetup(crl, MONITOR_SETUP_E);
00675         return NULL;
00676     }
00677 
00678     /* listen for custom shutdown event */
00679     EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL);
00680     if (kevent(crl->mfd, &change, 1, NULL, 0, NULL) < 0) {
00681         WOLFSSL_MSG("kevent monitor customer event failed");
00682         SignalSetup(crl, MONITOR_SETUP_E);
00683         close(crl->mfd);
00684         return NULL;
00685     }
00686 
00687     fPEM = -1;
00688     fDER = -1;
00689 
00690     if (crl->monitors[0].path) {
00691         fPEM = open(crl->monitors[0].path, XEVENT_MODE);
00692         if (fPEM == -1) {
00693             WOLFSSL_MSG("PEM event dir open failed");
00694             SignalSetup(crl, MONITOR_SETUP_E);
00695             close(crl->mfd);
00696             return NULL;
00697         }
00698     }
00699 
00700     if (crl->monitors[1].path) {
00701         fDER = open(crl->monitors[1].path, XEVENT_MODE);
00702         if (fDER == -1) {
00703             WOLFSSL_MSG("DER event dir open failed");
00704             if (fPEM != -1)
00705                 close(fPEM);
00706             close(crl->mfd);
00707             SignalSetup(crl, MONITOR_SETUP_E);
00708             return NULL;
00709         }
00710     }
00711 
00712     if (fPEM != -1)
00713         EV_SET(&change, fPEM, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
00714                 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
00715 
00716     if (fDER != -1)
00717         EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
00718                 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
00719 
00720     /* signal to calling thread we're setup */
00721     if (SignalSetup(crl, 1) != 0) {
00722         if (fPEM != -1)
00723             close(fPEM);
00724         if (fDER != -1)
00725             close(fDER);
00726         close(crl->mfd);
00727         return NULL;
00728     }
00729 
00730     for (;;) {
00731         struct kevent event;
00732         int           numEvents = kevent(crl->mfd, &change, 1, &event, 1, NULL);
00733 
00734         WOLFSSL_MSG("Got kevent");
00735 
00736         if (numEvents == -1) {
00737             WOLFSSL_MSG("kevent problem, continue");
00738             continue;
00739         }
00740 
00741         if (event.filter == EVFILT_USER) {
00742             WOLFSSL_MSG("Got user shutdown event, breaking out");
00743             break;
00744         }
00745 
00746         if (SwapLists(crl) < 0) {
00747             WOLFSSL_MSG("SwapLists problem, continue");
00748         }
00749     }
00750 
00751     if (fPEM != -1)
00752         close(fPEM);
00753     if (fDER != -1)
00754         close(fDER);
00755 
00756     close(crl->mfd);
00757 
00758     return NULL;
00759 }
00760 
00761 
00762 #elif defined(__linux__)
00763 
00764 #include <sys/types.h>
00765 #include <sys/inotify.h>
00766 #include <sys/eventfd.h>
00767 #include <unistd.h>
00768 
00769 
00770 #ifndef max
00771     static WC_INLINE int max(int a, int b)
00772     {
00773         return a > b ? a : b;
00774     }
00775 #endif /* max */
00776 
00777 
00778 /* shutdown monitor thread, 0 on success */
00779 static int StopMonitor(int mfd)
00780 {
00781     word64 w64 = 1;
00782 
00783     /* write to our custom event */
00784     if (write(mfd, &w64, sizeof(w64)) < 0) {
00785         WOLFSSL_MSG("StopMonitor write failed");
00786         return -1;
00787     }
00788 
00789     return 0;
00790 }
00791 
00792 
00793 /* linux monitoring */
00794 static void* DoMonitor(void* arg)
00795 {
00796     int         notifyFd;
00797     int         wd  = -1;
00798     WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
00799 #ifdef WOLFSSL_SMALL_STACK
00800     char*       buff;
00801 #else
00802     char        buff[8192];
00803 #endif
00804 
00805     WOLFSSL_ENTER("DoMonitor");
00806 
00807     crl->mfd = eventfd(0, 0);  /* our custom shutdown event */
00808     if (crl->mfd < 0) {
00809         WOLFSSL_MSG("eventfd failed");
00810         SignalSetup(crl, MONITOR_SETUP_E);
00811         return NULL;
00812     }
00813 
00814     notifyFd = inotify_init();
00815     if (notifyFd < 0) {
00816         WOLFSSL_MSG("inotify failed");
00817         close(crl->mfd);
00818         SignalSetup(crl, MONITOR_SETUP_E);
00819         return NULL;
00820     }
00821 
00822     if (crl->monitors[0].path) {
00823         wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE |
00824                                                                 IN_DELETE);
00825         if (wd < 0) {
00826             WOLFSSL_MSG("PEM notify add watch failed");
00827             close(crl->mfd);
00828             close(notifyFd);
00829             SignalSetup(crl, MONITOR_SETUP_E);
00830             return NULL;
00831         }
00832     }
00833 
00834     if (crl->monitors[1].path) {
00835         wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE |
00836                                                                 IN_DELETE);
00837         if (wd < 0) {
00838             WOLFSSL_MSG("DER notify add watch failed");
00839             close(crl->mfd);
00840             close(notifyFd);
00841             SignalSetup(crl, MONITOR_SETUP_E);
00842             return NULL;
00843         }
00844     }
00845 
00846 #ifdef WOLFSSL_SMALL_STACK
00847     buff = (char*)XMALLOC(8192, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00848     if (buff == NULL)
00849         return NULL;
00850 #endif
00851 
00852     /* signal to calling thread we're setup */
00853     if (SignalSetup(crl, 1) != 0) {
00854         #ifdef WOLFSSL_SMALL_STACK
00855             XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00856         #endif
00857 
00858         if (wd > 0)
00859             inotify_rm_watch(notifyFd, wd);
00860         close(crl->mfd);
00861         close(notifyFd);
00862         return NULL;
00863     }
00864 
00865     for (;;) {
00866         fd_set readfds;
00867         int    result;
00868         int    length;
00869 
00870         FD_ZERO(&readfds);
00871         FD_SET(notifyFd, &readfds);
00872         FD_SET(crl->mfd, &readfds);
00873 
00874         result = select(max(notifyFd, crl->mfd) + 1, &readfds, NULL, NULL,NULL);
00875 
00876         WOLFSSL_MSG("Got notify event");
00877 
00878         if (result < 0) {
00879             WOLFSSL_MSG("select problem, continue");
00880             continue;
00881         }
00882 
00883         if (FD_ISSET(crl->mfd, &readfds)) {
00884             WOLFSSL_MSG("got custom shutdown event, breaking out");
00885             break;
00886         }
00887 
00888         length = (int) read(notifyFd, buff, 8192);
00889         if (length < 0) {
00890             WOLFSSL_MSG("notify read problem, continue");
00891             continue;
00892         }
00893 
00894         if (SwapLists(crl) < 0) {
00895             WOLFSSL_MSG("SwapLists problem, continue");
00896         }
00897     }
00898 
00899 #ifdef WOLFSSL_SMALL_STACK
00900     XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00901 #endif
00902 
00903     if (wd > 0)
00904         inotify_rm_watch(notifyFd, wd);
00905     close(crl->mfd);
00906     close(notifyFd);
00907 
00908     return NULL;
00909 }
00910 
00911 #endif /* MACH or linux */
00912 
00913 
00914 /* Start Monitoring the CRL path(s) in a thread */
00915 static int StartMonitorCRL(WOLFSSL_CRL* crl)
00916 {
00917     int ret = WOLFSSL_SUCCESS;
00918 
00919     WOLFSSL_ENTER("StartMonitorCRL");
00920 
00921     if (crl == NULL)
00922         return BAD_FUNC_ARG;
00923 
00924     if (crl->tid != 0) {
00925         WOLFSSL_MSG("Monitor thread already running");
00926         return ret;  /* that's ok, someone already started */
00927     }
00928 
00929     if (pthread_create(&crl->tid, NULL, DoMonitor, crl) != 0) {
00930         WOLFSSL_MSG("Thread creation error");
00931         return THREAD_CREATE_E;
00932     }
00933 
00934     /* wait for setup to complete */
00935     if (wc_LockMutex(&crl->crlLock) != 0) {
00936         WOLFSSL_MSG("wc_LockMutex crlLock error");
00937         return BAD_MUTEX_E;
00938     }
00939 
00940         while (crl->setup == 0) {
00941             if (pthread_cond_wait(&crl->cond, &crl->crlLock) != 0) {
00942                 ret = BAD_COND_E;
00943                 break;
00944             }
00945         }
00946 
00947         if (crl->setup < 0)
00948             ret = crl->setup;  /* store setup error */
00949 
00950     wc_UnLockMutex(&crl->crlLock);
00951 
00952     if (ret < 0) {
00953         WOLFSSL_MSG("DoMonitor setup failure");
00954         crl->tid = 0;  /* thread already done */
00955     }
00956 
00957     return ret;
00958 }
00959 
00960 
00961 #else /* HAVE_CRL_MONITOR */
00962 
00963 #ifndef NO_FILESYSTEM
00964 
00965 static int StartMonitorCRL(WOLFSSL_CRL* crl)
00966 {
00967     (void)crl;
00968 
00969     WOLFSSL_ENTER("StartMonitorCRL");
00970     WOLFSSL_MSG("Not compiled in");
00971 
00972     return NOT_COMPILED_IN;
00973 }
00974 
00975 #endif /* NO_FILESYSTEM */
00976 
00977 #endif  /* HAVE_CRL_MONITOR */
00978 
00979 #if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
00980 
00981 /* Load CRL path files of type, WOLFSSL_SUCCESS on ok */
00982 int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
00983 {
00984     int         ret = WOLFSSL_SUCCESS;
00985     char*       name = NULL;
00986 #ifdef WOLFSSL_SMALL_STACK
00987     ReadDirCtx* readCtx = NULL;
00988 #else
00989     ReadDirCtx  readCtx[1];
00990 #endif
00991 
00992     WOLFSSL_ENTER("LoadCRL");
00993     if (crl == NULL)
00994         return BAD_FUNC_ARG;
00995 
00996 #ifdef WOLFSSL_SMALL_STACK
00997     readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), crl->heap,
00998                                                        DYNAMIC_TYPE_TMP_BUFFER);
00999     if (readCtx == NULL)
01000         return MEMORY_E;
01001 #endif
01002 
01003     /* try to load each regular file in path */
01004     ret = wc_ReadDirFirst(readCtx, path, &name);
01005     while (ret == 0 && name) {
01006         int skip = 0;
01007         if (type == WOLFSSL_FILETYPE_PEM) {
01008             if (XSTRSTR(name, ".pem") == NULL) {
01009                 WOLFSSL_MSG("not .pem file, skipping");
01010                 skip = 1;
01011             }
01012         }
01013         else {
01014             if (XSTRSTR(name, ".der") == NULL &&
01015                 XSTRSTR(name, ".crl") == NULL)
01016             {
01017                 WOLFSSL_MSG("not .der or .crl file, skipping");
01018                 skip = 1;
01019             }
01020         }
01021 
01022         if (!skip && ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl,
01023                                  VERIFY) != WOLFSSL_SUCCESS) {
01024             WOLFSSL_MSG("CRL file load failed, continuing");
01025         }
01026 
01027         ret = wc_ReadDirNext(readCtx, path, &name);
01028     }
01029     wc_ReadDirClose(readCtx);
01030     ret = WOLFSSL_SUCCESS; /* load failures not reported, for backwards compat */
01031 
01032 #ifdef WOLFSSL_SMALL_STACK
01033     XFREE(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
01034 #endif
01035 
01036     if (monitor & WOLFSSL_CRL_MONITOR) {
01037         word32 pathLen;
01038         char* pathBuf;
01039 
01040         WOLFSSL_MSG("monitor path requested");
01041 
01042         pathLen = (word32)XSTRLEN(path);
01043         pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR);
01044         if (pathBuf) {
01045             XSTRNCPY(pathBuf, path, pathLen+1);
01046 
01047             if (type == WOLFSSL_FILETYPE_PEM) {
01048                 /* free old path before setting a new one */
01049                 if (crl->monitors[0].path) {
01050                     XFREE(crl->monitors[0].path, crl->heap,
01051                             DYNAMIC_TYPE_CRL_MONITOR);
01052                 }
01053                 crl->monitors[0].path = pathBuf;
01054                 crl->monitors[0].type = WOLFSSL_FILETYPE_PEM;
01055             } else {
01056                 /* free old path before setting a new one */
01057                 if (crl->monitors[1].path) {
01058                     XFREE(crl->monitors[1].path, crl->heap,
01059                             DYNAMIC_TYPE_CRL_MONITOR);
01060                 }
01061                 crl->monitors[1].path = pathBuf;
01062                 crl->monitors[1].type = WOLFSSL_FILETYPE_ASN1;
01063             }
01064 
01065             if (monitor & WOLFSSL_CRL_START_MON) {
01066                 WOLFSSL_MSG("start monitoring requested");
01067 
01068                 ret = StartMonitorCRL(crl);
01069             }
01070         }
01071         else {
01072             ret = MEMORY_E;
01073         }
01074     }
01075 
01076     return ret;
01077 }
01078 
01079 #else
01080 int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
01081 {
01082     (void)crl;
01083     (void)path;
01084     (void)type;
01085     (void)monitor;
01086 
01087     /* stub for scenario where file system is not supported */
01088     return NOT_COMPILED_IN;
01089 }
01090 #endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */
01091 
01092 #endif /* HAVE_CRL */
01093 #endif /* !WOLFCRYPT_ONLY */
01094