diff options
Diffstat (limited to 'FreeRTOS-Plus/Source/WolfSSL/src/crl.c')
-rw-r--r-- | FreeRTOS-Plus/Source/WolfSSL/src/crl.c | 651 |
1 files changed, 477 insertions, 174 deletions
diff --git a/FreeRTOS-Plus/Source/WolfSSL/src/crl.c b/FreeRTOS-Plus/Source/WolfSSL/src/crl.c index 0f47ee1a4..a48cf9d83 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/src/crl.c +++ b/FreeRTOS-Plus/Source/WolfSSL/src/crl.c @@ -1,8 +1,8 @@ /* crl.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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-1301, USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* Name change compatibility layer no longer needs included here */ #ifdef HAVE_CONFIG_H @@ -27,48 +28,62 @@ #include <wolfssl/wolfcrypt/settings.h> +#ifndef WOLFCRYPT_ONLY #ifdef HAVE_CRL #include <wolfssl/internal.h> #include <wolfssl/error-ssl.h> -#include <dirent.h> -#include <sys/stat.h> #include <string.h> #ifdef HAVE_CRL_MONITOR - static int StopMonitor(int mfd); -#endif + #if (defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__)) + static int StopMonitor(int mfd); + #else + #error "CRL monitor only currently supported on linux or mach" + #endif +#endif /* HAVE_CRL_MONITOR */ -/* Initialze CRL members */ +/* Initialize CRL members */ int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm) { WOLFSSL_ENTER("InitCRL"); - + if(cm != NULL) + crl->heap = cm->heap; + else + crl->heap = NULL; crl->cm = cm; crl->crlList = NULL; crl->monitors[0].path = NULL; crl->monitors[1].path = NULL; #ifdef HAVE_CRL_MONITOR - crl->tid = 0; - crl->mfd = -1; /* mfd for bsd is kqueue fd, eventfd for linux */ + crl->tid = 0; + crl->mfd = -1; /* mfd for bsd is kqueue fd, eventfd for linux */ + crl->setup = 0; /* thread setup done predicate */ + if (pthread_cond_init(&crl->cond, 0) != 0) { + WOLFSSL_MSG("Pthread condition init failed"); + return BAD_COND_E; + } #endif - if (InitMutex(&crl->crlLock) != 0) - return BAD_MUTEX_E; + if (wc_InitMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("Init Mutex failed"); + return BAD_MUTEX_E; + } return 0; } -/* Initialze CRL Entry */ -static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl) +/* Initialize CRL Entry */ +static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff, + int verified, void* heap) { WOLFSSL_ENTER("InitCRL_Entry"); XMEMCPY(crle->issuerHash, dcrl->issuerHash, CRL_DIGEST_SIZE); /* XMEMCPY(crle->crlHash, dcrl->crlHash, CRL_DIGEST_SIZE); - * copy the hash here if needed for optimized comparisons */ + * copy the hash here if needed for optimized comparisons */ XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE); XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE); crle->lastDateFormat = dcrl->lastDateFormat; @@ -77,23 +92,60 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl) crle->certs = dcrl->certs; /* take ownsership */ dcrl->certs = NULL; crle->totalCerts = dcrl->totalCerts; + crle->verified = verified; + if (!verified) { + crle->tbsSz = dcrl->sigIndex - dcrl->certBegin; + crle->signatureSz = dcrl->sigLength; + crle->signatureOID = dcrl->signatureOID; + crle->toBeSigned = (byte*)XMALLOC(crle->tbsSz, heap, + DYNAMIC_TYPE_CRL_ENTRY); + if (crle->toBeSigned == NULL) + return -1; + crle->signature = (byte*)XMALLOC(crle->signatureSz, heap, + DYNAMIC_TYPE_CRL_ENTRY); + if (crle->signature == NULL) { + XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_CRL_ENTRY); + return -1; + } + XMEMCPY(crle->toBeSigned, buff + dcrl->certBegin, crle->tbsSz); + XMEMCPY(crle->signature, dcrl->signature, crle->signatureSz); + #ifndef NO_SKID + crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet; + if (crle->extAuthKeyIdSet) + XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE); + #endif + } + else { + crle->toBeSigned = NULL; + crle->signature = NULL; + } + + (void)verified; + (void)heap; return 0; } /* Free all CRL Entry resources */ -static void FreeCRL_Entry(CRL_Entry* crle) +static void FreeCRL_Entry(CRL_Entry* crle, void* heap) { - RevokedCert* tmp = crle->certs; + RevokedCert* tmp = crle->certs; + RevokedCert* next; WOLFSSL_ENTER("FreeCRL_Entry"); - while(tmp) { - RevokedCert* next = tmp->next; - XFREE(tmp, NULL, DYNAMIC_TYPE_REVOKED); + while (tmp) { + next = tmp->next; + XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED); tmp = next; } + if (crle->signature != NULL) + XFREE(crle->signature, heap, DYNAMIC_TYPE_REVOKED); + if (crle->toBeSigned != NULL) + XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_REVOKED); + + (void)heap; } @@ -104,19 +156,18 @@ void FreeCRL(WOLFSSL_CRL* crl, int dynamic) CRL_Entry* tmp = crl->crlList; WOLFSSL_ENTER("FreeCRL"); - if (crl->monitors[0].path) - XFREE(crl->monitors[0].path, NULL, DYNAMIC_TYPE_CRL_MONITOR); + XFREE(crl->monitors[0].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR); if (crl->monitors[1].path) - XFREE(crl->monitors[1].path, NULL, DYNAMIC_TYPE_CRL_MONITOR); + XFREE(crl->monitors[1].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR); while(tmp) { CRL_Entry* next = tmp->next; - FreeCRL_Entry(tmp); - XFREE(tmp, NULL, DYNAMIC_TYPE_CRL_ENTRY); + FreeCRL_Entry(tmp, crl->heap); + XFREE(tmp, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); tmp = next; - } + } #ifdef HAVE_CRL_MONITOR if (crl->tid != 0) { @@ -124,28 +175,25 @@ void FreeCRL(WOLFSSL_CRL* crl, int dynamic) if (StopMonitor(crl->mfd) == 0) pthread_join(crl->tid, NULL); else { - WOLFSSL_MSG("stop monitor failed, cancel instead"); - pthread_cancel(crl->tid); + WOLFSSL_MSG("stop monitor failed"); } } + pthread_cond_destroy(&crl->cond); #endif - FreeMutex(&crl->crlLock); + wc_FreeMutex(&crl->crlLock); if (dynamic) /* free self */ - XFREE(crl, NULL, DYNAMIC_TYPE_CRL); + XFREE(crl, crl->heap, DYNAMIC_TYPE_CRL); } -/* Is the cert ok with CRL, return 0 on success */ -int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) +static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntry) { CRL_Entry* crle; int foundEntry = 0; int ret = 0; - WOLFSSL_ENTER("CheckCertCRL"); - - if (LockMutex(&crl->crlLock) != 0) { - WOLFSSL_MSG("LockMutex failed"); + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); return BAD_MUTEX_E; } @@ -154,14 +202,113 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) while (crle) { if (XMEMCMP(crle->issuerHash, cert->issuerHash, CRL_DIGEST_SIZE) == 0) { WOLFSSL_MSG("Found CRL Entry on list"); + + if (crle->verified == 0) { + Signer* ca = NULL; + #ifndef NO_SKID + byte extAuthKeyId[KEYID_SIZE]; + #endif + byte issuerHash[CRL_DIGEST_SIZE]; + byte* tbs; + word32 tbsSz = crle->tbsSz; + byte* sig = NULL; + word32 sigSz = crle->signatureSz; + word32 sigOID = crle->signatureOID; + SignatureCtx sigCtx; + + tbs = (byte*)XMALLOC(tbsSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + if (tbs == NULL) { + wc_UnLockMutex(&crl->crlLock); + return MEMORY_E; + } + sig = (byte*)XMALLOC(sigSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + if (sig == NULL) { + XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + wc_UnLockMutex(&crl->crlLock); + return MEMORY_E; + } + + XMEMCPY(tbs, crle->toBeSigned, tbsSz); + XMEMCPY(sig, crle->signature, sigSz); + #ifndef NO_SKID + XMEMCPY(extAuthKeyId, crle->extAuthKeyId, + sizeof(extAuthKeyId)); + #endif + XMEMCPY(issuerHash, crle->issuerHash, sizeof(issuerHash)); + + wc_UnLockMutex(&crl->crlLock); + + #ifndef NO_SKID + if (crle->extAuthKeyIdSet) + ca = GetCA(crl->cm, extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(crl->cm, issuerHash); + #else /* NO_SKID */ + ca = GetCA(crl->cm, issuerHash); + #endif /* NO_SKID */ + if (ca == NULL) { + XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + WOLFSSL_MSG("Did NOT find CRL issuer CA"); + return ASN_CRL_NO_SIGNER_E; + } + + ret = VerifyCRL_Signature(&sigCtx, tbs, tbsSz, sig, sigSz, + sigOID, ca, crl->heap); + + XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); + return BAD_MUTEX_E; + } + + crle = crl->crlList; + while (crle) { + if (XMEMCMP(crle->issuerHash, cert->issuerHash, + CRL_DIGEST_SIZE) == 0) { + + if (ret == 0) + crle->verified = 1; + else + crle->verified = ret; + + XFREE(crle->toBeSigned, crl->heap, + DYNAMIC_TYPE_CRL_ENTRY); + crle->toBeSigned = NULL; + XFREE(crle->signature, crl->heap, + DYNAMIC_TYPE_CRL_ENTRY); + crle->signature = NULL; + break; + } + crle = crle->next; + } + if (crle == NULL || crle->verified < 0) + break; + } + else if (crle->verified < 0) { + WOLFSSL_MSG("Cannot use CRL as it didn't verify"); + ret = crle->verified; + break; + } + WOLFSSL_MSG("Checking next date validity"); - if (!ValidateDate(crle->nextDate, crle->nextDateFormat, AFTER)) { - WOLFSSL_MSG("CRL next date is no longer valid"); - ret = ASN_AFTER_DATE_E; + #ifdef WOLFSSL_NO_CRL_NEXT_DATE + if (crle->nextDateFormat != ASN_OTHER_TYPE) + #endif + { + #ifndef NO_ASN_TIME + if (!XVALIDATE_DATE(crle->nextDate,crle->nextDateFormat, AFTER)) { + WOLFSSL_MSG("CRL next date is no longer valid"); + ret = ASN_AFTER_DATE_E; + } + #endif } - else + if (ret == 0) { foundEntry = 1; + } break; } crle = crle->next; @@ -171,126 +318,161 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) RevokedCert* rc = crle->certs; while (rc) { - if (XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) { + if (rc->serialSz == cert->serialSz && + XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) { WOLFSSL_MSG("Cert revoked"); ret = CRL_CERT_REVOKED; break; } - rc = rc->next; + rc = rc->next; } } - UnLockMutex(&crl->crlLock); + wc_UnLockMutex(&crl->crlLock); + + *pFoundEntry = foundEntry; + + return ret; +} + +/* Is the cert ok with CRL, return 0 on success */ +int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) +{ + int foundEntry = 0; + int ret = 0; + + WOLFSSL_ENTER("CheckCertCRL"); + + ret = CheckCertCRLList(crl, cert, &foundEntry); + +#ifdef HAVE_CRL_IO + if (foundEntry == 0) { + /* perform embedded lookup */ + if (crl->crlIOCb) { + ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo, + cert->extCrlInfoSz); + if (ret == WOLFSSL_CBIO_ERR_WANT_READ) { + ret = WANT_READ; + } + else if (ret >= 0) { + /* try again */ + ret = CheckCertCRLList(crl, cert, &foundEntry); + } + } + } +#endif if (foundEntry == 0) { WOLFSSL_MSG("Couldn't find CRL for status check"); ret = CRL_MISSING; + if (crl->cm->cbMissingCRL) { char url[256]; WOLFSSL_MSG("Issuing missing CRL callback"); url[0] = '\0'; - if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) { - XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz); - url[cert->extCrlInfoSz] = '\0'; - } - else { - WOLFSSL_MSG("CRL url too long"); + if (cert->extCrlInfo) { + if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) { + XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz); + url[cert->extCrlInfoSz] = '\0'; + } + else { + WOLFSSL_MSG("CRL url too long"); + } } + crl->cm->cbMissingCRL(url); } } - - return ret; + return ret; } /* Add Decoded CRL, 0 on success */ -static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl) +static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff, + int verified) { CRL_Entry* crle; WOLFSSL_ENTER("AddCRL"); - crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), NULL, DYNAMIC_TYPE_CRL_ENTRY); + crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), crl->heap, DYNAMIC_TYPE_CRL_ENTRY); if (crle == NULL) { WOLFSSL_MSG("alloc CRL Entry failed"); return -1; } - if (InitCRL_Entry(crle, dcrl) < 0) { + if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) { WOLFSSL_MSG("Init CRL Entry failed"); - XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY); + XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); return -1; } - if (LockMutex(&crl->crlLock) != 0) { - WOLFSSL_MSG("LockMutex failed"); - FreeCRL_Entry(crle); - XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY); + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); + FreeCRL_Entry(crle, crl->heap); + XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); return BAD_MUTEX_E; } crle->next = crl->crlList; crl->crlList = crle; - UnLockMutex(&crl->crlLock); + wc_UnLockMutex(&crl->crlLock); return 0; } -/* Load CRL File of type, SSL_SUCCESS on ok */ -int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type) +/* Load CRL File of type, WOLFSSL_SUCCESS on ok */ +int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type, + int verify) { - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; const byte* myBuffer = buff; /* if DER ok, otherwise switch */ - buffer der; + DerBuffer* der = NULL; #ifdef WOLFSSL_SMALL_STACK DecodedCRL* dcrl; #else DecodedCRL dcrl[1]; #endif - der.buffer = NULL; - WOLFSSL_ENTER("BufferLoadCRL"); if (crl == NULL || buff == NULL || sz == 0) return BAD_FUNC_ARG; - if (type == SSL_FILETYPE_PEM) { - int eccKey = 0; /* not used */ - EncryptedInfo info; - info.ctx = NULL; - - ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, &info, &eccKey); + if (type == WOLFSSL_FILETYPE_PEM) { + #ifdef WOLFSSL_PEM_TO_DER + ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, NULL, NULL); if (ret == 0) { - myBuffer = der.buffer; - sz = der.length; + myBuffer = der->buffer; + sz = der->length; } else { WOLFSSL_MSG("Pem to Der failed"); + FreeDer(&der); return -1; } + #else + ret = NOT_COMPILED_IN; + #endif } #ifdef WOLFSSL_SMALL_STACK dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (dcrl == NULL) { - if (der.buffer) - XFREE(der.buffer, NULL, DYNAMIC_TYPE_CRL); - + FreeDer(&der); return MEMORY_E; } #endif - InitDecodedCRL(dcrl); + InitDecodedCRL(dcrl, crl->heap); ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm); - if (ret != 0) { + if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && verify == NO_VERIFY)) { WOLFSSL_MSG("ParseCRL error"); } else { - ret = AddCRL(crl, dcrl); + ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E); if (ret != 0) { WOLFSSL_MSG("AddCRL error"); } @@ -302,32 +484,82 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type) XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - if (der.buffer) - XFREE(der.buffer, NULL, DYNAMIC_TYPE_CRL); + FreeDer(&der); - return ret ? ret : SSL_SUCCESS; /* convert 0 to SSL_SUCCESS */ + return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */ } +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) +int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newcrl) +{ + CRL_Entry *crle; + WOLFSSL_CRL *crl; + + WOLFSSL_ENTER("wolfSSL_X509_STORE_add_crl"); + if (store == NULL || newcrl == NULL) + return BAD_FUNC_ARG; + + crl = store->crl; + crle = newcrl->crlList; + + if (wc_LockMutex(&crl->crlLock) != 0) + { + WOLFSSL_MSG("wc_LockMutex failed"); + return BAD_MUTEX_E; + } + crle->next = crl->crlList; + crl->crlList = crle; + newcrl->crlList = NULL; + wc_UnLockMutex(&crl->crlLock); + + WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_crl", WOLFSSL_SUCCESS); + + return WOLFSSL_SUCCESS; +} +#endif #ifdef HAVE_CRL_MONITOR +/* Signal Monitor thread is setup, save status to setup flag, 0 on success */ +static int SignalSetup(WOLFSSL_CRL* crl, int status) +{ + int ret; + + /* signal to calling thread we're setup */ + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex crlLock failed"); + return BAD_MUTEX_E; + } + + crl->setup = status; + ret = pthread_cond_signal(&crl->cond); + + wc_UnLockMutex(&crl->crlLock); + + if (ret != 0) + return BAD_COND_E; + + return 0; +} + + /* read in new CRL entries and save new list */ static int SwapLists(WOLFSSL_CRL* crl) { int ret; CRL_Entry* newList; #ifdef WOLFSSL_SMALL_STACK - WOLFSSL_CRL* tmp; + WOLFSSL_CRL* tmp; #else WOLFSSL_CRL tmp[1]; #endif - + #ifdef WOLFSSL_SMALL_STACK tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) return MEMORY_E; -#endif +#endif if (InitCRL(tmp, crl->cm) < 0) { WOLFSSL_MSG("Init tmp CRL failed"); @@ -338,8 +570,8 @@ static int SwapLists(WOLFSSL_CRL* crl) } if (crl->monitors[0].path) { - ret = LoadCRL(tmp, crl->monitors[0].path, SSL_FILETYPE_PEM, 0); - if (ret != SSL_SUCCESS) { + ret = LoadCRL(tmp, crl->monitors[0].path, WOLFSSL_FILETYPE_PEM, 0); + if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("PEM LoadCRL on dir change failed"); FreeCRL(tmp, 0); #ifdef WOLFSSL_SMALL_STACK @@ -350,8 +582,8 @@ static int SwapLists(WOLFSSL_CRL* crl) } if (crl->monitors[1].path) { - ret = LoadCRL(tmp, crl->monitors[1].path, SSL_FILETYPE_ASN1, 0); - if (ret != SSL_SUCCESS) { + ret = LoadCRL(tmp, crl->monitors[1].path, WOLFSSL_FILETYPE_ASN1, 0); + if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("DER LoadCRL on dir change failed"); FreeCRL(tmp, 0); #ifdef WOLFSSL_SMALL_STACK @@ -361,8 +593,8 @@ static int SwapLists(WOLFSSL_CRL* crl) } } - if (LockMutex(&crl->crlLock) != 0) { - WOLFSSL_MSG("LockMutex failed"); + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); FreeCRL(tmp, 0); #ifdef WOLFSSL_SMALL_STACK XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -376,7 +608,7 @@ static int SwapLists(WOLFSSL_CRL* crl) tmp->crlList = crl->crlList; crl->crlList = newList; - UnLockMutex(&crl->crlLock); + wc_UnLockMutex(&crl->crlLock); FreeCRL(tmp, 0); @@ -439,6 +671,7 @@ static void* DoMonitor(void* arg) crl->mfd = kqueue(); if (crl->mfd == -1) { WOLFSSL_MSG("kqueue failed"); + SignalSetup(crl, MONITOR_SETUP_E); return NULL; } @@ -446,6 +679,7 @@ static void* DoMonitor(void* arg) EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL); if (kevent(crl->mfd, &change, 1, NULL, 0, NULL) < 0) { WOLFSSL_MSG("kevent monitor customer event failed"); + SignalSetup(crl, MONITOR_SETUP_E); close(crl->mfd); return NULL; } @@ -457,6 +691,7 @@ static void* DoMonitor(void* arg) fPEM = open(crl->monitors[0].path, XEVENT_MODE); if (fPEM == -1) { WOLFSSL_MSG("PEM event dir open failed"); + SignalSetup(crl, MONITOR_SETUP_E); close(crl->mfd); return NULL; } @@ -466,7 +701,10 @@ static void* DoMonitor(void* arg) fDER = open(crl->monitors[1].path, XEVENT_MODE); if (fDER == -1) { WOLFSSL_MSG("DER event dir open failed"); + if (fPEM != -1) + close(fPEM); close(crl->mfd); + SignalSetup(crl, MONITOR_SETUP_E); return NULL; } } @@ -479,10 +717,20 @@ static void* DoMonitor(void* arg) EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0); + /* signal to calling thread we're setup */ + if (SignalSetup(crl, 1) != 0) { + if (fPEM != -1) + close(fPEM); + if (fDER != -1) + close(fDER); + close(crl->mfd); + return NULL; + } + for (;;) { struct kevent event; int numEvents = kevent(crl->mfd, &change, 1, &event, 1, NULL); - + WOLFSSL_MSG("Got kevent"); if (numEvents == -1) { @@ -520,7 +768,7 @@ static void* DoMonitor(void* arg) #ifndef max - static INLINE int max(int a, int b) + static WC_INLINE int max(int a, int b) { return a > b ? a : b; } @@ -559,6 +807,7 @@ static void* DoMonitor(void* arg) crl->mfd = eventfd(0, 0); /* our custom shutdown event */ if (crl->mfd < 0) { WOLFSSL_MSG("eventfd failed"); + SignalSetup(crl, MONITOR_SETUP_E); return NULL; } @@ -566,6 +815,7 @@ static void* DoMonitor(void* arg) if (notifyFd < 0) { WOLFSSL_MSG("inotify failed"); close(crl->mfd); + SignalSetup(crl, MONITOR_SETUP_E); return NULL; } @@ -576,6 +826,7 @@ static void* DoMonitor(void* arg) WOLFSSL_MSG("PEM notify add watch failed"); close(crl->mfd); close(notifyFd); + SignalSetup(crl, MONITOR_SETUP_E); return NULL; } } @@ -587,6 +838,7 @@ static void* DoMonitor(void* arg) WOLFSSL_MSG("DER notify add watch failed"); close(crl->mfd); close(notifyFd); + SignalSetup(crl, MONITOR_SETUP_E); return NULL; } } @@ -597,6 +849,19 @@ static void* DoMonitor(void* arg) return NULL; #endif + /* signal to calling thread we're setup */ + if (SignalSetup(crl, 1) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + if (wd > 0) + inotify_rm_watch(notifyFd, wd); + close(crl->mfd); + close(notifyFd); + return NULL; + } + for (;;) { fd_set readfds; int result; @@ -607,7 +872,7 @@ static void* DoMonitor(void* arg) FD_SET(crl->mfd, &readfds); result = select(max(notifyFd, crl->mfd) + 1, &readfds, NULL, NULL,NULL); - + WOLFSSL_MSG("Got notify event"); if (result < 0) { @@ -620,11 +885,11 @@ static void* DoMonitor(void* arg) break; } - length = read(notifyFd, buff, 8192); + length = (int) read(notifyFd, buff, 8192); if (length < 0) { WOLFSSL_MSG("notify read problem, continue"); continue; - } + } if (SwapLists(crl) < 0) { WOLFSSL_MSG("SwapLists problem, continue"); @@ -643,42 +908,60 @@ static void* DoMonitor(void* arg) return NULL; } - -#else - -#error "CRL monitor only currently supported on linux or mach" - #endif /* MACH or linux */ /* Start Monitoring the CRL path(s) in a thread */ static int StartMonitorCRL(WOLFSSL_CRL* crl) { - pthread_attr_t attr; + int ret = WOLFSSL_SUCCESS; WOLFSSL_ENTER("StartMonitorCRL"); - if (crl == NULL) + if (crl == NULL) return BAD_FUNC_ARG; if (crl->tid != 0) { WOLFSSL_MSG("Monitor thread already running"); - return MONITOR_RUNNING_E; + return ret; /* that's ok, someone already started */ } - pthread_attr_init(&attr); - - if (pthread_create(&crl->tid, &attr, DoMonitor, crl) != 0) { + if (pthread_create(&crl->tid, NULL, DoMonitor, crl) != 0) { WOLFSSL_MSG("Thread creation error"); return THREAD_CREATE_E; } - return SSL_SUCCESS; + /* wait for setup to complete */ + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex crlLock error"); + return BAD_MUTEX_E; + } + + while (crl->setup == 0) { + if (pthread_cond_wait(&crl->cond, &crl->crlLock) != 0) { + ret = BAD_COND_E; + break; + } + } + + if (crl->setup < 0) + ret = crl->setup; /* store setup error */ + + wc_UnLockMutex(&crl->crlLock); + + if (ret < 0) { + WOLFSSL_MSG("DoMonitor setup failure"); + crl->tid = 0; /* thread already done */ + } + + return ret; } #else /* HAVE_CRL_MONITOR */ +#ifndef NO_FILESYSTEM + static int StartMonitorCRL(WOLFSSL_CRL* crl) { (void)crl; @@ -689,102 +972,122 @@ static int StartMonitorCRL(WOLFSSL_CRL* crl) return NOT_COMPILED_IN; } +#endif /* NO_FILESYSTEM */ + #endif /* HAVE_CRL_MONITOR */ +#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) -/* Load CRL path files of type, SSL_SUCCESS on ok */ +/* Load CRL path files of type, WOLFSSL_SUCCESS on ok */ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) { - struct dirent* entry; - DIR* dir; - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; + char* name = NULL; #ifdef WOLFSSL_SMALL_STACK - char* name; + ReadDirCtx* readCtx = NULL; #else - char name[MAX_FILENAME_SZ]; + ReadDirCtx readCtx[1]; #endif WOLFSSL_ENTER("LoadCRL"); if (crl == NULL) return BAD_FUNC_ARG; - dir = opendir(path); - if (dir == NULL) { - WOLFSSL_MSG("opendir path crl load failed"); - return BAD_PATH_ERROR; - } - #ifdef WOLFSSL_SMALL_STACK - name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (name == NULL) + readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), crl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (readCtx == NULL) return MEMORY_E; #endif - while ( (entry = readdir(dir)) != NULL) { - struct stat s; - - XMEMSET(name, 0, MAX_FILENAME_SZ); - XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2); - XSTRNCAT(name, "/", 1); - XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2); - - if (stat(name, &s) != 0) { - WOLFSSL_MSG("stat on name failed"); - continue; - } - if (s.st_mode & S_IFREG) { - - if (type == SSL_FILETYPE_PEM) { - if (strstr(entry->d_name, ".pem") == NULL) { - WOLFSSL_MSG("not .pem file, skipping"); - continue; - } + /* try to load each regular file in path */ + ret = wc_ReadDirFirst(readCtx, path, &name); + while (ret == 0 && name) { + int skip = 0; + if (type == WOLFSSL_FILETYPE_PEM) { + if (XSTRSTR(name, ".pem") == NULL) { + WOLFSSL_MSG("not .pem file, skipping"); + skip = 1; } - else { - if (strstr(entry->d_name, ".der") == NULL && - strstr(entry->d_name, ".crl") == NULL) { - - WOLFSSL_MSG("not .der or .crl file, skipping"); - continue; - } + } + else { + if (XSTRSTR(name, ".der") == NULL && + XSTRSTR(name, ".crl") == NULL) + { + WOLFSSL_MSG("not .der or .crl file, skipping"); + skip = 1; } + } - if (ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl) - != SSL_SUCCESS) { - WOLFSSL_MSG("CRL file load failed, continuing"); - } + if (!skip && ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl, + VERIFY) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("CRL file load failed, continuing"); } + + ret = wc_ReadDirNext(readCtx, path, &name); } + wc_ReadDirClose(readCtx); + ret = WOLFSSL_SUCCESS; /* load failures not reported, for backwards compat */ #ifdef WOLFSSL_SMALL_STACK - XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif if (monitor & WOLFSSL_CRL_MONITOR) { + word32 pathLen; + char* pathBuf; + WOLFSSL_MSG("monitor path requested"); - if (type == SSL_FILETYPE_PEM) { - crl->monitors[0].path = strdup(path); - crl->monitors[0].type = SSL_FILETYPE_PEM; - if (crl->monitors[0].path == NULL) - ret = MEMORY_E; - } else { - crl->monitors[1].path = strdup(path); - crl->monitors[1].type = SSL_FILETYPE_ASN1; - if (crl->monitors[1].path == NULL) - ret = MEMORY_E; + pathLen = (word32)XSTRLEN(path); + pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR); + if (pathBuf) { + XSTRNCPY(pathBuf, path, pathLen+1); + + if (type == WOLFSSL_FILETYPE_PEM) { + /* free old path before setting a new one */ + if (crl->monitors[0].path) { + XFREE(crl->monitors[0].path, crl->heap, + DYNAMIC_TYPE_CRL_MONITOR); + } + crl->monitors[0].path = pathBuf; + crl->monitors[0].type = WOLFSSL_FILETYPE_PEM; + } else { + /* free old path before setting a new one */ + if (crl->monitors[1].path) { + XFREE(crl->monitors[1].path, crl->heap, + DYNAMIC_TYPE_CRL_MONITOR); + } + crl->monitors[1].path = pathBuf; + crl->monitors[1].type = WOLFSSL_FILETYPE_ASN1; + } + + if (monitor & WOLFSSL_CRL_START_MON) { + WOLFSSL_MSG("start monitoring requested"); + + ret = StartMonitorCRL(crl); + } + } + else { + ret = MEMORY_E; } - - if (monitor & WOLFSSL_CRL_START_MON) { - WOLFSSL_MSG("start monitoring requested"); - - ret = StartMonitorCRL(crl); - } } - - closedir(dir); return ret; } +#else +int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) +{ + (void)crl; + (void)path; + (void)type; + (void)monitor; + + /* stub for scenario where file system is not supported */ + return NOT_COMPILED_IN; +} +#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */ + #endif /* HAVE_CRL */ +#endif /* !WOLFCRYPT_ONLY */ |