From b8aeaf4fa878fd9d157e774d9302b150402dc50f Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 8 Nov 2024 16:00:46 -0600 Subject: [PATCH 1/3] src/ssl.c: implement WOLFSSL_CLEANUP_THREADSAFE in wolfSSL_Init() / wolfSSL_Cleanup(). --- src/ssl.c | 57 +++++++++++++++++++++++++++++++------ wolfssl/wolfcrypt/wc_port.h | 4 +++ 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 5728b399ef..7fa6b6f9b4 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1037,7 +1037,7 @@ static volatile WOLFSSL_GLOBAL int initRefCount = 0; static WOLFSSL_GLOBAL wolfSSL_Mutex inits_count_mutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(inits_count_mutex); #ifndef WOLFSSL_MUTEX_INITIALIZER -static WOLFSSL_GLOBAL int inits_count_mutex_valid = 0; +static WOLFSSL_GLOBAL volatile int inits_count_mutex_valid = 0; #endif /* Create a new WOLFSSL_CTX struct and return the pointer to created struct. @@ -5641,12 +5641,29 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) static int wolfSSL_RAND_InitMutex(void); #endif +#if defined(WOLFSSL_CLEANUP_THREADSAFE) && !defined(WOLFSSL_MUTEX_INITIALIZER) + #ifndef WOLFSSL_ATOMIC_OPS + #error WOLFSSL_CLEANUP_THREADSAFE with !WOLFSSL_MUTEX_INITIALIZER requires WOLFSSL_ATOMIC_OPS + #endif + /* WOLFSSL_CLEANUP_THREADSAFE depends on a wolfSSL_Atomic_Int that can + * be statically initialized. + */ + static wolfSSL_Atomic_Int inits_count_mutex_valid2 = 0; +#endif /* WOLFSSL_CLEANUP_THREADSAFE && !WOLFSSL_MUTEX_INITIALIZER */ + #if defined(OPENSSL_EXTRA) && defined(HAVE_ATEXIT) static void AtExitCleanup(void) { if (initRefCount > 0) { initRefCount = 1; (void)wolfSSL_Cleanup(); +#if defined(WOLFSSL_CLEANUP_THREADSAFE) && !defined(WOLFSSL_MUTEX_INITIALIZER) + if (inits_count_mutex_valid == 1) { + (void)wc_FreeMutex(&inits_count_mutex); + inits_count_mutex_valid = 0; + inits_count_mutex_valid2 = 0; + } +#endif } } #endif @@ -5662,13 +5679,37 @@ int wolfSSL_Init(void) WOLFSSL_ENTER("wolfSSL_Init"); #ifndef WOLFSSL_MUTEX_INITIALIZER - if (inits_count_mutex_valid == 0) { - if (wc_InitMutex(&inits_count_mutex) != 0) { - WOLFSSL_MSG("Bad Init Mutex count"); - return BAD_MUTEX_E; + if (inits_count_mutex_valid <= 0) { + #ifdef WOLFSSL_CLEANUP_THREADSAFE + int current_inits_count_mutex_valid; + if (wolfSSL_Atomic_Int_FetchAdd(&inits_count_mutex_valid2, 1) != 0) { + /* We treat inits_count_mutex_valid as a spin lock -- this may cause + * deadlocks in some runtimes. Applications can fully mitigate this + * race by calling wolfSSL_Init() and wolfSSL_Cleanup() + * consecutively at startup, uncontended. This leaves + * inits_count_mutex safely initialized, but releases all other + * resources. + */ + while ((current_inits_count_mutex_valid = inits_count_mutex_valid) == 0); + if (current_inits_count_mutex_valid < 0) { + (void)wolfSSL_Atomic_Int_FetchSub(&inits_count_mutex_valid2, 1); + return BAD_MUTEX_E; + } } - else { - inits_count_mutex_valid = 1; + else + #endif /* WOLFSSL_CLEANUP_THREADSAFE */ + { + if (wc_InitMutex(&inits_count_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex count"); + inits_count_mutex_valid = -1; + #ifdef WOLFSSL_CLEANUP_THREADSAFE + (void)wolfSSL_Atomic_Int_FetchSub(&inits_count_mutex_valid2, 1); + #endif + return BAD_MUTEX_E; + } + else { + inits_count_mutex_valid = 1; + } } } #endif /* !WOLFSSL_MUTEX_INITIALIZER */ @@ -10422,7 +10463,7 @@ int wolfSSL_Cleanup(void) #endif #endif /* !NO_SESSION_CACHE */ -#ifndef WOLFSSL_MUTEX_INITIALIZER +#if !defined(WOLFSSL_CLEANUP_THREADSAFE) && !defined(WOLFSSL_MUTEX_INITIALIZER) if ((inits_count_mutex_valid == 1) && (wc_FreeMutex(&inits_count_mutex) != 0)) { if (ret == WOLFSSL_SUCCESS) diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index eec259ecba..49a64225af 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -320,6 +320,10 @@ #endif /* SINGLE_THREADED */ +#ifdef WOLFSSL_TEST_NO_MUTEX_INITIALIZER + #undef WOLFSSL_MUTEX_INITIALIZER +#endif + #ifdef WOLFSSL_MUTEX_INITIALIZER #define WOLFSSL_MUTEX_INITIALIZER_CLAUSE(lockname) = WOLFSSL_MUTEX_INITIALIZER(lockname) #else From 524f0f5799f0c081b63490a1bd942e391c0f45d1 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Tue, 12 Nov 2024 23:57:35 -0600 Subject: [PATCH 2/3] peer review on "WOLFSSL_CLEANUP_THREADSAFE": * add WOLFSSL_ATOMIC_INITIALIZER() to wc_port.h; * rename feature macro to WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS for clarity; * remove spin lock logic in wolfSSL_Init() and instead return DEADLOCK_AVERTED_E on contended initialization; * unless WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS is user-defined to 0, automatically enable it when appropriate. --- src/ssl.c | 78 +++++++++++++++++++------------------ wolfssl/wolfcrypt/wc_port.h | 3 ++ 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 7fa6b6f9b4..bf204d373e 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -5641,15 +5641,31 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) static int wolfSSL_RAND_InitMutex(void); #endif -#if defined(WOLFSSL_CLEANUP_THREADSAFE) && !defined(WOLFSSL_MUTEX_INITIALIZER) +/* If we don't have static mutex initializers, but we do have static atomic + * initializers, activate WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS to leverage + * the latter. + */ +#ifndef WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS + #if !defined(WOLFSSL_MUTEX_INITIALIZER) && !defined(SINGLE_THREADED) && \ + defined(WOLFSSL_ATOMIC_OPS) && defined(WOLFSSL_ATOMIC_INITIALIZER) + #define WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS 1 + #else + #define WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS 0 + #endif +#elif defined(WOLFSSL_MUTEX_INITIALIZER) || defined(SINGLE_THREADED) + #undef WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS + #define WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS 0 +#endif + +#if WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS #ifndef WOLFSSL_ATOMIC_OPS - #error WOLFSSL_CLEANUP_THREADSAFE with !WOLFSSL_MUTEX_INITIALIZER requires WOLFSSL_ATOMIC_OPS + #error WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS with !WOLFSSL_MUTEX_INITIALIZER requires WOLFSSL_ATOMIC_OPS #endif - /* WOLFSSL_CLEANUP_THREADSAFE depends on a wolfSSL_Atomic_Int that can - * be statically initialized. - */ - static wolfSSL_Atomic_Int inits_count_mutex_valid2 = 0; -#endif /* WOLFSSL_CLEANUP_THREADSAFE && !WOLFSSL_MUTEX_INITIALIZER */ + #ifndef WOLFSSL_ATOMIC_INITIALIZER + #error WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS with !WOLFSSL_MUTEX_INITIALIZER requires WOLFSSL_ATOMIC_INITIALIZER + #endif + static wolfSSL_Atomic_Int inits_count_mutex_valid2 = WOLFSSL_ATOMIC_INITIALIZER(0); +#endif /* WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS && !WOLFSSL_MUTEX_INITIALIZER */ #if defined(OPENSSL_EXTRA) && defined(HAVE_ATEXIT) static void AtExitCleanup(void) @@ -5657,7 +5673,7 @@ static void AtExitCleanup(void) if (initRefCount > 0) { initRefCount = 1; (void)wolfSSL_Cleanup(); -#if defined(WOLFSSL_CLEANUP_THREADSAFE) && !defined(WOLFSSL_MUTEX_INITIALIZER) +#if WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS if (inits_count_mutex_valid == 1) { (void)wc_FreeMutex(&inits_count_mutex); inits_count_mutex_valid = 0; @@ -5679,37 +5695,22 @@ int wolfSSL_Init(void) WOLFSSL_ENTER("wolfSSL_Init"); #ifndef WOLFSSL_MUTEX_INITIALIZER - if (inits_count_mutex_valid <= 0) { - #ifdef WOLFSSL_CLEANUP_THREADSAFE - int current_inits_count_mutex_valid; + if (inits_count_mutex_valid == 0) { + #if WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS if (wolfSSL_Atomic_Int_FetchAdd(&inits_count_mutex_valid2, 1) != 0) { - /* We treat inits_count_mutex_valid as a spin lock -- this may cause - * deadlocks in some runtimes. Applications can fully mitigate this - * race by calling wolfSSL_Init() and wolfSSL_Cleanup() - * consecutively at startup, uncontended. This leaves - * inits_count_mutex safely initialized, but releases all other - * resources. - */ - while ((current_inits_count_mutex_valid = inits_count_mutex_valid) == 0); - if (current_inits_count_mutex_valid < 0) { - (void)wolfSSL_Atomic_Int_FetchSub(&inits_count_mutex_valid2, 1); - return BAD_MUTEX_E; - } - } - else - #endif /* WOLFSSL_CLEANUP_THREADSAFE */ - { - if (wc_InitMutex(&inits_count_mutex) != 0) { - WOLFSSL_MSG("Bad Init Mutex count"); - inits_count_mutex_valid = -1; - #ifdef WOLFSSL_CLEANUP_THREADSAFE - (void)wolfSSL_Atomic_Int_FetchSub(&inits_count_mutex_valid2, 1); + (void)wolfSSL_Atomic_Int_FetchSub(&inits_count_mutex_valid2, 1); + return DEADLOCK_AVERTED_E; + } + #endif /* WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS */ + if (wc_InitMutex(&inits_count_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex count"); + #if WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS + (void)wolfSSL_Atomic_Int_FetchSub(&inits_count_mutex_valid2, 1); #endif - return BAD_MUTEX_E; - } - else { - inits_count_mutex_valid = 1; - } + return BAD_MUTEX_E; + } + else { + inits_count_mutex_valid = 1; } } #endif /* !WOLFSSL_MUTEX_INITIALIZER */ @@ -10463,7 +10464,8 @@ int wolfSSL_Cleanup(void) #endif #endif /* !NO_SESSION_CACHE */ -#if !defined(WOLFSSL_CLEANUP_THREADSAFE) && !defined(WOLFSSL_MUTEX_INITIALIZER) +#if !defined(WOLFSSL_MUTEX_INITIALIZER) && \ + !WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS if ((inits_count_mutex_valid == 1) && (wc_FreeMutex(&inits_count_mutex) != 0)) { if (ret == WOLFSSL_SUCCESS) diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index 49a64225af..002e9d4053 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -340,6 +340,7 @@ #if defined(__GNUC__) && defined(__ATOMIC_RELAXED) /* C++ using direct calls to compiler built-in functions */ typedef volatile int wolfSSL_Atomic_Int; + #define WOLFSSL_ATOMIC_INITIALIZER(x) (x) #define WOLFSSL_ATOMIC_OPS #endif #else @@ -347,6 +348,7 @@ /* Default C Implementation */ #include typedef atomic_int wolfSSL_Atomic_Int; + #define WOLFSSL_ATOMIC_INITIALIZER(x) (x) #define WOLFSSL_ATOMIC_OPS #endif /* WOLFSSL_HAVE_ATOMIC_H */ #endif @@ -358,6 +360,7 @@ #include #endif typedef volatile long wolfSSL_Atomic_Int; + #define WOLFSSL_ATOMIC_INITIALIZER(x) (x) #define WOLFSSL_ATOMIC_OPS #endif #endif /* WOLFSSL_NO_ATOMICS */ From 0ebd86d668faa45724045df0bd648dcfcc8efbce Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Wed, 13 Nov 2024 13:01:00 -0600 Subject: [PATCH 3/3] add second wolfCrypt error code span, and add DEADLOCK_AVERTED_E. --- src/internal.c | 6 ++-- src/ssl.c | 39 ++++++++++++++++++-------- support/gen-debug-trace-error-codes.sh | 10 ++++--- tests/api.c | 12 ++++---- wolfcrypt/src/error.c | 6 ++-- wolfcrypt/test/test.c | 6 ++-- wolfssl/error-ssl.h | 4 +++ wolfssl/wolfcrypt/error-crypt.h | 29 ++++++++++++++++--- 8 files changed, 81 insertions(+), 31 deletions(-) diff --git a/src/internal.c b/src/internal.c index fc0139e2ee..976602c762 100644 --- a/src/internal.c +++ b/src/internal.c @@ -25672,7 +25672,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) } /* pass to wolfCrypt */ - if (error <= WC_FIRST_E && error >= WC_LAST_E) { + if ((error <= WC_SPAN1_FIRST_E && error >= WC_SPAN1_MIN_CODE_E) || + (error <= WC_SPAN2_FIRST_E && error >= WC_SPAN2_MIN_CODE_E)) + { return wc_GetErrorString(error); } @@ -25684,7 +25686,7 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) #endif } - switch ((enum wolfSSL_ErrorCodes)error) { + switch ((enum wolfSSL_ErrorCodes)error) { /* // NOLINT(clang-analyzer-optin.core.EnumCastOutOfRange) */ case UNSUPPORTED_SUITE : return "unsupported cipher suite"; diff --git a/src/ssl.c b/src/ssl.c index bf204d373e..ded632e4f6 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -5644,6 +5644,8 @@ static int wolfSSL_RAND_InitMutex(void); /* If we don't have static mutex initializers, but we do have static atomic * initializers, activate WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS to leverage * the latter. + * + * See further explanation below in wolfSSL_Init(). */ #ifndef WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS #if !defined(WOLFSSL_MUTEX_INITIALIZER) && !defined(SINGLE_THREADED) && \ @@ -5659,12 +5661,13 @@ static int wolfSSL_RAND_InitMutex(void); #if WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS #ifndef WOLFSSL_ATOMIC_OPS - #error WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS with !WOLFSSL_MUTEX_INITIALIZER requires WOLFSSL_ATOMIC_OPS + #error WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS requires WOLFSSL_ATOMIC_OPS #endif #ifndef WOLFSSL_ATOMIC_INITIALIZER - #error WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS with !WOLFSSL_MUTEX_INITIALIZER requires WOLFSSL_ATOMIC_INITIALIZER + #error WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS requires WOLFSSL_ATOMIC_INITIALIZER #endif - static wolfSSL_Atomic_Int inits_count_mutex_valid2 = WOLFSSL_ATOMIC_INITIALIZER(0); + static wolfSSL_Atomic_Int inits_count_mutex_atomic_initing_flag = + WOLFSSL_ATOMIC_INITIALIZER(0); #endif /* WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS && !WOLFSSL_MUTEX_INITIALIZER */ #if defined(OPENSSL_EXTRA) && defined(HAVE_ATEXIT) @@ -5677,7 +5680,7 @@ static void AtExitCleanup(void) if (inits_count_mutex_valid == 1) { (void)wc_FreeMutex(&inits_count_mutex); inits_count_mutex_valid = 0; - inits_count_mutex_valid2 = 0; + inits_count_mutex_atomic_initing_flag = 0; } #endif } @@ -5697,15 +5700,29 @@ int wolfSSL_Init(void) #ifndef WOLFSSL_MUTEX_INITIALIZER if (inits_count_mutex_valid == 0) { #if WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS - if (wolfSSL_Atomic_Int_FetchAdd(&inits_count_mutex_valid2, 1) != 0) { - (void)wolfSSL_Atomic_Int_FetchSub(&inits_count_mutex_valid2, 1); + + /* Without this mitigation, if two threads enter wolfSSL_Init() at the + * same time, and both see zero inits_count_mutex_valid, then both will + * run wc_InitMutex(&inits_count_mutex), leading to process corruption + * or (best case) a resource leak. + * + * When WOLFSSL_ATOMIC_INITIALIZER() is available, we can mitigate this + * by use an atomic counting int as a mutex. + */ + + if (wolfSSL_Atomic_Int_FetchAdd(&inits_count_mutex_atomic_initing_flag, + 1) != 0) + { + (void)wolfSSL_Atomic_Int_FetchSub( + &inits_count_mutex_atomic_initing_flag, 1); return DEADLOCK_AVERTED_E; } #endif /* WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS */ if (wc_InitMutex(&inits_count_mutex) != 0) { WOLFSSL_MSG("Bad Init Mutex count"); #if WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS - (void)wolfSSL_Atomic_Int_FetchSub(&inits_count_mutex_valid2, 1); + (void)wolfSSL_Atomic_Int_FetchSub( + &inits_count_mutex_atomic_initing_flag, 1); #endif return BAD_MUTEX_E; } @@ -15772,11 +15789,11 @@ int wolfSSL_ERR_GET_REASON(unsigned long err) return ASN1_R_HEADER_TOO_LONG; #endif - /* check if error value is in range of wolfSSL errors */ + /* check if error value is in range of wolfCrypt or wolfSSL errors */ ret = 0 - ret; /* setting as negative value */ - /* wolfCrypt range is less than MAX (-100) - wolfSSL range is MIN (-300) and lower */ - if ((ret <= WC_FIRST_E && ret >= WC_LAST_E) || + + if ((ret <= WC_SPAN1_FIRST_E && ret >= WC_SPAN1_LAST_E) || + (ret <= WC_SPAN2_FIRST_E && ret >= WC_SPAN2_LAST_E) || (ret <= WOLFSSL_FIRST_E && ret >= WOLFSSL_LAST_E)) { return ret; diff --git a/support/gen-debug-trace-error-codes.sh b/support/gen-debug-trace-error-codes.sh index 0b181ae38e..540a95273b 100755 --- a/support/gen-debug-trace-error-codes.sh +++ b/support/gen-debug-trace-error-codes.sh @@ -20,10 +20,12 @@ BEGIN { if ((errcode_a[1] == "MIN_CODE_E") || (errcode_a[1] == "MAX_CODE_E") || - (errcode_a[1] == "WC_FIRST_E") || - (errcode_a[1] == "WC_LAST_E") || - (errcode_a[1] == "WOLFSSL_FIRST_E") || - (errcode_a[1] == "WOLFSSL_LAST_E")) + (errcode_a[1] ~ "WC.*MIN_CODE_E") || + (errcode_a[1] ~ "WC.*MAX_CODE_E") || + (errcode_a[1] ~ "WC.*_FIRST_E") || + (errcode_a[1] ~ "WC.*_LAST_E") || + (errcode_a[1] ~ "WOLFSSL.*_FIRST_E") || + (errcode_a[1] ~ "WOLFSSL.*_LAST_E")) { next; } diff --git a/tests/api.c b/tests/api.c index 8136bdbc9b..9eb879c737 100644 --- a/tests/api.c +++ b/tests/api.c @@ -89866,9 +89866,9 @@ static int error_test(void) { -15, -17 }, { -19, -19 }, { -26, -27 }, - { -30, WC_FIRST_E+1 }, + { -30, WC_SPAN1_FIRST_E + 1 }, #else - { -9, WC_FIRST_E+1 }, + { -9, WC_SPAN1_FIRST_E + 1 }, #endif { -124, -124 }, { -166, -169 }, @@ -89879,14 +89879,15 @@ static int error_test(void) { -358, -358 }, { -384, -384 }, { -466, -499 }, - { WOLFSSL_LAST_E-1, WOLFSSL_LAST_E-1 } + { WOLFSSL_LAST_E - 1, WC_SPAN2_FIRST_E + 1 }, + { WC_SPAN2_LAST_E - 1, MIN_CODE_E } }; /* Check that all errors have a string and it's the same through the two * APIs. Check that the values that are not errors map to the unknown * string. */ - for (i = 0; i >= WOLFSSL_LAST_E-1; i--) { + for (i = 0; i >= MIN_CODE_E; i--) { int this_missing = 0; for (j = 0; j < (int)XELEM_CNT(missing); ++j) { if ((i <= missing[j].first) && (i >= missing[j].last)) { @@ -89948,8 +89949,7 @@ static int test_wolfSSL_ERR_strings(void) ExpectNotNull(err = wolfSSL_ERR_func_error_string(WC_NO_ERR_TRACE((word32)UNSUPPORTED_SUITE))); ExpectIntEQ((*err == '\0'), 1); - /* The value -MIN_CODE_E+2 is PEM_R_PROBLEMS_GETTING_PASSWORD. */ - ExpectNotNull(err = wolfSSL_ERR_lib_error_string(-MIN_CODE_E+2)); + ExpectNotNull(err = wolfSSL_ERR_lib_error_string(-WOLFSSL_PEM_R_PROBLEMS_GETTING_PASSWORD_E)); ExpectIntEQ((*err == '\0'), 1); #endif #endif diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index deedcbe1a6..a87289371c 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -642,11 +642,14 @@ const char* wc_GetErrorString(int error) case PBKDF2_KAT_FIPS_E: return "wolfCrypt FIPS PBKDF2 Known Answer Test Failure"; + case DEADLOCK_AVERTED_E: + return "Deadlock averted -- retry the call"; + case MAX_CODE_E: + case WC_SPAN1_MIN_CODE_E: case MIN_CODE_E: default: return "unknown error number"; - } } @@ -660,4 +663,3 @@ void wc_ErrorString(int error, char* buffer) buffer[WOLFSSL_MAX_ERROR_SZ-1] = 0; } #endif /* !NO_ERROR_STRINGS */ - diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 5a42966e02..0afb0422e5 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -2777,14 +2777,16 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t error_test(void) int last; } missing[] = { { -124, -124 }, - { -166, -169 } + { -166, -169 }, + { WC_SPAN1_LAST_E - 1, WC_SPAN2_FIRST_E + 1 }, + { WC_SPAN2_LAST_E - 1, WC_SPAN2_MIN_CODE_E } }; /* Check that all errors have a string and it's the same through the two * APIs. Check that the values that are not errors map to the unknown * string. */ - for (i = WC_FIRST_E; i >= WC_LAST_E; i--) { + for (i = WC_SPAN1_FIRST_E; i >= WC_SPAN2_MIN_CODE_E; i--) { int this_missing = 0; for (j = 0; j < (int)XELEM_CNT(missing); ++j) { if ((i <= missing[j].first) && (i >= missing[j].last)) { diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index fe6ee78d04..a819103da6 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -233,8 +233,12 @@ enum wolfSSL_ErrorCodes { WOLFSSL_EVP_R_PRIVATE_KEY_DECODE_ERROR = -515, WOLFSSL_LAST_E = -515 + + /* codes -1000 to -1999 are reserved for wolfCrypt. */ }; +wc_static_assert((int)WC_LAST_E <= (int)WOLFSSL_LAST_E); + /* I/O Callback default errors */ enum IOerrors { WOLFSSL_CBIO_ERR_GENERAL = -1, /* general unexpected err */ diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 3f188f7444..337443c129 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -47,8 +47,10 @@ enum wolfCrypt_ErrorCodes { * reasons of backward compatibility. */ - MAX_CODE_E = -96, /* errors -97 - -299 */ - WC_FIRST_E = -97, /* errors -97 - -299 */ + MAX_CODE_E = -96, /* WC_FIRST_E + 1, for backward compat. */ + WC_FIRST_E = -97, /* First code used for wolfCrypt */ + + WC_SPAN1_FIRST_E = -97, /* errors -97 - -300 */ MP_MEM = -97, /* MP dynamic memory allocation failed. */ MP_VAL = -98, /* MP value passed is not able to be used. */ @@ -290,13 +292,32 @@ enum wolfCrypt_ErrorCodes { SM4_GCM_AUTH_E = -298, /* SM4-GCM Authentication check failure */ SM4_CCM_AUTH_E = -299, /* SM4-CCM Authentication check failure */ - WC_LAST_E = -299, /* Update this to indicate last error */ - MIN_CODE_E = -300 /* errors -2 - -299 */ + WC_SPAN1_LAST_E = -299, /* Last used code in span 1 */ + WC_SPAN1_MIN_CODE_E = -300, /* Last usable code in span 1 */ + + WC_SPAN2_FIRST_E = -1000, + + DEADLOCK_AVERTED_E = -1000, /* Deadlock averted -- retry the call */ + + WC_SPAN2_LAST_E = -1000, /* Update to indicate last used error code */ + WC_SPAN2_MIN_CODE_E = -1999, /* Last usable code in span 2 */ + + WC_LAST_E = -1000, /* the last code used either here or in + * error-ssl.h + */ + + MIN_CODE_E = -1999 /* the last code allocated either here or in + * error-ssl.h + */ /* add new companion error id strings for any new error codes wolfcrypt/src/error.c !!! */ }; +wc_static_assert((int)WC_LAST_E <= (int)WC_SPAN2_LAST_E); +wc_static_assert((int)MIN_CODE_E <= (int)WC_LAST_E); +wc_static_assert((int)MIN_CODE_E <= (int)WC_SPAN2_MIN_CODE_E); + #ifdef NO_ERROR_STRINGS #define wc_GetErrorString(error) "no support for error strings built in" #define wc_ErrorString(err, buf) \