From 8e7426ad514d52cf51603e992f2bea116428f45f Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 14 Aug 2026 16:35:47 -0500 Subject: [PATCH 1/9] linuxkm/linuxkm_wc_port.h: * reduce WC_LINUXKM_MAX_NS_WITHOUT_YIELD from 1 second to 25 ms for better kernel citizenship. * add WC_DEBUG_FORCE_KERNEL_SETTINGS for inhibiting #errors on unsupported configurations. * add __extension__ annotation to macros that need it. * add wc_svr_disallowed_count_reset() and wc_svr_disallowed_count_current(). * fix CAN_SAVE_VECTOR_REGISTERS() to honor DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_{ON,OFF}. * add WC_RELAX_LONG_LOOP() to DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_OFF variant of SAVE_VECTOR_REGISTERS2(). * allow for fully user-supplied SAVE_VECTOR_REGISTERS() and friends. --- linuxkm/linuxkm_wc_port.h | 82 ++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/linuxkm/linuxkm_wc_port.h b/linuxkm/linuxkm_wc_port.h index fdb42e2b5bd..4b3744a0aae 100644 --- a/linuxkm/linuxkm_wc_port.h +++ b/linuxkm/linuxkm_wc_port.h @@ -31,7 +31,7 @@ #include #include - #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) + #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) && !defined(WC_DEBUG_FORCE_KERNEL_SETTINGS) #error Unsupported kernel. #endif @@ -53,7 +53,8 @@ #endif #endif - #if defined(HAVE_FIPS) && defined(LINUXKM_LKCAPI_REGISTER_AESXTS) && defined(WC_LINUX_CONFIG_SELFTESTS_FULL) + #if defined(HAVE_FIPS) && defined(LINUXKM_LKCAPI_REGISTER_AESXTS) && defined(WC_LINUX_CONFIG_SELFTESTS_FULL) && \ + !defined(WC_DEBUG_FORCE_KERNEL_SETTINGS) /* CONFIG_CRYPTO_MANAGER_EXTRA_TESTS expects AES-XTS-384 to work, even when CONFIG_CRYPTO_FIPS, but FIPS 140-3 only allows AES-XTS-256 and AES-XTS-512. */ #error CONFIG_CRYPTO_MANAGER_EXTRA_TESTS is incompatible with FIPS wolfCrypt AES-XTS -- please reconfigure the target kernel to disable CONFIG_CRYPTO_MANAGER_EXTRA_TESTS/CONFIG_CRYPTO_SELFTESTS_FULL. #endif @@ -70,7 +71,8 @@ defined(HAVE_ECC) && \ (defined(LINUXKM_LKCAPI_REGISTER_ALL) || \ defined(LINUXKM_LKCAPI_REGISTER_ECDSA) || \ - (defined(LINUXKM_LKCAPI_REGISTER_ALL_KCONFIG) && defined(CONFIG_CRYPTO_ECDSA))) + (defined(LINUXKM_LKCAPI_REGISTER_ALL_KCONFIG) && defined(CONFIG_CRYPTO_ECDSA))) && \ + !defined(WC_DEBUG_FORCE_KERNEL_SETTINGS) #error Target kernel requires SHA-1 signature verification support. #endif @@ -125,7 +127,7 @@ * also needed to suppress inclusion of stdlib.h in * wolfssl/wolfcrypt/types.h. */ - #define XATOI(s) ({ \ + #define XATOI(s) __extension__ ({ \ long long _xatoi_res = 0; \ int _xatoi_ret = kstrtoll(s, 10, &_xatoi_res); \ if (_xatoi_ret != 0) { \ @@ -212,7 +214,7 @@ WOLFSSL_API int wc_linuxkm_sig_ignore_end(void); WOLFSSL_API int wc_linuxkm_check_for_intr_signals(void); #ifndef WC_LINUXKM_MAX_NS_WITHOUT_YIELD - #define WC_LINUXKM_MAX_NS_WITHOUT_YIELD 1000000000 + #define WC_LINUXKM_MAX_NS_WITHOUT_YIELD (25 * 1000 * 1000) #endif WOLFSSL_API void wc_linuxkm_relax_long_loop(void); @@ -833,12 +835,25 @@ #endif #endif #ifndef CAN_SAVE_VECTOR_REGISTERS - #define CAN_SAVE_VECTOR_REGISTERS() wc_can_save_vector_registers_x86() + #if defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_OFF) + #define CAN_SAVE_VECTOR_REGISTERS() 0 + #elif defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON) + #define CAN_SAVE_VECTOR_REGISTERS() 1 + #else + #define CAN_SAVE_VECTOR_REGISTERS() wc_can_save_vector_registers_x86() + #endif #endif #if defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON) && \ - defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_OFF) - #error Conflicting settings for DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_foo + defined(LINUXKM_LKCAPI_REGISTER) && \ + !defined(WC_DEBUG_FORCE_KERNEL_SETTINGS) + #error DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON is incompatible with LINUXKM_LKCAPI_REGISTER. + #endif + + #if defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_OFF) && \ + defined(WOLFSSL_LINUXKM_BENCHMARKS) && \ + !defined(WC_DEBUG_FORCE_KERNEL_SETTINGS) + #error DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_OFF is incompatible with WOLFSSL_LINUXKM_BENCHMARKS. #endif #ifndef SAVE_VECTOR_REGISTERS @@ -879,7 +894,7 @@ #endif #ifndef SAVE_VECTOR_REGISTERS2 #if defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON) - #define SAVE_VECTOR_REGISTERS2() \ + #define SAVE_VECTOR_REGISTERS2() __extension__ \ ({ \ int _svr_ret = wc_save_vector_registers_x86(WC_SVR_FLAG_NONE); \ if (_svr_ret != 0) { \ @@ -890,7 +905,10 @@ _svr_ret; \ }) #elif defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_OFF) - #define SAVE_VECTOR_REGISTERS2() WC_ACCEL_INHIBIT_E + #define SAVE_VECTOR_REGISTERS2() __extension__ ({ \ + WC_RELAX_LONG_LOOP(); \ + WC_ACCEL_INHIBIT_E; \ + }) #elif defined(DEBUG_VECTOR_REGISTER_ACCESS_FUZZING) #define SAVE_VECTOR_REGISTERS2() wc_save_vector_registers_x86(WC_SVR_FLAG_FUZZ) #else @@ -907,7 +925,7 @@ * DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON build -- ERROR if any * calls occur. */ - #define DISABLE_VECTOR_REGISTERS() \ + #define DISABLE_VECTOR_REGISTERS() __extension__ \ ({ \ pr_err("ERROR: DISABLE_VECTOR_REGISTERS() with DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON " \ "in %s at %s L %d\n", __func__, __FILE__, __LINE__); \ @@ -923,7 +941,10 @@ #endif #ifndef SAVE_VECTOR_REGISTERS_MAYBE_INHIBIT - #ifdef DEBUG_VECTOR_REGISTER_ACCESS_FUZZING + #if (defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON) || \ + defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_OFF)) + #define SAVE_VECTOR_REGISTERS_MAYBE_INHIBIT() SAVE_VECTOR_REGISTERS2() + #elif defined(DEBUG_VECTOR_REGISTER_ACCESS_FUZZING) #define SAVE_VECTOR_REGISTERS_MAYBE_INHIBIT() wc_save_vector_registers_x86(WC_SVR_FLAG_FUZZ | WC_SVR_FLAG_MAYBE_INHIBIT) #else #define SAVE_VECTOR_REGISTERS_MAYBE_INHIBIT() wc_save_vector_registers_x86(WC_SVR_FLAG_MAYBE_INHIBIT) @@ -969,7 +990,14 @@ #define RESTORE_VECTOR_REGISTERS() restore_vector_registers_arm() #endif - #elif defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) + #elif (defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && \ + (!defined(SAVE_VECTOR_REGISTERS) || \ + !defined(SAVE_VECTOR_REGISTERS2) || \ + !defined(RESTORE_VECTOR_REGISTERS) || \ + !defined(DISABLE_VECTOR_REGISTERS) || \ + !defined(REENABLE_VECTOR_REGISTERS) || \ + !defined(SAVE_VECTOR_REGISTERS_MAYBE_INHIBIT) || \ + !defined(RESTORE_VECTOR_REGISTERS_MAYBE_INHIBITED))) #error WOLFSSL_USE_SAVE_VECTOR_REGISTERS is set for an unimplemented architecture. #endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS */ @@ -1325,7 +1353,7 @@ typeof(wc_linuxkm_free_svr_states) *wc_linuxkm_free_svr_states; typeof(wc_restore_vector_registers_x86) *wc_restore_vector_registers_x86; typeof(wc_save_vector_registers_x86) *wc_save_vector_registers_x86; - #else /* !CONFIG_X86 */ + #elif !defined(WC_DEBUG_FORCE_KERNEL_SETTINGS) /* !CONFIG_X86 */ #error WOLFSSL_USE_SAVE_VECTOR_REGISTERS is set for an unimplemented architecture. #endif /* arch */ @@ -1684,7 +1712,7 @@ #define wc_linuxkm_free_svr_states WC_PIE_INDIRECT_SYM(wc_linuxkm_free_svr_states) #define wc_restore_vector_registers_x86 WC_PIE_INDIRECT_SYM(wc_restore_vector_registers_x86) #define wc_save_vector_registers_x86 WC_PIE_INDIRECT_SYM(wc_save_vector_registers_x86) - #elif defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) + #elif defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && !defined(WC_DEBUG_FORCE_KERNEL_SETTINGS) #error WOLFSSL_USE_SAVE_VECTOR_REGISTERS is set for an unimplemented architecture. #endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS */ @@ -1810,10 +1838,10 @@ #if defined(WOLFSSL_KERNEL_STACK_DEBUG) || defined(WC_LINUXKM_STACK_DEBUG) - #ifndef CONFIG_THREAD_INFO_IN_TASK + #if !defined(CONFIG_THREAD_INFO_IN_TASK) && !defined(WC_DEBUG_FORCE_KERNEL_SETTINGS) #error WC_LINUXKM_STACK_DEBUG requires CONFIG_THREAD_INFO_IN_TASK #endif - #ifdef CONFIG_STACK_GROWSUP + #if defined(CONFIG_STACK_GROWSUP) && !defined(WC_DEBUG_FORCE_KERNEL_SETTINGS) #error WC_LINUXKM_STACK_DEBUG requires !CONFIG_STACK_GROWSUP #endif @@ -2035,7 +2063,7 @@ #ifndef REENABLE_VECTOR_REGISTERS #define REENABLE_VECTOR_REGISTERS() wc_restore_vector_registers_x86(WC_SVR_FLAG_INHIBIT) #endif - #else /* !CONFIG_X86 */ + #elif !defined(WC_DEBUG_FORCE_KERNEL_SETTINGS) /* !CONFIG_X86 */ #error WOLFSSL_USE_SAVE_VECTOR_REGISTERS is set for an unimplemented architecture. #endif /* !CONFIG_X86 */ #endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS */ @@ -2059,7 +2087,7 @@ #ifdef WOLFSSL_LINUXKM_USE_MUTEXES #define WC_MUTEX_OPS_INLINE - #ifdef LINUXKM_LKCAPI_REGISTER + #if defined(LINUXKM_LKCAPI_REGISTER) && !defined(WC_DEBUG_FORCE_KERNEL_SETTINGS) /* must use spin locks when registering implementations with the * kernel, because mutexes are forbidden when calling with nonzero * irq_count(). @@ -2271,23 +2299,23 @@ #endif #ifdef WOLFSSL_TRACK_MEMORY - #define XMALLOC(s, h, t) ({(void)(h); (void)(t); wolfSSL_Malloc(s);}) + #define XMALLOC(s, h, t) __extension__ ({(void)(h); (void)(t); wolfSSL_Malloc(s);}) #ifdef WOLFSSL_XFREE_NO_NULLNESS_CHECK - #define XFREE(p, h, t) ({(void)(h); (void)(t); wolfSSL_Free(p);}) + #define XFREE(p, h, t) __extension__ ({(void)(h); (void)(t); wolfSSL_Free(p);}) #else - #define XFREE(p, h, t) ({void* _xp; (void)(h); _xp = (p); if(_xp) wolfSSL_Free(_xp);}) + #define XFREE(p, h, t) __extension__ ({void* _xp; (void)(h); _xp = (p); if(_xp) wolfSSL_Free(_xp);}) #endif - #define XREALLOC(p, n, h, t) ({(void)(h); (void)(t); wolfSSL_Realloc(p, n);}) + #define XREALLOC(p, n, h, t) __extension__ ({(void)(h); (void)(t); wolfSSL_Realloc(p, n);}) #else #if !defined(XMALLOC_USER) && !defined(XMALLOC_OVERRIDE) - #define XMALLOC(s, h, t) ({(void)(h); (void)(t); malloc(s);}) + #define XMALLOC(s, h, t) __extension__ ({(void)(h); (void)(t); malloc(s);}) #ifdef WOLFSSL_XFREE_NO_NULLNESS_CHECK - #define XFREE(p, h, t) ({(void)(h); (void)(t); free(p);}) + #define XFREE(p, h, t) __extension__ ({(void)(h); (void)(t); free(p);}) #else - #define XFREE(p, h, t) ({void* _xp; (void)(h); (void)(t); _xp = (p); if(_xp) free(_xp);}) + #define XFREE(p, h, t) __extension__ ({void* _xp; (void)(h); (void)(t); _xp = (p); if(_xp) free(_xp);}) #endif #if defined(USE_KVREALLOC) || !defined(USE_KVMALLOC) - #define XREALLOC(p, n, h, t) ({(void)(h); (void)(t); realloc(p, n);}) + #define XREALLOC(p, n, h, t) __extension__ ({(void)(h); (void)(t); realloc(p, n);}) #endif #endif /* !XMALLOC_USER && !XMALLOC_OVERRIDE */ #endif From 925b401843012f2d46e43fe6e1de2e5f4c12788a Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 14 Aug 2026 16:36:00 -0500 Subject: [PATCH 2/9] linuxkm/module_hooks.c: * add WOLFSSL_DEBUG_TRACE_ERROR_CODES coverage for all system error codes used by module_hooks.c and its includes. * implement double-run wolfCrypt_IntegrityTest_fips() and wc_RunAllCast_fips() in WC_C_DYNAMIC_FALLBACK configurations, once with acceleration on (leveraging fallback instrumentation to fail the module if any fallbacks occur), and once with it forced off using DISABLE_VECTOR_REGISTERS(). --- linuxkm/module_hooks.c | 173 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 1 deletion(-) diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index c661cbe65d4..000de2b2cc2 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -63,16 +63,61 @@ enum linux_errcodes { my_EINVAL = EINVAL, my_ENOMEM = ENOMEM, - my_EBADMSG = EBADMSG + my_EBADMSG = EBADMSG, + my_ENOKEY = ENOKEY, + my_EFAULT = EFAULT, + my_EAFNOSUPPORT = EAFNOSUPPORT, + my_EOVERFLOW = EOVERFLOW, + my_EOPNOTSUPP = EOPNOTSUPP, + my_EDEADLK = EDEADLK, + my_EAGAIN = EAGAIN, + my_EBUSY = EBUSY, + my_ECANCELED = ECANCELED, + my_EINTR = EINTR, + my_ELIBBAD = ELIBBAD, + my_ENODATA = ENODATA, + my_ENODEV = ENODEV, + my_EPERM = EPERM, + my_EFBIG = EFBIG }; #undef EINVAL #undef ENOMEM #undef EBADMSG + #undef ENOKEY + #undef EFAULT + #undef EAFNOSUPPORT + #undef EOVERFLOW + #undef EOPNOTSUPP + #undef EDEADLK + #undef EAGAIN + #undef EBUSY + #undef ECANCELED + #undef EINTR + #undef ELIBBAD + #undef ENODATA + #undef ENODEV + #undef EPERM + #undef EFBIG #define EINVAL WC_ERR_TRACE(my_EINVAL) #define ENOMEM WC_ERR_TRACE(my_ENOMEM) #define EBADMSG WC_ERR_TRACE(my_EBADMSG) + #define ENOKEY WC_ERR_TRACE(my_ENOKEY) + #define EFAULT WC_ERR_TRACE(my_EFAULT) + #define EAFNOSUPPORT WC_ERR_TRACE(my_EAFNOSUPPORT) + #define EOVERFLOW WC_ERR_TRACE(my_EOVERFLOW) + #define EOPNOTSUPP WC_ERR_TRACE(my_EOPNOTSUPP) + #define EDEADLK WC_ERR_TRACE(my_EDEADLK) + #define EAGAIN WC_ERR_TRACE(my_EAGAIN) + #define EBUSY WC_ERR_TRACE(my_EBUSY) + #define ECANCELED WC_ERR_TRACE(my_ECANCELED) + #define EINTR WC_ERR_TRACE(my_EINTR) + #define ELIBBAD WC_ERR_TRACE(my_ELIBBAD) + #define ENODATA WC_ERR_TRACE(my_ENODATA) + #define ENODEV WC_ERR_TRACE(my_ENODEV) + #define EPERM WC_ERR_TRACE(my_EPERM) + #define EFBIG WC_ERR_TRACE(my_EFBIG) #endif static int libwolfssl_cleanup(void) { @@ -849,6 +894,14 @@ static int wolfssl_init(void) reloc_counts.other = 0; #endif + /* In asm builds, we run the FIPS self-test twice, once via fipsEntry() checking + * afterwards that no C fallbacks occurred, and a second time via + * wolfCrypt_IntegrityTest_fips() with asm disabled. + */ + +#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) + wc_svr_disallowed_count_reset(); +#endif if (WC_SIG_IGNORE_BEGIN() >= 0) { fipsEntry(); (void)WC_SIG_IGNORE_END(); @@ -878,6 +931,44 @@ static int wolfssl_init(void) } return -ECANCELED; } + +#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) + { + long long unsigned int svr_disallowed_count = wc_svr_disallowed_count_current(); + if (svr_disallowed_count > 0) { + pr_err("ERROR: wc_svr_disallowed_count_current() returned %llu after fipsEntry().\n", svr_disallowed_count); + return -ECANCELED; + } + + ret = DISABLE_VECTOR_REGISTERS(); + if (ret != 0) { + pr_err("ERROR: DISABLE_VECTOR_REGISTERS() for wolfCrypt_IntegrityTest_fips() returned %d.\n", ret); + return -ECANCELED; + } + + ret = wolfCrypt_IntegrityTest_fips(); + + REENABLE_VECTOR_REGISTERS(); + + svr_disallowed_count = wc_svr_disallowed_count_current(); + if (svr_disallowed_count == 0) { + pr_err("ERROR: wc_svr_disallowed_count_current() returned %llu after DISABLE_VECTOR_REGISTERS().\n", svr_disallowed_count); + return -ECANCELED; + } + + if (ret != 0) { + pr_err("ERROR: wolfCrypt_IntegrityTest_fips() with DISABLE_VECTOR_REGISTERS() returned %d.\n", ret); + return -ECANCELED; + } + + ret = wolfCrypt_GetStatus_fips(); + if (ret != 0) { + pr_err("ERROR: wolfCrypt_GetStatus_fips() failed with code %d: %s\n", ret, wc_GetErrorString(ret)); + return -ECANCELED; + } + } +#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS && WC_C_DYNAMIC_FALLBACK */ + #endif /* HAVE_FIPS */ #ifdef WC_RNG_SEED_CB @@ -915,6 +1006,10 @@ static int wolfssl_init(void) wc_linuxkm_stack_hwm_prepare(0xee); #endif +#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) + wc_svr_disallowed_count_reset(); +#endif + ret = wc_RunAllCast_fips(); #ifdef WC_LINUXKM_HAVE_STACK_DEBUG @@ -930,6 +1025,58 @@ static int wolfssl_init(void) return -ECANCELED; } +#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) + { + long long unsigned int svr_disallowed_count = wc_svr_disallowed_count_current(); + if (svr_disallowed_count > 0) { + pr_err("ERROR: wc_svr_disallowed_count_current() returned %llu after wc_RunAllCast_fips().\n", svr_disallowed_count); + return -ECANCELED; + } + + #ifdef WC_LINUXKM_HAVE_STACK_DEBUG + { + unsigned long stack_usage; + wc_linuxkm_stack_hwm_prepare(0xee); + #endif + + ret = DISABLE_VECTOR_REGISTERS(); + if (ret != 0) { + pr_err("ERROR: DISABLE_VECTOR_REGISTERS() for wc_RunAllCast_fips() returned %d.\n", ret); + return -ECANCELED; + } + + ret = wc_RunAllCast_fips(); + + REENABLE_VECTOR_REGISTERS(); + + #ifdef WC_LINUXKM_HAVE_STACK_DEBUG + stack_usage = wc_linuxkm_stack_hwm_measure_rel(0xee); + pr_info("STACK INFO: rel usage by wc_RunAllCast_fips() with DISABLE_VECTOR_REGISTERS(): %lu\n", stack_usage); + /* shush up false stack HWM reading by kernel: */ + wc_linuxkm_stack_hwm_prepare(0); + } + #endif + + svr_disallowed_count = wc_svr_disallowed_count_current(); + if (svr_disallowed_count == 0) { + pr_err("ERROR: wc_svr_disallowed_count_current() returned %llu after DISABLE_VECTOR_REGISTERS().\n", svr_disallowed_count); + return -ECANCELED; + } + + if (ret != 0) { + pr_err("ERROR: wc_RunAllCast_fips() with DISABLE_VECTOR_REGISTERS() returned %d.\n", ret); + return -ECANCELED; + } + + ret = wolfCrypt_GetStatus_fips(); + if (ret != 0) { + pr_err("ERROR: wolfCrypt_GetStatus_fips() failed with code %d: %s\n", ret, wc_GetErrorString(ret)); + return -ECANCELED; + } + } + +#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS && WC_C_DYNAMIC_FALLBACK */ + pr_info("FIPS 140-3 wolfCrypt-fips v%d.%d.%d%s%s startup " "self-test succeeded.\n", #ifdef HAVE_FIPS_VERSION_MAJOR @@ -955,6 +1102,7 @@ static int wolfssl_init(void) "" #endif ); + #endif /* HAVE_FIPS && FIPS_VERSION3_GT(5,2,0) */ #ifdef FIPS_OPTEST @@ -2041,6 +2189,29 @@ static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_at return -EINVAL; } +#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) + /* Note that wc_svr_disallowed_count*() can't be checked in + * FIPS_rerun_self_test_handler() -- we're already multiuser at this point + * and other threads can and will increment wc_svr_disallowed_count outside + * our control. + */ + + ret = DISABLE_VECTOR_REGISTERS(); + if (ret != 0) { + pr_err("ERROR: DISABLE_VECTOR_REGISTERS() for wc_RunAllCast_fips() returned %d.\n", ret); + return -EINVAL; + } + + ret = wc_RunAllCast_fips(); + + REENABLE_VECTOR_REGISTERS(); + + if (ret != 0) { + pr_err("ERROR: wc_RunAllCast_fips() with DISABLE_VECTOR_REGISTERS() returned %d.\n", ret); + return -EINVAL; + } +#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS && WC_C_DYNAMIC_FALLBACK */ + pr_info("wolfCrypt FIPS re-self-test succeeded: all algorithms verified and available.\n"); return count; From 88556e0aa324285dd11fcfa88adeb4ead77de3cc Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 17 Aug 2026 16:52:43 -0500 Subject: [PATCH 3/9] linuxkm/module_hooks.c: when DEBUG_VECTOR_REGISTER_ACCESS_FUZZING or DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON, inhibit DISABLE_VECTOR_REGISTERS() exercises and auditing of wc_svr_disallowed_count_current(). --- linuxkm/module_hooks.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index 000de2b2cc2..7903711b275 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -932,7 +932,10 @@ static int wolfssl_init(void) return -ECANCELED; } -#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) +#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) && \ + !defined(DEBUG_VECTOR_REGISTER_ACCESS_FUZZING) && \ + !defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON) + { long long unsigned int svr_disallowed_count = wc_svr_disallowed_count_current(); if (svr_disallowed_count > 0) { @@ -967,7 +970,8 @@ static int wolfssl_init(void) return -ECANCELED; } } -#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS && WC_C_DYNAMIC_FALLBACK */ +#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS && WC_C_DYNAMIC_FALLBACK && */ + /* !DEBUG_VECTOR_REGISTER_ACCESS_FUZZING && !DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON */ #endif /* HAVE_FIPS */ @@ -1025,7 +1029,9 @@ static int wolfssl_init(void) return -ECANCELED; } -#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) +#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) && \ + !defined(DEBUG_VECTOR_REGISTER_ACCESS_FUZZING) && \ + !defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON) { long long unsigned int svr_disallowed_count = wc_svr_disallowed_count_current(); if (svr_disallowed_count > 0) { @@ -1075,7 +1081,8 @@ static int wolfssl_init(void) } } -#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS && WC_C_DYNAMIC_FALLBACK */ +#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS && WC_C_DYNAMIC_FALLBACK && */ + /* !DEBUG_VECTOR_REGISTER_ACCESS_FUZZING && !DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON */ pr_info("FIPS 140-3 wolfCrypt-fips v%d.%d.%d%s%s startup " "self-test succeeded.\n", @@ -2189,7 +2196,9 @@ static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_at return -EINVAL; } -#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) +#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) && \ + !defined(DEBUG_VECTOR_REGISTER_ACCESS_FUZZING) && \ + !defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON) /* Note that wc_svr_disallowed_count*() can't be checked in * FIPS_rerun_self_test_handler() -- we're already multiuser at this point * and other threads can and will increment wc_svr_disallowed_count outside @@ -2210,7 +2219,8 @@ static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_at pr_err("ERROR: wc_RunAllCast_fips() with DISABLE_VECTOR_REGISTERS() returned %d.\n", ret); return -EINVAL; } -#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS && WC_C_DYNAMIC_FALLBACK */ +#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS && WC_C_DYNAMIC_FALLBACK && */ + /* !DEBUG_VECTOR_REGISTER_ACCESS_FUZZING && !DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON */ pr_info("wolfCrypt FIPS re-self-test succeeded: all algorithms verified and available.\n"); From 6c3f63eea8d42c69825d94868ba79c380e08fd30 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Tue, 18 Aug 2026 18:46:13 -0500 Subject: [PATCH 4/9] linuxkm/module_hooks.c: implement /sys/module/libwolfssl/FIPS_optest_run_code_audit_accel and /sys/module/libwolfssl/FIPS_optest_run_code_audit_c. --- linuxkm/module_hooks.c | 128 ++++++++++++++++++++++++++++++++++------- 1 file changed, 107 insertions(+), 21 deletions(-) diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index 7903711b275..dbf341ee8f5 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -591,13 +591,17 @@ int wc_linuxkm_GenerateSeed_IntelRD(struct OS_Seed* os, byte* output, word32 sz) static WC_MAYBE_UNUSED void *my_kallsyms_lookup_name(const char *name); #endif +#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) && \ + !defined(DEBUG_VECTOR_REGISTER_ACCESS_FUZZING) && \ + !defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON) && \ + !defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_OFF) + #define WC_LINUXKM_SVR_DYNAMIC_AUDITING +#endif + #ifdef FIPS_OPTEST #ifndef HAVE_FIPS #error FIPS_OPTEST requires HAVE_FIPS. #endif - #ifdef LINUXKM_LKCAPI_REGISTER - #error FIPS_OPTEST is not allowed with LINUXKM_LKCAPI_REGISTER. - #endif extern int linuxkm_op_test_1(int argc, const char* argv[]); extern int linuxkm_op_test_wrapper(void); static wolfSSL_Atomic_Int *conTestFailure_ptr = NULL; @@ -608,6 +612,12 @@ int wc_linuxkm_GenerateSeed_IntelRD(struct OS_Seed* os, byte* output, word32 sz) const char *buf, size_t count); static struct kobj_attribute FIPS_optest_trig_attr = __ATTR(FIPS_optest_run_code, 0220, NULL, FIPS_optest_trig_handler); static int installed_sysfs_FIPS_optest_trig_files = 0; +#ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING + static struct kobj_attribute FIPS_optest_trig_audit_accel_attr = __ATTR(FIPS_optest_run_code_audit_accel, 0220, NULL, FIPS_optest_trig_handler); + static int installed_sysfs_FIPS_optest_trig_audit_accel_files = 0; + static struct kobj_attribute FIPS_optest_trig_audit_c_attr = __ATTR(FIPS_optest_run_code_audit_c, 0220, NULL, FIPS_optest_trig_handler); + static int installed_sysfs_FIPS_optest_trig_audit_c_files = 0; +#endif #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) @@ -899,7 +909,7 @@ static int wolfssl_init(void) * wolfCrypt_IntegrityTest_fips() with asm disabled. */ -#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) +#ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING wc_svr_disallowed_count_reset(); #endif if (WC_SIG_IGNORE_BEGIN() >= 0) { @@ -932,10 +942,7 @@ static int wolfssl_init(void) return -ECANCELED; } -#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) && \ - !defined(DEBUG_VECTOR_REGISTER_ACCESS_FUZZING) && \ - !defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON) - +#ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING { long long unsigned int svr_disallowed_count = wc_svr_disallowed_count_current(); if (svr_disallowed_count > 0) { @@ -970,8 +977,7 @@ static int wolfssl_init(void) return -ECANCELED; } } -#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS && WC_C_DYNAMIC_FALLBACK && */ - /* !DEBUG_VECTOR_REGISTER_ACCESS_FUZZING && !DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON */ +#endif /* WC_LINUXKM_SVR_DYNAMIC_AUDITING */ #endif /* HAVE_FIPS */ @@ -1010,7 +1016,7 @@ static int wolfssl_init(void) wc_linuxkm_stack_hwm_prepare(0xee); #endif -#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) +#ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING wc_svr_disallowed_count_reset(); #endif @@ -1029,9 +1035,7 @@ static int wolfssl_init(void) return -ECANCELED; } -#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) && \ - !defined(DEBUG_VECTOR_REGISTER_ACCESS_FUZZING) && \ - !defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON) +#ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING { long long unsigned int svr_disallowed_count = wc_svr_disallowed_count_current(); if (svr_disallowed_count > 0) { @@ -1081,8 +1085,7 @@ static int wolfssl_init(void) } } -#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS && WC_C_DYNAMIC_FALLBACK && */ - /* !DEBUG_VECTOR_REGISTER_ACCESS_FUZZING && !DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON */ +#endif /* WC_LINUXKM_SVR_DYNAMIC_AUDITING */ pr_info("FIPS 140-3 wolfCrypt-fips v%d.%d.%d%s%s startup " "self-test succeeded.\n", @@ -1129,6 +1132,19 @@ static int wolfssl_init(void) return -ECANCELED; } +#ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING + ret = linuxkm_lkcapi_sysfs_install_node(&FIPS_optest_trig_audit_accel_attr, &installed_sysfs_FIPS_optest_trig_audit_accel_files); + if (ret != 0) { + pr_err("ERROR: linuxkm_lkcapi_sysfs_install_node() failed for %s (code %d).\n", FIPS_optest_trig_audit_accel_attr.attr.name, ret); + return -ECANCELED; + } + ret = linuxkm_lkcapi_sysfs_install_node(&FIPS_optest_trig_audit_c_attr, &installed_sysfs_FIPS_optest_trig_audit_c_files); + if (ret != 0) { + pr_err("ERROR: linuxkm_lkcapi_sysfs_install_node() failed for %s (code %d).\n", FIPS_optest_trig_audit_c_attr.attr.name, ret); + return -ECANCELED; + } +#endif + #ifdef FIPS_OPTEST_FULL_RUN_AT_MODULE_INIT #ifdef WC_LINUXKM_HAVE_STACK_DEBUG @@ -1301,6 +1317,10 @@ static void wolfssl_exit(void) (void)linuxkm_lkcapi_sysfs_deinstall_node(&FIPS_rerun_self_test_attr, &installed_sysfs_FIPS_files); #ifdef FIPS_OPTEST (void)linuxkm_lkcapi_sysfs_deinstall_node(&FIPS_optest_trig_attr, &installed_sysfs_FIPS_optest_trig_files); +#ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING + (void)linuxkm_lkcapi_sysfs_deinstall_node(&FIPS_optest_trig_audit_accel_attr, &installed_sysfs_FIPS_optest_trig_audit_accel_files); + (void)linuxkm_lkcapi_sysfs_deinstall_node(&FIPS_optest_trig_audit_c_attr, &installed_sysfs_FIPS_optest_trig_audit_c_files); +#endif #endif #endif @@ -2196,9 +2216,8 @@ static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_at return -EINVAL; } -#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WC_C_DYNAMIC_FALLBACK) && \ - !defined(DEBUG_VECTOR_REGISTER_ACCESS_FUZZING) && \ - !defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON) +#ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING + /* Note that wc_svr_disallowed_count*() can't be checked in * FIPS_rerun_self_test_handler() -- we're already multiuser at this point * and other threads can and will increment wc_svr_disallowed_count outside @@ -2219,8 +2238,7 @@ static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_at pr_err("ERROR: wc_RunAllCast_fips() with DISABLE_VECTOR_REGISTERS() returned %d.\n", ret); return -EINVAL; } -#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS && WC_C_DYNAMIC_FALLBACK && */ - /* !DEBUG_VECTOR_REGISTER_ACCESS_FUZZING && !DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON */ +#endif /* WC_LINUXKM_SVR_DYNAMIC_AUDITING */ pr_info("wolfCrypt FIPS re-self-test succeeded: all algorithms verified and available.\n"); @@ -2242,10 +2260,21 @@ static ssize_t FIPS_optest_trig_handler(struct kobject *kobj, struct kobj_attrib char code_buf[5]; size_t corrected_count; int i; + static wolfSSL_Atomic_Int in_optest = WOLFSSL_ATOMIC_INITIALIZER(-1); +#ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING + long long unsigned int svr_disallowed_before_optest = 0, svr_disallowed_after_optest; +#endif (void)kobj; (void)attr; +#ifdef LINUXKM_LKCAPI_REGISTER + if (linuxkm_lkcapi_registered) { + pr_err("ERROR: FIPS_optest_trig_handler() with linuxkm_lkcapi_registered: before running optest, echo 1 > /sys/module/libwolfssl/deinstall_algs.\n"); + return -EBUSY; + } +#endif + /* buf may or may not have an LF at end -- tolerate both. there is no * terminating null in either case. */ @@ -2268,6 +2297,17 @@ static ssize_t FIPS_optest_trig_handler(struct kobject *kobj, struct kobj_attrib argv[2] = code_buf; argc = 3; + { + WC_ATOMIC_INT_ARG expected_in_optest = -1; + if (! wolfSSL_Atomic_Int_CompareExchange( + &in_optest, &expected_in_optest, task_pid_nr(current))) + { + pr_err("ERROR: FIPS_optest_trig_handler() called by pid %d while pid %d is running optest in another thread.\n", + task_pid_nr(current), expected_in_optest); + return -EBUSY; + } + } + printf("OK, testing code %s\n", code_buf); #ifdef WC_LINUXKM_HAVE_STACK_DEBUG @@ -2278,8 +2318,54 @@ static ssize_t FIPS_optest_trig_handler(struct kobject *kobj, struct kobj_attrib wc_linuxkm_stack_hwm_prepare(0xee); #endif +#ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING + + /* The audits treat wc_svr_disallowed_count as + * ours alone: in_optest excludes the other trigger nodes, and the + * linuxkm_lkcapi_registered check above excludes registered- + * algorithm consumers. The entry check is advisory against re- + * registration mid-optest; don't do that. + */ + + if ((attr == &FIPS_optest_trig_audit_accel_attr) || + (attr == &FIPS_optest_trig_audit_c_attr)) + { + if (attr == &FIPS_optest_trig_audit_c_attr) { + ret = DISABLE_VECTOR_REGISTERS(); + if (ret != 0) { + pr_err("ERROR: DISABLE_VECTOR_REGISTERS() for FIPS_optest_trig_handler() returned %d.\n", ret); + WOLFSSL_ATOMIC_STORE(in_optest, -1); + return -EINVAL; + } + } + svr_disallowed_before_optest = wc_svr_disallowed_count_current(); + } +#endif + ret = linuxkm_op_test_1(argc, &argv[0]); +#ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING + if (attr == &FIPS_optest_trig_audit_c_attr) { + REENABLE_VECTOR_REGISTERS(); + svr_disallowed_after_optest = wc_svr_disallowed_count_current(); + if (svr_disallowed_after_optest == svr_disallowed_before_optest) { + pr_err("ERROR: wc_svr_disallowed_count_current() did not increment during optest with DISABLE_VECTOR_REGISTERS().\n"); + WOLFSSL_ATOMIC_STORE(in_optest, -1); + return -EINVAL; + } + } + else if (attr == &FIPS_optest_trig_audit_accel_attr) { + svr_disallowed_after_optest = wc_svr_disallowed_count_current(); + if (svr_disallowed_after_optest != svr_disallowed_before_optest) { + pr_err("ERROR: wc_svr_disallowed_count_current() incremented (+%llu) during optest.\n", svr_disallowed_after_optest - svr_disallowed_before_optest); + WOLFSSL_ATOMIC_STORE(in_optest, -1); + return -EINVAL; + } + } +#endif + + WOLFSSL_ATOMIC_STORE(in_optest, -1); + #ifdef WC_LINUXKM_HAVE_STACK_DEBUG stack_usage = wc_linuxkm_stack_hwm_measure_rel(0xee); pr_info("STACK INFO: rel usage by linuxkm_op_test_1(): %lu\n", stack_usage); From f47a3f2f9efc9c9e1fb5f78dd0c1201342a40e1b Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Thu, 20 Aug 2026 16:30:51 -0500 Subject: [PATCH 5/9] linuxkm/module_hooks.c: in wolfssl_init(), when WOLFSSL_AESNI but not USE_INTEL_SPEEDUP, don't expect wc_svr_disallowed_count_current() to increase for wolfCrypt_IntegrityTest_fips() (no AES in it). --- linuxkm/module_hooks.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index dbf341ee8f5..728ee626d30 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -945,6 +945,9 @@ static int wolfssl_init(void) #ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING { long long unsigned int svr_disallowed_count = wc_svr_disallowed_count_current(); + #if !(defined(WOLFSSL_AESNI) && !defined(USE_INTEL_SPEEDUP)) + long long unsigned int svr_disallowed_snapshot; + #endif if (svr_disallowed_count > 0) { pr_err("ERROR: wc_svr_disallowed_count_current() returned %llu after fipsEntry().\n", svr_disallowed_count); return -ECANCELED; @@ -956,15 +959,26 @@ static int wolfssl_init(void) return -ECANCELED; } + #if !(defined(WOLFSSL_AESNI) && !defined(USE_INTEL_SPEEDUP)) + /* DISABLE_VECTOR_REGISTERS() itself increments the disallowed + * count (it's a save call with WC_SVR_FLAG_INHIBIT), so snapshot + * after it and require the test run to increment past the + * snapshot -- a bare != 0 check after the test is vacuously + * satisfied by the DISABLE itself and detects nothing. */ + svr_disallowed_snapshot = wc_svr_disallowed_count_current(); + #endif + ret = wolfCrypt_IntegrityTest_fips(); REENABLE_VECTOR_REGISTERS(); + #if !(defined(WOLFSSL_AESNI) && !defined(USE_INTEL_SPEEDUP)) svr_disallowed_count = wc_svr_disallowed_count_current(); if (svr_disallowed_count == 0) { pr_err("ERROR: wc_svr_disallowed_count_current() returned %llu after DISABLE_VECTOR_REGISTERS().\n", svr_disallowed_count); return -ECANCELED; } + #endif if (ret != 0) { pr_err("ERROR: wolfCrypt_IntegrityTest_fips() with DISABLE_VECTOR_REGISTERS() returned %d.\n", ret); From d3e6d17607029d0ad90168487647259e06339d7d Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 21 Aug 2026 13:04:00 -0500 Subject: [PATCH 6/9] linuxkm/module_hooks.c and wolfcrypt/src/rng_bank.c: fixes for external review of FIPS_OPTEST/LKCAPI coexistence and affinity lock error handling. in FIPS_optest_trig_handler(), implement assiduous (atomic-based) mutual exclusion with LKCAPI registration. in wc_rng_bank_checkout(), propagate INTERRUPTED_E from bank->affinity_lock_cb rather than swallowing it -- caller-requested interruption must abort checkout, consistent with the WC_CHECK_FOR_INTR_SIGNALS() handling in the same loop; other affinity lock errors continue to be tolerated (affinity is advisory). --- linuxkm/module_hooks.c | 66 ++++++++++++++++++++++++++++------------ wolfcrypt/src/rng_bank.c | 10 +++--- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index 728ee626d30..240f5f89d8a 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -2277,18 +2277,12 @@ static ssize_t FIPS_optest_trig_handler(struct kobject *kobj, struct kobj_attrib static wolfSSL_Atomic_Int in_optest = WOLFSSL_ATOMIC_INITIALIZER(-1); #ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING long long unsigned int svr_disallowed_before_optest = 0, svr_disallowed_after_optest; + ssize_t ret_count = 0; #endif (void)kobj; (void)attr; -#ifdef LINUXKM_LKCAPI_REGISTER - if (linuxkm_lkcapi_registered) { - pr_err("ERROR: FIPS_optest_trig_handler() with linuxkm_lkcapi_registered: before running optest, echo 1 > /sys/module/libwolfssl/deinstall_algs.\n"); - return -EBUSY; - } -#endif - /* buf may or may not have an LF at end -- tolerate both. there is no * terminating null in either case. */ @@ -2311,11 +2305,34 @@ static ssize_t FIPS_optest_trig_handler(struct kobject *kobj, struct kobj_attrib argv[2] = code_buf; argc = 3; +#ifdef LINUXKM_LKCAPI_REGISTER + { + int current_linuxkm_lkcapi_registering_now = 0; + + if (! wolfSSL_Atomic_Int_CompareExchange( + &linuxkm_lkcapi_registering_now, + ¤t_linuxkm_lkcapi_registering_now, + 1)) { + pr_err("ERROR: FIPS_optest_trig_handler() with linuxkm_lkcapi_registered: before running optest, echo 1 > /sys/module/libwolfssl/deinstall_algs.\n"); + return -EBUSY; + } + + if (linuxkm_lkcapi_registered) { + WOLFSSL_ATOMIC_STORE(linuxkm_lkcapi_registering_now, 0); + pr_err("ERROR: FIPS_optest_trig_handler() with linuxkm_lkcapi_registered: before running optest, echo 1 > /sys/module/libwolfssl/deinstall_algs.\n"); + return -EBUSY; + } + } +#endif + { WC_ATOMIC_INT_ARG expected_in_optest = -1; if (! wolfSSL_Atomic_Int_CompareExchange( &in_optest, &expected_in_optest, task_pid_nr(current))) { +#ifdef LINUXKM_LKCAPI_REGISTER + WOLFSSL_ATOMIC_STORE(linuxkm_lkcapi_registering_now, 0); +#endif pr_err("ERROR: FIPS_optest_trig_handler() called by pid %d while pid %d is running optest in another thread.\n", task_pid_nr(current), expected_in_optest); return -EBUSY; @@ -2335,10 +2352,10 @@ static ssize_t FIPS_optest_trig_handler(struct kobject *kobj, struct kobj_attrib #ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING /* The audits treat wc_svr_disallowed_count as - * ours alone: in_optest excludes the other trigger nodes, and the - * linuxkm_lkcapi_registered check above excludes registered- - * algorithm consumers. The entry check is advisory against re- - * registration mid-optest; don't do that. + * ours alone: in_optest excludes the other trigger nodes, and + * getting linuxkm_lkcapi_registering_now then checking + * linuxkm_lkcapi_registered excludes registered- + * algorithm consumers. */ if ((attr == &FIPS_optest_trig_audit_accel_attr) || @@ -2348,8 +2365,8 @@ static ssize_t FIPS_optest_trig_handler(struct kobject *kobj, struct kobj_attrib ret = DISABLE_VECTOR_REGISTERS(); if (ret != 0) { pr_err("ERROR: DISABLE_VECTOR_REGISTERS() for FIPS_optest_trig_handler() returned %d.\n", ret); - WOLFSSL_ATOMIC_STORE(in_optest, -1); - return -EINVAL; + ret_count = -EINVAL; + goto out; } } svr_disallowed_before_optest = wc_svr_disallowed_count_current(); @@ -2364,22 +2381,18 @@ static ssize_t FIPS_optest_trig_handler(struct kobject *kobj, struct kobj_attrib svr_disallowed_after_optest = wc_svr_disallowed_count_current(); if (svr_disallowed_after_optest == svr_disallowed_before_optest) { pr_err("ERROR: wc_svr_disallowed_count_current() did not increment during optest with DISABLE_VECTOR_REGISTERS().\n"); - WOLFSSL_ATOMIC_STORE(in_optest, -1); - return -EINVAL; + ret_count = -EINVAL; } } else if (attr == &FIPS_optest_trig_audit_accel_attr) { svr_disallowed_after_optest = wc_svr_disallowed_count_current(); if (svr_disallowed_after_optest != svr_disallowed_before_optest) { pr_err("ERROR: wc_svr_disallowed_count_current() incremented (+%llu) during optest.\n", svr_disallowed_after_optest - svr_disallowed_before_optest); - WOLFSSL_ATOMIC_STORE(in_optest, -1); - return -EINVAL; + ret_count = -EINVAL; } } #endif - WOLFSSL_ATOMIC_STORE(in_optest, -1); - #ifdef WC_LINUXKM_HAVE_STACK_DEBUG stack_usage = wc_linuxkm_stack_hwm_measure_rel(0xee); pr_info("STACK INFO: rel usage by linuxkm_op_test_1(): %lu\n", stack_usage); @@ -2390,6 +2403,10 @@ static ssize_t FIPS_optest_trig_handler(struct kobject *kobj, struct kobj_attrib printf("ret of op_test = %d\n", ret); +#ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING +out: +#endif + /* reload the library in memory and re-init state */ printf("Reloading the module in memory (equivalent to power " "cycle)\n"); @@ -2412,7 +2429,16 @@ static ssize_t FIPS_optest_trig_handler(struct kobject *kobj, struct kobj_attrib printf("Module status is: %d\n", wolfCrypt_GetStatus_fips()); printf("Module mode is: %d\n", wolfCrypt_GetMode_fips()); - return count; + WOLFSSL_ATOMIC_STORE(in_optest, -1); +#ifdef LINUXKM_LKCAPI_REGISTER + WOLFSSL_ATOMIC_STORE(linuxkm_lkcapi_registering_now, 0); +#endif + +#ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING + return ret_count ? ret_count : (ssize_t)count; +#else + return (ssize_t)count; +#endif } #endif /* FIPS_OPTEST */ diff --git a/wolfcrypt/src/rng_bank.c b/wolfcrypt/src/rng_bank.c index c17e30eda11..7c5bcfa5adc 100644 --- a/wolfcrypt/src/rng_bank.c +++ b/wolfcrypt/src/rng_bank.c @@ -545,11 +545,13 @@ WOLFSSL_API int wc_rng_bank_checkout( ret = bank->affinity_lock_cb(bank->cb_arg); if (ret == 0) new_lock_value |= WC_RNG_BANK_INST_LOCK_AFFINITY_LOCKED; - else if ((ret == WC_NO_ERR_TRACE(ALREADY_E)) || - (ret == WC_NO_ERR_TRACE(WC_ACCEL_INHIBIT_E))) - ret = 0; - else + else if (ret == WC_NO_ERR_TRACE(INTERRUPTED_E)) break; + else { + /* need to, and can, continue regardless of other error codes from + * bank->affinity_lock_cb. */ + ret = 0; + } } if (flags & WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST) { From a0d0d7c34696221a2377532e1520dcb02ef8aa7e Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 4 Sep 2026 12:06:26 -0500 Subject: [PATCH 7/9] linuxkm/linuxkm-fips-hash.c: in hmac_update_cb(), use wc_HmacUpdate(), not wc_HmacUpdate_fips(), for compatibility with dev-no-post. --- linuxkm/linuxkm-fips-hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linuxkm/linuxkm-fips-hash.c b/linuxkm/linuxkm-fips-hash.c index ff327f0ceb7..b3d3ad7d9ff 100644 --- a/linuxkm/linuxkm-fips-hash.c +++ b/linuxkm/linuxkm-fips-hash.c @@ -66,7 +66,7 @@ static int hmac_setkey_cb(Hmac *hmac, const byte *key, word32 key_len) { } static int hmac_update_cb(Hmac *hmac, const byte *in, word32 in_len) { - return wc_HmacUpdate_fips(hmac, in, in_len); + return wc_HmacUpdate(hmac, in, in_len); } static int hmac_final_cb(Hmac *hmac, byte *out, word32 out_sz) { From 3e0340871402dfb05a8d4d7fc8561f579db04930 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 4 Sep 2026 12:17:20 -0500 Subject: [PATCH 8/9] linuxkm/lkcapi_glue.c: tolerate !HAVE_FIPS with CONFIG_CRYPTO_FIPS, with a runtime check that kernel fips_enabled is zero. --- linuxkm/lkcapi_glue.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/linuxkm/lkcapi_glue.c b/linuxkm/lkcapi_glue.c index d4b9c70d0dd..685e4736010 100644 --- a/linuxkm/lkcapi_glue.c +++ b/linuxkm/lkcapi_glue.c @@ -37,12 +37,8 @@ * "fips_enabled" is only available in CONFIG_CRYPTO_FIPS kernels (otherwise * it's a macro hardcoding it to literal 0). */ - #if defined(CONFIG_CRYPTO_FIPS) != defined(HAVE_FIPS) - #ifdef HAVE_FIPS - #error CONFIG_CRYPTO_MANAGER requires that CONFIG_CRYPTO_FIPS match HAVE_FIPS (CONFIG_CRYPTO_FIPS unset). - #else - #error CONFIG_CRYPTO_MANAGER requires that CONFIG_CRYPTO_FIPS match HAVE_FIPS (HAVE_FIPS unset). - #endif + #if defined(HAVE_FIPS) && !defined(CONFIG_CRYPTO_FIPS) + #error wolfCrypt HAVE_FIPS with kernel CONFIG_CRYPTO_MANAGER requires kernel CONFIG_CRYPTO_FIPS. #endif #endif @@ -326,6 +322,13 @@ static int linuxkm_lkcapi_register(void) int seen_err = 0; int current_linuxkm_lkcapi_registering_now = 0; +#if defined(CONFIG_CRYPTO_FIPS) && !defined(HAVE_FIPS) + if (fips_enabled) { + pr_err("ERROR: can't load non-FIPS wolfCrypt module into fips_enabled kernel.\n"); + return -ECANCELED; + } +#endif + if (! wolfSSL_Atomic_Int_CompareExchange( &linuxkm_lkcapi_registering_now, ¤t_linuxkm_lkcapi_registering_now, From 2c5205743a1b2b77a4088a268865dcff188f7eb9 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 4 Sep 2026 13:57:49 -0500 Subject: [PATCH 9/9] linuxkm/module_hooks.c: * add libwolfssl_inited flag variable and use it for proper error-path cleanup; * call wc_linuxkm_allocate_svr_states() and wc_linuxkm_free_svr_states() explicitly in FIPS builds (avoid atomic-context synchronous call to wc_linuxkm_allocate_svr_states() via fipEntry()); * add missing WOLFSSL_FIPS_DEV_NO_POST gates; * in wc_lkm_LockMutex(), return BUSY_E immediately if in_nmi(). --- linuxkm/module_hooks.c | 115 ++++++++++++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 30 deletions(-) diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index 240f5f89d8a..dbfb777d243 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -120,20 +120,31 @@ #define EFBIG WC_ERR_TRACE(my_EFBIG) #endif +static int libwolfssl_inited; + static int libwolfssl_cleanup(void) { int ret; + if (libwolfssl_inited) { + libwolfssl_inited = 0; #ifdef WOLFCRYPT_ONLY - ret = wolfCrypt_Cleanup(); - if (ret != 0) - pr_err("ERROR: wolfCrypt_Cleanup() failed: %s\n", wc_GetErrorString(ret)); - else - pr_info("wolfCrypt " LIBWOLFSSL_VERSION_STRING " cleanup complete.\n"); + ret = wolfCrypt_Cleanup(); + if (ret != 0) + pr_err("ERROR: wolfCrypt_Cleanup() failed: %s\n", wc_GetErrorString(ret)); + else + pr_info("wolfCrypt " LIBWOLFSSL_VERSION_STRING " cleanup complete.\n"); #else - ret = wolfSSL_Cleanup(); - if (ret != WOLFSSL_SUCCESS) - pr_err("ERROR: wolfSSL_Cleanup() failed: %s\n", wc_GetErrorString(ret)); + ret = wolfSSL_Cleanup(); + if (ret != WOLFSSL_SUCCESS) + pr_err("ERROR: wolfSSL_Cleanup() failed: %s\n", wc_GetErrorString(ret)); + else + pr_info("wolfSSL " LIBWOLFSSL_VERSION_STRING " cleanup complete.\n"); +#endif + } else - pr_info("wolfSSL " LIBWOLFSSL_VERSION_STRING " cleanup complete.\n"); + ret = 0; + +#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(HAVE_FIPS) + wc_linuxkm_free_svr_states(); #endif return ret; @@ -197,7 +208,8 @@ extern const unsigned int wolfCrypt_FIPS_ro_end[]; #endif /* WC_SYM_RELOC_TABLES */ -#ifdef HAVE_FIPS +#if defined(HAVE_FIPS) && !defined(WOLFSSL_FIPS_DEV_NO_POST) + static void lkmFipsCb(int ok, int err, const char* hash) { if ((! ok) || (err != 0)) @@ -218,7 +230,7 @@ static void lkmFipsCb(int ok, int err, const char* hash) #ifdef WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE static int updateFipsHash(void); #endif -#endif /* HAVE_FIPS */ +#endif /* HAVE_FIPS && !WOLFSSL_FIPS_DEV_NO_POST */ #ifdef WOLFSSL_LINUXKM_BENCHMARKS extern int wolfcrypt_benchmark_main(int argc, char** argv); @@ -237,6 +249,8 @@ int wc_lkm_LockMutex(wolfSSL_Mutex* m) m->irq_flags = irq_flags; return 0; } + if (in_nmi()) + return BUSY_E; if (! wc_linuxkm_can_block()) { /* Note, this catches calls while SAVE_VECTOR_REGISTERS()ed as * required, because in_softirq() is always true while saved, @@ -643,6 +657,14 @@ static int wolfssl_init(void) return ret; #endif +#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(HAVE_FIPS) + ret = wc_linuxkm_allocate_svr_states(); + if (ret < 0) { + pr_err("wolfssl_init(): wc_linuxkm_allocate_svr_states() returned code %d.\n", ret); + return -ECANCELED; + } +#endif + #ifdef WC_LINUXKM_SUPPORT_DUMP_TO_FILE #ifdef WC_SYM_RELOC_TABLES @@ -721,6 +743,7 @@ static int wolfssl_init(void) #endif if (verifyCore_len != FIPS_IN_CORE_DIGEST_SIZE*2) { pr_err("ERROR: compile-time FIPS hash is the wrong length (expected %d hex digits, got %zu).\n", FIPS_IN_CORE_DIGEST_SIZE*2, verifyCore_len); + (void)libwolfssl_cleanup(); return -ECANCELED; } } @@ -732,6 +755,7 @@ static int wolfssl_init(void) ((uintptr_t)__wc_rodata_end < (uintptr_t)wolfCrypt_FIPS_ro_end)) { pr_err("ERROR: ELF segment fenceposts and FIPS fenceposts conflict.\n"); + (void)libwolfssl_cleanup(); return -ECANCELED; } #endif @@ -745,6 +769,7 @@ static int wolfssl_init(void) #ifdef CONFIG_MODULE_SIG if (THIS_MODULE->sig_ok == false) { pr_err("ERROR: wolfSSL module load aborted -- bad or missing module signature with FIPS dynamic hash.\n"); + (void)libwolfssl_cleanup(); return -ECANCELED; } #endif @@ -755,6 +780,7 @@ static int wolfssl_init(void) ret = updateFipsHash(); if (ret < 0) { pr_err("ERROR: wolfSSL module load aborted -- updateFipsHash: %s\n",wc_GetErrorString(ret)); + (void)libwolfssl_cleanup(); return -ECANCELED; } @@ -799,6 +825,7 @@ static int wolfssl_init(void) if (! canon_buf) { pr_err("ERROR: malloc(%d) for WOLFSSL_*_SEGMENT_CANONICALIZER failed.\n", WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ); + (void)libwolfssl_cleanup(); return -ECANCELED; } @@ -821,6 +848,7 @@ static int wolfssl_init(void) (unsigned)(uintptr_t)__wc_text_start, (unsigned)(uintptr_t)__wc_text_end); free(canon_buf); + (void)libwolfssl_cleanup(); return -ECANCELED; } stabilized_text_hash = hash_span(canon_buf, canon_buf + text_in_out_len, stabilized_text_hash); @@ -844,6 +872,7 @@ static int wolfssl_init(void) (unsigned)(uintptr_t)__wc_rodata_start, (unsigned)(uintptr_t)__wc_rodata_end); free(canon_buf); + (void)libwolfssl_cleanup(); return -ECANCELED; } stabilized_rodata_hash = hash_span(canon_buf, canon_buf + rodata_in_out_len, stabilized_rodata_hash); @@ -892,10 +921,11 @@ static int wolfssl_init(void) } #endif -#ifdef HAVE_FIPS +#if defined(HAVE_FIPS) && !defined(WOLFSSL_FIPS_DEV_NO_POST) ret = wolfCrypt_SetCb_fips(lkmFipsCb); if (ret != 0) { pr_err("ERROR: wolfCrypt_SetCb_fips() failed: %s\n", wc_GetErrorString(ret)); + (void)libwolfssl_cleanup(); return -ECANCELED; } @@ -939,6 +969,7 @@ static int wolfssl_init(void) pr_err("ERROR: could not compute new hash. Contact customer support.\n"); } } + (void)libwolfssl_cleanup(); return -ECANCELED; } @@ -950,12 +981,14 @@ static int wolfssl_init(void) #endif if (svr_disallowed_count > 0) { pr_err("ERROR: wc_svr_disallowed_count_current() returned %llu after fipsEntry().\n", svr_disallowed_count); + (void)libwolfssl_cleanup(); return -ECANCELED; } ret = DISABLE_VECTOR_REGISTERS(); if (ret != 0) { pr_err("ERROR: DISABLE_VECTOR_REGISTERS() for wolfCrypt_IntegrityTest_fips() returned %d.\n", ret); + (void)libwolfssl_cleanup(); return -ECANCELED; } @@ -974,26 +1007,29 @@ static int wolfssl_init(void) #if !(defined(WOLFSSL_AESNI) && !defined(USE_INTEL_SPEEDUP)) svr_disallowed_count = wc_svr_disallowed_count_current(); - if (svr_disallowed_count == 0) { - pr_err("ERROR: wc_svr_disallowed_count_current() returned %llu after DISABLE_VECTOR_REGISTERS().\n", svr_disallowed_count); + if (svr_disallowed_count <= svr_disallowed_snapshot) { + pr_err("ERROR: wc_svr_disallowed_count_current() returned %llu after wolfCrypt_IntegrityTest_fips() with DISABLE_VECTOR_REGISTERS() (snapshot %llu): inhibited-save instrumentation was not exercised.\n", svr_disallowed_count, svr_disallowed_snapshot); + (void)libwolfssl_cleanup(); return -ECANCELED; } #endif if (ret != 0) { pr_err("ERROR: wolfCrypt_IntegrityTest_fips() with DISABLE_VECTOR_REGISTERS() returned %d.\n", ret); + (void)libwolfssl_cleanup(); return -ECANCELED; } ret = wolfCrypt_GetStatus_fips(); if (ret != 0) { pr_err("ERROR: wolfCrypt_GetStatus_fips() failed with code %d: %s\n", ret, wc_GetErrorString(ret)); + (void)libwolfssl_cleanup(); return -ECANCELED; } } #endif /* WC_LINUXKM_SVR_DYNAMIC_AUDITING */ -#endif /* HAVE_FIPS */ +#endif /* HAVE_FIPS && !WOLFSSL_FIPS_DEV_NO_POST */ #ifdef WC_RNG_SEED_CB ret = wc_SetSeed_Cb(WC_GENERATE_SEED_DEFAULT); @@ -1010,17 +1046,20 @@ static int wolfssl_init(void) ret = wolfCrypt_Init(); if (ret != 0) { pr_err("ERROR: wolfCrypt_Init() failed: %s\n", wc_GetErrorString(ret)); + (void)libwolfssl_cleanup(); return -ECANCELED; } #else ret = wolfSSL_Init(); if (ret != WOLFSSL_SUCCESS) { pr_err("ERROR: wolfSSL_Init() failed: %s\n", wc_GetErrorString(ret)); + (void)libwolfssl_cleanup(); return -ECANCELED; } #endif + libwolfssl_inited = 1; -#if defined(HAVE_FIPS) && FIPS_VERSION3_GT(5,2,0) +#if defined(HAVE_FIPS) && FIPS_VERSION3_GT(5,2,0) && !defined(WOLFSSL_FIPS_DEV_NO_POST) #ifdef WC_LINUXKM_HAVE_STACK_DEBUG { @@ -1046,14 +1085,17 @@ static int wolfssl_init(void) if (ret != 0) { pr_err("ERROR: wc_RunAllCast_fips() failed with return value %d\n", ret); + (void)libwolfssl_cleanup(); return -ECANCELED; } #ifdef WC_LINUXKM_SVR_DYNAMIC_AUDITING { long long unsigned int svr_disallowed_count = wc_svr_disallowed_count_current(); + long long unsigned int svr_disallowed_snapshot; if (svr_disallowed_count > 0) { pr_err("ERROR: wc_svr_disallowed_count_current() returned %llu after wc_RunAllCast_fips().\n", svr_disallowed_count); + (void)libwolfssl_cleanup(); return -ECANCELED; } @@ -1066,9 +1108,14 @@ static int wolfssl_init(void) ret = DISABLE_VECTOR_REGISTERS(); if (ret != 0) { pr_err("ERROR: DISABLE_VECTOR_REGISTERS() for wc_RunAllCast_fips() returned %d.\n", ret); + (void)libwolfssl_cleanup(); return -ECANCELED; } + /* See the snapshot rationale in the wolfCrypt_IntegrityTest_fips() + * block above. */ + svr_disallowed_snapshot = wc_svr_disallowed_count_current(); + ret = wc_RunAllCast_fips(); REENABLE_VECTOR_REGISTERS(); @@ -1082,19 +1129,22 @@ static int wolfssl_init(void) #endif svr_disallowed_count = wc_svr_disallowed_count_current(); - if (svr_disallowed_count == 0) { - pr_err("ERROR: wc_svr_disallowed_count_current() returned %llu after DISABLE_VECTOR_REGISTERS().\n", svr_disallowed_count); + if (svr_disallowed_count <= svr_disallowed_snapshot) { + pr_err("ERROR: wc_svr_disallowed_count_current() returned %llu after wc_RunAllCast_fips() with DISABLE_VECTOR_REGISTERS() (snapshot %llu): inhibited-save instrumentation was not exercised.\n", svr_disallowed_count, svr_disallowed_snapshot); + (void)libwolfssl_cleanup(); return -ECANCELED; } if (ret != 0) { pr_err("ERROR: wc_RunAllCast_fips() with DISABLE_VECTOR_REGISTERS() returned %d.\n", ret); + (void)libwolfssl_cleanup(); return -ECANCELED; } ret = wolfCrypt_GetStatus_fips(); if (ret != 0) { pr_err("ERROR: wolfCrypt_GetStatus_fips() failed with code %d: %s\n", ret, wc_GetErrorString(ret)); + (void)libwolfssl_cleanup(); return -ECANCELED; } } @@ -1127,7 +1177,7 @@ static int wolfssl_init(void) #endif ); -#endif /* HAVE_FIPS && FIPS_VERSION3_GT(5,2,0) */ +#endif /* HAVE_FIPS && FIPS_VERSION3_GT(5,2,0) && !WOLFSSL_FIPS_DEV_NO_POST */ #ifdef FIPS_OPTEST #ifdef HAVE_WC_FIPS_OPTEST_CONTESTFAILURE_EXPORT @@ -1136,6 +1186,7 @@ static int wolfssl_init(void) conTestFailure_ptr = (wolfSSL_Atomic_Int *)my_kallsyms_lookup_name("conTestFailure"); if (conTestFailure_ptr == NULL) { pr_err("ERROR: couldn't obtain conTestFailure_ptr.\n"); + (void)libwolfssl_cleanup(); return -ECANCELED; } #endif @@ -1143,6 +1194,7 @@ static int wolfssl_init(void) ret = linuxkm_lkcapi_sysfs_install_node(&FIPS_optest_trig_attr, &installed_sysfs_FIPS_optest_trig_files); if (ret != 0) { pr_err("ERROR: linuxkm_lkcapi_sysfs_install_node() failed for %s (code %d).\n", FIPS_optest_trig_attr.attr.name, ret); + (void)libwolfssl_cleanup(); return -ECANCELED; } @@ -1150,11 +1202,13 @@ static int wolfssl_init(void) ret = linuxkm_lkcapi_sysfs_install_node(&FIPS_optest_trig_audit_accel_attr, &installed_sysfs_FIPS_optest_trig_audit_accel_files); if (ret != 0) { pr_err("ERROR: linuxkm_lkcapi_sysfs_install_node() failed for %s (code %d).\n", FIPS_optest_trig_audit_accel_attr.attr.name, ret); + (void)libwolfssl_cleanup(); return -ECANCELED; } ret = linuxkm_lkcapi_sysfs_install_node(&FIPS_optest_trig_audit_c_attr, &installed_sysfs_FIPS_optest_trig_audit_c_files); if (ret != 0) { pr_err("ERROR: linuxkm_lkcapi_sysfs_install_node() failed for %s (code %d).\n", FIPS_optest_trig_audit_c_attr.attr.name, ret); + (void)libwolfssl_cleanup(); return -ECANCELED; } #endif @@ -1198,6 +1252,7 @@ static int wolfssl_init(void) ret = wolfCrypt_GetStatus_fips(); if (ret != 0) { pr_err("ERROR: wolfCrypt_GetStatus_fips() after reset failed with code %d: %s\n", ret, wc_GetErrorString(ret)); + (void)libwolfssl_cleanup(); return -ECANCELED; } #endif @@ -1227,7 +1282,7 @@ static int wolfssl_init(void) } pr_info("wolfCrypt self-test passed.\n"); #else -#if !defined(HAVE_FIPS) || FIPS_VERSION3_LE(5,2,0) +#if !defined(HAVE_FIPS) || FIPS_VERSION3_LE(5,2,0) || defined(WOLFSSL_FIPS_DEV_NO_POST) pr_info("skipping full wolfcrypt_test() " "(configure with --enable-crypttests to enable).\n"); #endif @@ -1326,8 +1381,6 @@ static void wolfssl_exit(void) #endif { #ifdef HAVE_FIPS - int ret; - (void)linuxkm_lkcapi_sysfs_deinstall_node(&FIPS_rerun_self_test_attr, &installed_sysfs_FIPS_files); #ifdef FIPS_OPTEST (void)linuxkm_lkcapi_sysfs_deinstall_node(&FIPS_optest_trig_attr, &installed_sysfs_FIPS_optest_trig_files); @@ -1343,13 +1396,15 @@ static void wolfssl_exit(void) (void)linuxkm_lkcapi_sysfs_deinstall(); #endif -#ifdef HAVE_FIPS - ret = wc_RunAllCast_fips(); - if (ret != 0) { - pr_err("ERROR: wc_RunAllCast_fips() failed at shutdown with return value %d\n", ret); +#if defined(HAVE_FIPS) && !defined(WOLFSSL_FIPS_DEV_NO_POST) + { + int ret = wc_RunAllCast_fips(); + if (ret != 0) { + pr_err("ERROR: wc_RunAllCast_fips() failed at shutdown with return value %d\n", ret); + } + else + pr_info("wolfCrypt FIPS re-self-test succeeded at unload: all algorithms re-verified.\n"); } - else - pr_info("wolfCrypt FIPS re-self-test succeeded at unload: all algorithms re-verified.\n"); #endif (void)libwolfssl_cleanup(); @@ -1956,7 +2011,7 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) { #endif /* WC_SYM_RELOC_TABLES */ -#if defined(HAVE_FIPS) && defined(WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE) +#if defined(HAVE_FIPS) && defined(WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE) && !defined(WOLFSSL_FIPS_DEV_NO_POST) #include @@ -2142,7 +2197,7 @@ static int updateFipsHash(void) return ret; } -#endif /* HAVE_FIPS && WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE */ +#endif /* HAVE_FIPS && WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE && !WOLFSSL_FIPS_DEV_NO_POST */ #ifdef CONFIG_HAVE_KPROBES