summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Source/WolfSSL/src/crl.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Plus/Source/WolfSSL/src/crl.c')
-rw-r--r--FreeRTOS-Plus/Source/WolfSSL/src/crl.c651
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 */