From 595f55eceb689089eeb5be3dcff555d43f6e1f11 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Thu, 14 Nov 2024 16:22:53 -0600 Subject: [PATCH] add struct wolfSSL_RefWithMutex, wolfSSL_RefWithMutexLock, and wolfSSL_RefWithMutexUnlock, and change WOLFSSL_CTX.ref from wolfSSL_Ref to wolfSSL_RefWithMutex. in in wc_port.c, rename mutexful implementations of wolfSSL_Ref*() to wolfSSL_RefWithMutex*(), and build them even if defined(WOLFSSL_ATOMIC_OPS). refactor wolfSSL_CTX_UnloadIntermediateCerts() to wrap the refcount check and deallocation with wolfSSL_RefWithMutexLock()...wolfSSL_RefWithMutexUnlock(). move port-specific setup for WARN_UNUSED_RESULT, WC_MAYBE_UNUSED, and WC_INLINE, from types.h to wc_port.h, to make them usable by port-specific definitions later in wc_port.h. when defined(SINGLE_THREADED) and !defined(WOLFSSL_NO_ATOMICS), typedef int wolfSSL_Atomic_Int, so that access to wolfSSL_Atomic_Ints in SINGLE_THREADED builds is easy. refactor fallback definitions of wolfSSL_Atomic_Int_FetchAdd and wolfSSL_Atomic_Int_FetchSub as WC_INLINE functions to avoid -Wunused-result. --- src/internal.c | 4 +- src/ssl.c | 19 ++++-- wolfcrypt/src/wc_port.c | 25 +++++-- wolfssl/internal.h | 2 +- wolfssl/wolfcrypt/types.h | 56 --------------- wolfssl/wolfcrypt/wc_port.h | 131 +++++++++++++++++++++++++++++++----- 6 files changed, 150 insertions(+), 87 deletions(-) diff --git a/src/internal.c b/src/internal.c index f036c4be9b..7fde8dcc76 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2297,7 +2297,7 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) ctx->minDowngrade = WOLFSSL_MIN_DOWNGRADE; } - wolfSSL_RefInit(&ctx->ref, &ret); + wolfSSL_RefWithMutexInit(&ctx->ref, &ret); #ifdef WOLFSSL_REFCNT_ERROR_RETURN if (ret < 0) { WOLFSSL_MSG("Mutex error on CTX init"); @@ -2782,7 +2782,7 @@ void FreeSSL_Ctx(WOLFSSL_CTX* ctx) #endif /* decrement CTX reference count */ - wolfSSL_RefDec(&ctx->ref, &isZero, &ret); + wolfSSL_RefWithMutexDec(&ctx->ref, &isZero, &ret); #ifdef WOLFSSL_REFCNT_ERROR_RETURN if (ret < 0) { /* check error state, if mutex error code then mutex init failed but diff --git a/src/ssl.c b/src/ssl.c index 03f7989907..94f7ed6a78 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1136,7 +1136,7 @@ WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method) int wolfSSL_CTX_up_ref(WOLFSSL_CTX* ctx) { int ret; - wolfSSL_RefInc(&ctx->ref, &ret); + wolfSSL_RefWithMutexInc(&ctx->ref, &ret); #ifdef WOLFSSL_REFCNT_ERROR_RETURN return ((ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE); #else @@ -11104,18 +11104,29 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int wolfSSL_CTX_UnloadIntermediateCerts(WOLFSSL_CTX* ctx) { + int ret; + WOLFSSL_ENTER("wolfSSL_CTX_UnloadIntermediateCerts"); if (ctx == NULL) return BAD_FUNC_ARG; + ret = wolfSSL_RefWithMutexLock(&ctx->ref); + if (ret < 0) + return ret; + if (ctx->ref.count > 1) { WOLFSSL_MSG("ctx object must have a ref count of 1 before " "unloading intermediate certs"); - return BAD_STATE_E; + ret = BAD_STATE_E; + } + else { + ret = wolfSSL_CertManagerUnloadIntermediateCerts(ctx->cm); } - return wolfSSL_CertManagerUnloadIntermediateCerts(ctx->cm); + wolfSSL_RefWithMutexUnlock(&ctx->ref); + + return ret; } @@ -20579,7 +20590,7 @@ WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) InitSSL_CTX_Suites(ctx); } - wolfSSL_RefInc(&ctx->ref, &ret); + wolfSSL_RefWithMutexInc(&ctx->ref, &ret); #ifdef WOLFSSL_REFCNT_ERROR_RETURN if (ret != 0) { /* can only fail on serious stuff, like mutex not working diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 78cdeee78b..8c96bee929 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -1232,7 +1232,7 @@ char* wc_strdup_ex(const char *src, int memType) { } #endif -#ifdef WOLFSSL_ATOMIC_OPS +#if defined(WOLFSSL_ATOMIC_OPS) && !defined(SINGLE_THREADED) #ifdef HAVE_C___ATOMIC /* Atomic ops using standard C lib */ @@ -1292,8 +1292,9 @@ int wolfSSL_Atomic_Int_FetchSub(wolfSSL_Atomic_Int* c, int i) #endif /* WOLFSSL_ATOMIC_OPS */ -#if !defined(SINGLE_THREADED) && !defined(WOLFSSL_ATOMIC_OPS) -void wolfSSL_RefInit(wolfSSL_Ref* ref, int* err) +#if !defined(SINGLE_THREADED) + +void wolfSSL_RefWithMutexInit(wolfSSL_RefWithMutex* ref, int* err) { int ret = wc_InitMutex(&ref->mutex); if (ret != 0) { @@ -1304,14 +1305,14 @@ void wolfSSL_RefInit(wolfSSL_Ref* ref, int* err) *err = ret; } -void wolfSSL_RefFree(wolfSSL_Ref* ref) +void wolfSSL_RefWithMutexFree(wolfSSL_RefWithMutex* ref) { if (wc_FreeMutex(&ref->mutex) != 0) { WOLFSSL_MSG("Failed to free mutex of reference counting!"); } } -void wolfSSL_RefInc(wolfSSL_Ref* ref, int* err) +void wolfSSL_RefWithMutexInc(wolfSSL_RefWithMutex* ref, int* err) { int ret = wc_LockMutex(&ref->mutex); if (ret != 0) { @@ -1324,7 +1325,17 @@ void wolfSSL_RefInc(wolfSSL_Ref* ref, int* err) *err = ret; } -void wolfSSL_RefDec(wolfSSL_Ref* ref, int* isZero, int* err) +int wolfSSL_RefWithMutexLock(wolfSSL_RefWithMutex* ref) +{ + return wc_LockMutex(&ref->mutex); +} + +void wolfSSL_RefWithMutexUnlock(wolfSSL_RefWithMutex* ref) +{ + wc_UnLockMutex(&ref->mutex); +} + +void wolfSSL_RefWithMutexDec(wolfSSL_RefWithMutex* ref, int* isZero, int* err) { int ret = wc_LockMutex(&ref->mutex); if (ret != 0) { @@ -1341,7 +1352,7 @@ void wolfSSL_RefDec(wolfSSL_Ref* ref, int* isZero, int* err) } *err = ret; } -#endif +#endif /* ! SINGLE_THREADED */ #if WOLFSSL_CRYPT_HW_MUTEX /* Mutex for protection of cryptography hardware */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 70c99818e5..7fef724239 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3724,7 +3724,7 @@ struct WOLFSSL_CTX { #ifdef SINGLE_THREADED WC_RNG* rng; /* to be shared with WOLFSSL w/o locking */ #endif - wolfSSL_Ref ref; + wolfSSL_RefWithMutex ref; int err; /* error code in case of mutex not created */ #ifndef NO_DH buffer serverDH_P; diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index e2dd969d8a..a980873f9e 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -318,25 +318,6 @@ typedef struct w64wrapper { #define WOLFSSL_MAX_16BIT 0xffffU #define WOLFSSL_MAX_32BIT 0xffffffffU - #ifndef WARN_UNUSED_RESULT - #if defined(WOLFSSL_LINUXKM) && defined(__must_check) - #define WARN_UNUSED_RESULT __must_check - #elif (defined(__GNUC__) && (__GNUC__ >= 4)) || \ - (defined(__IAR_SYSTEMS_ICC__) && (__VER__ >= 9040001)) - #define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) - #else - #define WARN_UNUSED_RESULT - #endif - #endif /* WARN_UNUSED_RESULT */ - - #ifndef WC_MAYBE_UNUSED - #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) || defined(__IAR_SYSTEMS_ICC__) - #define WC_MAYBE_UNUSED __attribute__((unused)) - #else - #define WC_MAYBE_UNUSED - #endif - #endif /* WC_MAYBE_UNUSED */ - #ifndef WC_DO_NOTHING #define WC_DO_NOTHING do {} while (0) #ifdef _MSC_VER @@ -347,43 +328,6 @@ typedef struct w64wrapper { #endif #endif - /* use inlining if compiler allows */ - #ifndef WC_INLINE - #ifndef NO_INLINE - #ifdef _MSC_VER - #define WC_INLINE __inline - #elif defined(__GNUC__) - #ifdef WOLFSSL_VXWORKS - #define WC_INLINE __inline__ - #else - #define WC_INLINE inline - #endif - #elif defined(__IAR_SYSTEMS_ICC__) - #define WC_INLINE inline - #elif defined(THREADX) - #define WC_INLINE _Inline - #elif defined(__ghc__) - #ifndef __cplusplus - #define WC_INLINE __inline - #else - #define WC_INLINE inline - #endif - #elif defined(__CCRX__) - #define WC_INLINE inline - #elif defined(__DCC__) - #ifndef __cplusplus - #define WC_INLINE __inline__ - #else - #define WC_INLINE inline - #endif - #else - #define WC_INLINE WC_MAYBE_UNUSED - #endif - #else - #define WC_INLINE WC_MAYBE_UNUSED - #endif - #endif - #if defined(HAVE_FIPS) || defined(HAVE_SELFTEST) #define INLINE WC_INLINE #endif diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index 21f4c00d3d..4ca49b3c10 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -62,6 +62,63 @@ #include "../../linuxkm/linuxkm_wc_port.h" #endif /* WOLFSSL_LINUXKM */ +#ifndef WARN_UNUSED_RESULT + #if defined(WOLFSSL_LINUXKM) && defined(__must_check) + #define WARN_UNUSED_RESULT __must_check + #elif (defined(__GNUC__) && (__GNUC__ >= 4)) || \ + (defined(__IAR_SYSTEMS_ICC__) && (__VER__ >= 9040001)) + #define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) + #else + #define WARN_UNUSED_RESULT + #endif +#endif /* !WARN_UNUSED_RESULT */ + +#ifndef WC_MAYBE_UNUSED + #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) || \ + defined(__IAR_SYSTEMS_ICC__) + #define WC_MAYBE_UNUSED __attribute__((unused)) + #else + #define WC_MAYBE_UNUSED + #endif +#endif /* !WC_MAYBE_UNUSED */ + +/* use inlining if compiler allows */ +#ifndef WC_INLINE +#ifndef NO_INLINE + #ifdef _MSC_VER + #define WC_INLINE __inline + #elif defined(__GNUC__) + #ifdef WOLFSSL_VXWORKS + #define WC_INLINE __inline__ + #else + #define WC_INLINE inline + #endif + #elif defined(__IAR_SYSTEMS_ICC__) + #define WC_INLINE inline + #elif defined(THREADX) + #define WC_INLINE _Inline + #elif defined(__ghc__) + #ifndef __cplusplus + #define WC_INLINE __inline + #else + #define WC_INLINE inline + #endif + #elif defined(__CCRX__) + #define WC_INLINE inline + #elif defined(__DCC__) + #ifndef __cplusplus + #define WC_INLINE __inline__ + #else + #define WC_INLINE inline + #endif + #else + #define WC_INLINE WC_MAYBE_UNUSED + #endif +#else + #define WC_INLINE WC_MAYBE_UNUSED +#endif +#endif + /* THREADING/MUTEX SECTION */ #if defined(SINGLE_THREADED) && defined(NO_FILESYSTEM) /* No system headers required for build. */ @@ -335,7 +392,11 @@ #endif #ifndef WOLFSSL_NO_ATOMICS -#ifdef HAVE_C___ATOMIC +#ifdef SINGLE_THREADED + typedef int wolfSSL_Atomic_Int; + #define WOLFSSL_ATOMIC_INITIALIZER(x) (x) + #define WOLFSSL_ATOMIC_OPS +#elif defined(HAVE_C___ATOMIC) #ifdef __cplusplus #if defined(__GNUC__) && defined(__ATOMIC_RELAXED) /* C++ using direct calls to compiler built-in functions */ @@ -365,34 +426,47 @@ #endif #endif /* WOLFSSL_NO_ATOMICS */ -#ifdef WOLFSSL_ATOMIC_OPS +#if defined(WOLFSSL_ATOMIC_OPS) && !defined(SINGLE_THREADED) WOLFSSL_API void wolfSSL_Atomic_Int_Init(wolfSSL_Atomic_Int* c, int i); /* Fetch* functions return the value of the counter immediately preceding * the effects of the function. */ WOLFSSL_API int wolfSSL_Atomic_Int_FetchAdd(wolfSSL_Atomic_Int* c, int i); WOLFSSL_API int wolfSSL_Atomic_Int_FetchSub(wolfSSL_Atomic_Int* c, int i); #else - /* Code using these fallback macros needs to arrange its own fallback for - * wolfSSL_Atomic_Int, which is never defined if - * !defined(WOLFSSL_ATOMIC_OPS). This forces local awareness of - * thread-unsafe semantics. + /* Code using these fallback implementations in non-SINGLE_THREADED builds + * needs to arrange its own explicit fallback to int for wolfSSL_Atomic_Int, + * which is not defined if !defined(WOLFSSL_ATOMIC_OPS) && + * !defined(SINGLE_THREADED). This forces local awareness of thread-unsafe + * semantics. */ #define wolfSSL_Atomic_Int_Init(c, i) (*(c) = (i)) - #define wolfSSL_Atomic_Int_FetchAdd(c, i) (*(c) += (i), *(c) - (i)) - #define wolfSSL_Atomic_Int_FetchSub(c, i) (*(c) -= (i), *(c) + (i)) + static WC_INLINE int wolfSSL_Atomic_Int_FetchAdd(int *c, int i) { + int ret = *c; + *c += i; + return ret; + } + static WC_INLINE int wolfSSL_Atomic_Int_FetchSub(int *c, int i) { + int ret = *c; + *c -= i; + return ret; + } #endif /* Reference counting. */ -typedef struct wolfSSL_Ref { -#if !defined(SINGLE_THREADED) && !defined(WOLFSSL_ATOMIC_OPS) +typedef struct wolfSSL_RefWithMutex { +#if !defined(SINGLE_THREADED) wolfSSL_Mutex mutex; #endif -#ifdef WOLFSSL_ATOMIC_OPS + int count; +} wolfSSL_RefWithMutex; + +#if defined(WOLFSSL_ATOMIC_OPS) && !defined(SINGLE_THREADED) +typedef struct wolfSSL_Ref { wolfSSL_Atomic_Int count; +} wolfSSL_Ref; #else - int count; +typedef struct wolfSSL_RefWithMutex wolfSSL_Ref; #endif -} wolfSSL_Ref; #if defined(SINGLE_THREADED) || defined(WOLFSSL_ATOMIC_OPS) @@ -419,10 +493,33 @@ typedef struct wolfSSL_Ref { #define WOLFSSL_REFCNT_ERROR_RETURN -WOLFSSL_LOCAL void wolfSSL_RefInit(wolfSSL_Ref* ref, int* err); -WOLFSSL_LOCAL void wolfSSL_RefFree(wolfSSL_Ref* ref); -WOLFSSL_LOCAL void wolfSSL_RefInc(wolfSSL_Ref* ref, int* err); -WOLFSSL_LOCAL void wolfSSL_RefDec(wolfSSL_Ref* ref, int* isZero, int* err); +#define wolfSSL_RefInit wolfSSL_RefWithMutexInit +#define wolfSSL_RefFree wolfSSL_RefWithMutexFree +#define wolfSSL_RefInc wolfSSL_RefWithMutexInc +#define wolfSSL_RefDec wolfSSL_RefWithMutexDec + +#endif + +#if defined(SINGLE_THREADED) + +#define wolfSSL_RefWithMutexInit wolfSSL_RefInit +#define wolfSSL_RefWithMutexFree wolfSSL_RefFree +#define wolfSSL_RefWithMutexInc wolfSSL_RefInc +#define wolfSSL_RefWithMutexLock(ref) 0 +#define wolfSSL_RefWithMutexUnlock(ref) WC_DO_NOTHING +#define wolfSSL_RefWithMutexDec wolfSSL_RefDec + +#else + +WOLFSSL_LOCAL void wolfSSL_RefWithMutexInit(wolfSSL_RefWithMutex* ref, + int* err); +WOLFSSL_LOCAL void wolfSSL_RefWithMutexFree(wolfSSL_RefWithMutex* ref); +WOLFSSL_LOCAL void wolfSSL_RefWithMutexInc(wolfSSL_RefWithMutex* ref, + int* err); +WOLFSSL_LOCAL int wolfSSL_RefWithMutexLock(wolfSSL_RefWithMutex* ref); +WOLFSSL_LOCAL void wolfSSL_RefWithMutexUnlock(wolfSSL_RefWithMutex* ref); +WOLFSSL_LOCAL void wolfSSL_RefWithMutexDec(wolfSSL_RefWithMutex* ref, + int* isZero, int* err); #endif