Init windows CRL monitor

This commit is contained in:
Juliusz Sosinowicz 2023-05-22 15:15:00 +02:00
parent da4424cd0c
commit 8ab0050801
10 changed files with 353 additions and 81 deletions

View File

@ -37,6 +37,9 @@
#define WC_RSA_BLINDING
#define NO_MULTIBYTE_PRINT
#define HAVE_CRL
#define HAVE_CRL_MONITOR
#if defined(WOLFSSL_LIB)
/* The lib */
#define OPENSSL_EXTRA

189
src/crl.c
View File

@ -46,10 +46,11 @@ CRL Options:
#endif
#ifdef HAVE_CRL_MONITOR
#if (defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__))
static int StopMonitor(int mfd);
#if defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__) || \
defined(_MSC_VER)
static int StopMonitor(wolfSSL_CRL_mfd_t mfd);
#else
#error "CRL monitor only currently supported on linux or mach"
#error "CRL monitor only currently supported on linux or mach or windows"
#endif
#endif /* HAVE_CRL_MONITOR */
@ -68,10 +69,10 @@ int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm)
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->setup = 0; /* thread setup done predicate */
if (pthread_cond_init(&crl->cond, 0) != 0) {
crl->tid = INVALID_THREAD_VAL;
crl->mfd = WOLFSSL_CRL_MFD_INIT_VAL;
crl->setup = 0; /* thread setup done predicate */
if (wolfSSL_CondInit(&crl->cond) != 0) {
WOLFSSL_MSG("Pthread condition init failed");
return BAD_COND_E;
}
@ -221,22 +222,18 @@ void FreeCRL(WOLFSSL_CRL* crl, int dynamic)
}
#ifdef HAVE_CRL_MONITOR
if (crl->tid != 0) {
if (crl->tid != INVALID_THREAD_VAL) {
WOLFSSL_MSG("stopping monitor thread");
if (StopMonitor(crl->mfd) == 0) {
int _pthread_ret = pthread_join(crl->tid, NULL);
if (_pthread_ret != 0)
if (wolfSSL_JoinThread(crl->tid) != 0)
WOLFSSL_MSG("stop monitor failed in pthread_join");
}
else {
WOLFSSL_MSG("stop monitor failed");
}
}
{
int _pthread_ret = pthread_cond_destroy(&crl->cond);
if (_pthread_ret != 0)
WOLFSSL_MSG("pthread_cond_destroy failed in FreeCRL");
}
if (wolfSSL_CondFree(&crl->cond) != 0)
WOLFSSL_MSG("pthread_cond_destroy failed in FreeCRL");
#endif
wc_FreeMutex(&crl->crlLock);
if (dynamic) /* free self */
@ -931,15 +928,19 @@ static int SignalSetup(WOLFSSL_CRL* crl, int status)
int ret;
/* signal to calling thread we're setup */
#ifndef COND_NO_REQUIRE_LOCKED_MUTEX
if (wc_LockMutex(&crl->crlLock) != 0) {
WOLFSSL_MSG("wc_LockMutex crlLock failed");
return BAD_MUTEX_E;
}
#endif
crl->setup = status;
ret = pthread_cond_signal(&crl->cond);
crl->setup = status;
ret = wolfSSL_CondSignal(&crl->cond);
#ifndef COND_NO_REQUIRE_LOCKED_MUTEX
wc_UnLockMutex(&crl->crlLock);
#endif
if (ret != 0)
return BAD_COND_E;
@ -1047,7 +1048,7 @@ static int SwapLists(WOLFSSL_CRL* crl)
/* shutdown monitor thread, 0 on success */
static int StopMonitor(int mfd)
static int StopMonitor(wolfSSL_CRL_mfd_t mfd)
{
struct kevent change;
@ -1063,7 +1064,7 @@ static int StopMonitor(int mfd)
/* OS X monitoring */
static void* DoMonitor(void* arg)
static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg)
{
int fPEM, fDER;
struct kevent change;
@ -1180,7 +1181,7 @@ static void* DoMonitor(void* arg)
/* shutdown monitor thread, 0 on success */
static int StopMonitor(int mfd)
static int StopMonitor(wolfSSL_CRL_mfd_t mfd)
{
word64 w64 = 1;
@ -1195,7 +1196,7 @@ static int StopMonitor(int mfd)
/* linux monitoring */
static void* DoMonitor(void* arg)
static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg)
{
int notifyFd;
int wd = -1;
@ -1326,7 +1327,120 @@ static void* DoMonitor(void* arg)
return NULL;
}
#endif /* MACH or linux */
#elif defined(_MSC_VER)
/* shutdown monitor thread, 0 on success */
static int StopMonitor(wolfSSL_CRL_mfd_t mfd)
{
if (SetEvent(mfd) == 0) {
WOLFSSL_MSG("SetEvent custom event trigger failed");
return -1;
}
return 0;
}
#define DM_ERROR() do { status = MONITOR_SETUP_E; goto cleanup; } while(0)
/* windows monitoring
* Tested initially by hand by running
* .\server.exe -A certs/ca-cert.pem
* and connecting to with
* .\client.exe -C -c certs/server-cert.pem -k certs/server-key.pem
* This connection succeeds by default. By deleting all files from certs/crl
* except for crl.revoked we disallow the client to connect. Deleting files
* is done while the server is running to show that the monitor reacts to
* changes in the crl directory. */
static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg)
{
WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
int status = 0;
HANDLE handles[WOLFSSL_CRL_MONITORS_LEN + 1];
DWORD handlesLen = 0;
int i;
WOLFSSL_ENTER("DoMonitor");
handles[0] = crl->mfd = CreateEventA(NULL, FALSE, FALSE, NULL);
if (crl->mfd == NULL) {
WOLFSSL_MSG("CreateEventA failed");
DM_ERROR();
}
handlesLen++;
for (i = 0; i < WOLFSSL_CRL_MONITORS_LEN; i++) {
if (crl->monitors[i].path) {
handles[handlesLen] = FindFirstChangeNotificationA(
crl->monitors[i].path, TRUE,
/* Watch for any changes that may affect what CRL's we load.
* This may trigger on the same file multiple times but this
* way we are certain that we have the most up to date and
* accurate set of CRL's. We don't expect this to trigger
* often enough for it to be a bottleneck. */
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_SECURITY);
if (handles[handlesLen] == INVALID_HANDLE_VALUE) {
WOLFSSL_MSG("FindFirstChangeNotificationA failed");
DM_ERROR();
}
handlesLen++;
}
}
if (handlesLen == 1) {
WOLFSSL_MSG("Nothing to watch. Only custom event handle set.");
DM_ERROR();
}
if (SignalSetup(crl, 1) != 0) {
WOLFSSL_MSG("Call to SignalSetup failed");
DM_ERROR();
}
for (;;) {
DWORD waitRet = WaitForMultipleObjects(handlesLen, handles, FALSE,
INFINITE);
WOLFSSL_MSG("Got notify event");
if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + handlesLen) {
if (waitRet == WAIT_OBJECT_0) {
WOLFSSL_MSG("got custom shutdown event, breaking out");
break;
}
else if (SwapLists(crl) < 0) {
WOLFSSL_MSG("SwapLists problem, continue");
}
}
else {
WOLFSSL_MSG("Unexpected WaitForMultipleObjects return. Continue.");
}
for (i = 1; i < (int)handlesLen; i++) {
if (FindNextChangeNotification(handles[i]) == 0) {
WOLFSSL_MSG("FindNextChangeNotification failed");
DM_ERROR();
}
}
}
cleanup:
if (status != 0)
SignalSetup(crl, status);
for (i = 0; i < (int)handlesLen; i++) {
BOOL closeRet;
if (i == 0) /* First handle is our custom event */
closeRet = CloseHandle(handles[i]);
else
closeRet = FindCloseChangeNotification(handles[i]);
if (closeRet == 0) {
WOLFSSL_MSG("Failed to close handle");
}
}
crl->mfd = INVALID_HANDLE_VALUE;
return 0;
}
#endif /* MACH or linux or windows */
/* Start Monitoring the CRL path(s) in a thread */
@ -1339,36 +1453,40 @@ static int StartMonitorCRL(WOLFSSL_CRL* crl)
if (crl == NULL)
return BAD_FUNC_ARG;
if (crl->tid != 0) {
if (crl->tid != INVALID_THREAD_VAL) {
WOLFSSL_MSG("Monitor thread already running");
return ret; /* that's ok, someone already started */
}
if (pthread_create(&crl->tid, NULL, DoMonitor, crl) != 0) {
if (wolfSSL_NewThread(&crl->tid, DoMonitor, crl) != 0) {
WOLFSSL_MSG("Thread creation error");
return THREAD_CREATE_E;
}
#ifndef COND_NO_REQUIRE_LOCKED_MUTEX
/* wait for setup to complete */
if (wc_LockMutex(&crl->crlLock) != 0) {
WOLFSSL_MSG("wc_LockMutex crlLock error");
return BAD_MUTEX_E;
}
#endif
while (crl->setup == 0) {
if (pthread_cond_wait(&crl->cond, &crl->crlLock) != 0) {
ret = BAD_COND_E;
break;
}
while (crl->setup == 0) {
if (wolfSSL_CondWait(&crl->cond, &crl->crlLock) != 0) {
ret = BAD_COND_E;
break;
}
if (crl->setup < 0)
ret = crl->setup; /* store setup error */
}
if (crl->setup < 0)
ret = crl->setup; /* store setup error */
#ifndef COND_NO_REQUIRE_LOCKED_MUTEX
wc_UnLockMutex(&crl->crlLock);
#endif
if (ret < 0) {
WOLFSSL_MSG("DoMonitor setup failure");
crl->tid = 0; /* thread already done */
crl->tid = INVALID_THREAD_VAL; /* thread already done */
}
return ret;
@ -1451,13 +1569,14 @@ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
#endif
if (monitor & WOLFSSL_CRL_MONITOR) {
#ifdef HAVE_CRL_MONITOR
word32 pathLen;
char* pathBuf;
WOLFSSL_MSG("monitor path requested");
pathLen = (word32)XSTRLEN(path);
pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR);
pathBuf = (char*)XMALLOC(pathLen+1, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
if (pathBuf) {
XMEMCPY(pathBuf, path, pathLen+1);
@ -1488,6 +1607,10 @@ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
else {
ret = MEMORY_E;
}
#else
WOLFSSL_MSG("CRL monitoring requested but not compiled in");
ret = NOT_COMPILED_IN;
#endif
}
return ret;

View File

@ -10209,7 +10209,7 @@ static int ec_point_convert_to_affine(const WOLFSSL_EC_GROUP *group,
WOLFSSL_EC_POINT *point)
{
int err = 0;
mp_digit mp;
mp_digit mp = 0;
#ifdef WOLFSSL_SMALL_STACK
mp_int* modulus;
#else

View File

@ -54588,50 +54588,58 @@ static int test_wolfSSL_CTX_LoadCRL(void)
const char* issuerCert = "./certs/client-cert.pem";
int derType = WOLFSSL_FILETYPE_ASN1;
int pemType = WOLFSSL_FILETYPE_PEM;
#ifdef HAVE_CRL_MONITOR
int monitor = WOLFSSL_CRL_MONITOR;
#else
int monitor = 0;
#endif
WOLFSSL_CERT_MANAGER* cm = NULL;
ExpectIntEQ(wolfSSL_CTX_LoadCRL(ctx, validPath, pemType, monitor),
BAD_FUNC_ARG);
#define FAIL_T1(x, y, z, p, d) AssertIntEQ((int) x(y, z, p, d), \
BAD_FUNC_ARG)
#define FAIL_T2(x, y, z, p, d) AssertIntEQ((int) x(y, z, p, d), \
NOT_COMPILED_IN)
#define SUCC_T(x, y, z, p, d) AssertIntEQ((int) x(y, z, p, d), \
WOLFSSL_SUCCESS)
#ifndef NO_WOLFSSL_CLIENT
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
#define NEW_CTX(ctx) AssertNotNull( \
ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()))
#elif !defined(NO_WOLFSSL_SERVER)
#define NEW_CTX(ctx) AssertNotNull( \
ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()))
#else
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
#define NEW_CTX(ctx) return
#endif
ExpectIntEQ(wolfSSL_CTX_LoadCRL(ctx, validPath, pemType, monitor),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CTX_LoadCRL(ctx, badPath, pemType, monitor),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CTX_LoadCRL(ctx, badPath, derType, monitor),
WOLFSSL_SUCCESS);
FAIL_T1(wolfSSL_CTX_LoadCRL, ctx, validPath, pemType, monitor);
NEW_CTX(ctx);
#ifndef HAVE_CRL_MONITOR
FAIL_T2(wolfSSL_CTX_LoadCRL, ctx, validPath, pemType, WOLFSSL_CRL_MONITOR);
wolfSSL_CTX_free(ctx);
NEW_CTX(ctx);
#endif
SUCC_T (wolfSSL_CTX_LoadCRL, ctx, validPath, pemType, monitor);
SUCC_T (wolfSSL_CTX_LoadCRL, ctx, badPath, pemType, monitor);
SUCC_T (wolfSSL_CTX_LoadCRL, ctx, badPath, derType, monitor);
wolfSSL_CTX_free(ctx);
ctx = NULL;
#ifndef NO_WOLFSSL_CLIENT
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
#else
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
#endif
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx, issuerCert, NULL),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CTX_LoadCRLFile(ctx, validFilePath, pemType),
WOLFSSL_SUCCESS);
NEW_CTX(ctx);
AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, issuerCert, NULL),
WOLFSSL_SUCCESS);
AssertIntEQ(wolfSSL_CTX_LoadCRLFile(ctx, validFilePath, pemType), WOLFSSL_SUCCESS);
wolfSSL_CTX_free(ctx);
ctx = NULL;
#ifndef NO_WOLFSSL_CLIENT
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
#else
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
#endif
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx, issuerCert, NULL),
WOLFSSL_SUCCESS);
ExpectNotNull(ssl = wolfSSL_new(ctx));
ExpectIntEQ(wolfSSL_LoadCRLFile(ssl, validFilePath, pemType),
WOLFSSL_SUCCESS);
NEW_CTX(ctx);
AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, issuerCert, NULL),
WOLFSSL_SUCCESS);
AssertNotNull(ssl = wolfSSL_new(ctx));
AssertIntEQ(wolfSSL_LoadCRLFile(ssl, validFilePath, pemType), WOLFSSL_SUCCESS);
wolfSSL_free(ssl);
ssl = NULL;
wolfSSL_CTX_free(ctx);

View File

@ -469,7 +469,7 @@ void wait_tcp_ready(func_args* args)
* @param [in] args Object to send to function in thread.
* @param [out] thread Handle to thread.
*/
void start_thread(THREAD_FUNC fun, func_args* args, THREAD_TYPE* thread)
void start_thread(THREAD_CB fun, func_args* args, THREAD_TYPE* thread)
{
#if defined(HAVE_PTHREAD)
PTHREAD_CHECK_RET(pthread_create(thread, 0, fun, args));
@ -529,8 +529,8 @@ void start_thread(THREAD_FUNC fun, func_args* args, THREAD_TYPE* thread)
}
/* end if NETOS */
#else
/* custom / external thread type */
*thread = (THREAD_TYPE)_beginthreadex(0, 0, fun, args, 0, 0);
/* windows thread type */
*thread = (THREAD_TYPE)_beginthreadex(NULL, 0, fun, args, 0, 0);
#endif /* thread types */
}
@ -554,7 +554,7 @@ void join_thread(THREAD_TYPE thread)
#elif defined(NETOS)
/* TODO: */
#else
int res = WaitForSingleObject((HANDLE)thread, INFINITE);
DWORD res = WaitForSingleObject((HANDLE)thread, INFINITE);
assert(res == WAIT_OBJECT_0);
res = CloseHandle((HANDLE)thread);
assert(res);

View File

@ -3344,3 +3344,100 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n)
#include <wolfcrypt/src/port/arm/cryptoCellHash.c> /* sha256 */
#endif
#endif
#ifndef SINGLE_THREADED
#ifdef _MSC_VER
int wolfSSL_NewThread(THREAD_TYPE* thread,
THREAD_CB cb, void* arg)
{
if (thread == NULL || cb == NULL)
return BAD_FUNC_ARG;
/* Use _beginthreadex instead of _beginthread because of:
* _beginthreadex is safer to use than _beginthread. If the thread
* that's generated by _beginthread exits quickly, the handle that's
* returned to the caller of _beginthread might be invalid or point
* to another thread. However, the handle that's returned by
* _beginthreadex has to be closed by the caller of _beginthreadex,
* so it's guaranteed to be a valid handle if _beginthreadex didn't
* return an error.*/
*thread = _beginthreadex(NULL, 0, cb, arg, 0, NULL);
if (*thread == 0) {
*thread = INVALID_THREAD_VAL;
return MEMORY_ERROR;
}
return 0;
}
int wolfSSL_JoinThread(THREAD_TYPE thread)
{
if (thread == INVALID_THREAD_VAL)
return BAD_FUNC_ARG;
if (WaitForSingleObject((HANDLE)thread, INFINITE) == WAIT_FAILED)
return MEMORY_ERROR;
if (CloseHandle((HANDLE)thread) == 0)
return MEMORY_ERROR;
return 0;
}
#ifdef WOLFSSL_COND
int wolfSSL_CondInit(COND_TYPE* cond)
{
if (cond == NULL)
return BAD_FUNC_ARG;
*cond = CreateEventA(NULL, FALSE, FALSE, NULL);
if (*cond == NULL)
return MEMORY_ERROR;
return 0;
}
int wolfSSL_CondFree(COND_TYPE* cond)
{
if (cond == NULL)
return BAD_FUNC_ARG;
if (CloseHandle(*cond) == 0)
return MEMORY_ERROR;
return 0;
}
int wolfSSL_CondSignal(COND_TYPE* cond)
{
if (cond == NULL)
return BAD_FUNC_ARG;
if (SetEvent(*cond) == 0)
return MEMORY_ERROR;
return 0;
}
int wolfSSL_CondWait(COND_TYPE* cond,
wolfSSL_Mutex* mutex)
{
(void)mutex;
if (cond == NULL)
return BAD_FUNC_ARG;
if (WaitForSingleObject(*cond, INFINITE) == WAIT_FAILED)
return MEMORY_ERROR;
return 0;
}
#endif /* WOLFSSL_COND */
#else /* pthread */
#endif
#endif /* SINGLE_THREADED */

View File

@ -2408,6 +2408,19 @@ struct CRL_Monitor {
#undef HAVE_CRL_MONITOR
#endif
/* PEM and DER possible */
#define WOLFSSL_CRL_MONITORS_LEN (2)
#if defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__)
typedef int wolfSSL_CRL_mfd_t; /* monitor fd, -1 if no init yet */
/* mfd for bsd is kqueue fd, eventfd for linux */
#define WOLFSSL_CRL_MFD_INIT_VAL (-1)
#elif defined(_MSC_VER)
typedef HANDLE wolfSSL_CRL_mfd_t; /* monitor fd, INVALID_HANDLE_VALUE if
* no init yet */
#define WOLFSSL_CRL_MFD_INIT_VAL (INVALID_HANDLE_VALUE)
#endif
/* wolfSSL CRL controller */
struct WOLFSSL_CRL {
WOLFSSL_CERT_MANAGER* cm; /* pointer back to cert manager */
@ -2417,11 +2430,11 @@ struct WOLFSSL_CRL {
CbCrlIO crlIOCb;
#endif
wolfSSL_Mutex crlLock; /* CRL list lock */
CRL_Monitor monitors[2]; /* PEM and DER possible */
CRL_Monitor monitors[WOLFSSL_CRL_MONITORS_LEN];
#ifdef HAVE_CRL_MONITOR
pthread_cond_t cond; /* condition to signal setup */
pthread_t tid; /* monitoring thread */
int mfd; /* monitor fd, -1 if no init yet */
COND_TYPE cond; /* condition to signal setup */
THREAD_TYPE tid; /* monitoring thread */
wolfSSL_CRL_mfd_t mfd;
int setup; /* thread is setup predicate */
#endif
void* heap; /* heap hint for dynamic memory */

View File

@ -633,13 +633,7 @@ typedef struct func_args {
void wait_tcp_ready(func_args* args);
#ifdef WOLFSSL_ZEPHYR
typedef void THREAD_FUNC(void*, void*, void*);
#else
typedef THREAD_RETURN WOLFSSL_THREAD THREAD_FUNC(void*);
#endif
void start_thread(THREAD_FUNC fun, func_args* args, THREAD_TYPE* thread);
void start_thread(THREAD_CB fun, func_args* args, THREAD_TYPE* thread);
void join_thread(THREAD_TYPE thread);
typedef int (*cbType)(WOLFSSL_CTX *ctx, WOLFSSL *ssl);

View File

@ -1360,18 +1360,49 @@ typedef struct w64wrapper {
typedef void* THREAD_RETURN;
typedef pthread_t THREAD_TYPE;
#define WOLFSSL_THREAD
#define INFINITE (-1)
#define WAIT_OBJECT_0 0L
#error TODO implement threading with pthreads
#elif defined(FREERTOS)
typedef unsigned int THREAD_RETURN;
typedef TaskHandle_t THREAD_TYPE;
#define WOLFSSL_THREAD
#elif defined(_MSC_VER)
typedef unsigned THREAD_RETURN;
typedef uintptr_t THREAD_TYPE;
typedef HANDLE COND_TYPE;
#define WOLFSSL_COND
#define INVALID_THREAD_VAL ((THREAD_TYPE)(INVALID_HANDLE_VALUE))
#define COND_NO_REQUIRE_LOCKED_MUTEX
#define WOLFSSL_THREAD __stdcall
#else
typedef unsigned int THREAD_RETURN;
typedef size_t THREAD_TYPE;
#define WOLFSSL_THREAD __stdcall
#endif
#ifndef SINGLE_THREADED
/* Necessary headers should already be included. */
/* We don't support returns from threads */
typedef THREAD_RETURN (WOLFSSL_THREAD *THREAD_CB)(void* arg);
#ifndef INVALID_THREAD_VAL
#define INVALID_THREAD_VAL (-1)
#endif
WOLFSSL_LOCAL int wolfSSL_NewThread(THREAD_TYPE* thread,
THREAD_CB cb, void* arg);
WOLFSSL_LOCAL int wolfSSL_JoinThread(THREAD_TYPE thread);
#ifdef WOLFSSL_COND
WOLFSSL_LOCAL int wolfSSL_CondInit(COND_TYPE* cond);
WOLFSSL_LOCAL int wolfSSL_CondFree(COND_TYPE* cond);
WOLFSSL_LOCAL int wolfSSL_CondSignal(COND_TYPE* cond);
WOLFSSL_LOCAL int wolfSSL_CondWait(COND_TYPE* cond,
wolfSSL_Mutex* mutex);
#endif
#endif /* SINGLE_THREADED */
#if defined(HAVE_STACK_SIZE)
#define EXIT_TEST(ret) return (THREAD_RETURN)((size_t)(ret))
#else

View File

@ -77,6 +77,9 @@
#endif
#endif /* WOLFSSL_SGX */
#endif
#ifndef SINGLE_THREADED
#include <process.h>
#endif
#elif defined(THREADX)
#ifndef SINGLE_THREADED
#ifdef NEED_THREADX_TYPES