From e0383b496ae81f0fb561f9318c33a58d91828f50 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 22 Aug 2025 21:57:23 -0500 Subject: [PATCH 1/2] linuxkm/module_hooks.c: implement wc_linuxkm_GenerateSeed_IntelRD, gated on WC_LINUXKM_RDSEED_IN_GLUE_LAYER; add WC_GENERATE_SEED_DEFAULT, which defaults to wc_GenerateSeed if not overridden, and replace wc_GenerateSeed with WC_GENERATE_SEED_DEFAULT in various calls to wc_SetSeed_Cb(); linuxkm/linuxkm_wc_port.h: if FIPS +#include + +static cpuid_flags_t intel_flags = WC_CPUID_INITIALIZER; +static inline void wc_InitRng_IntelRD(void) +{ + cpuid_get_flags_ex(&intel_flags); +} + +#define INTELRD_RETRY 32 + +static WC_INLINE int IntelRDseed64(word64* seed) +{ + unsigned char ok; + + __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok)); + return (ok) ? 0 : -1; +} + +/* return 0 on success */ +static WC_INLINE int IntelRDseed64_r(word64* rnd) +{ + int iters, retry_counter; + word64 buf; +#if defined(HAVE_AMD_RDSEED) + /* See "AMD RNG ESV Public Use Document". Version 0.7 of October 24, + * 2024 specifies 0.656 to 1.312 bits of entropy per 128 bit block of + * RDSEED output, depending on CPU family. + * + * FIPS v5 random.c sets ENTROPY_SCALE_FACTOR to 1 for + * HAVE_INTEL_RDSEED. + */ + iters = 128; +#elif defined(HAVE_INTEL_RDSEED) + /* The value of 2 applies to Intel's RDSEED which provides about + * 0.5 bits minimum of entropy per bit. The value of 4 gives a + * conservative margin for FIPS. + * + * FIPS v5 random.c sets ENTROPY_SCALE_FACTOR to 2 for + * HAVE_INTEL_RDSEED. + */ + iters = 2; +#else + #error WC_LINUXKM_RDSEED_IN_GLUE_LAYER requires HAVE_INTEL_RDSEED or HAVE_AMD_RDSEED +#endif + + while (--iters >= 0) { + for (retry_counter = 0; retry_counter < INTELRD_RETRY; retry_counter++) { + if (IntelRDseed64(&buf) == 0) + break; + } + if (retry_counter == INTELRD_RETRY) + return -1; + WC_SANITIZE_DISABLE(); + *rnd ^= buf; /* deliberately retain any garbage passed in the dest buffer. */ + WC_SANITIZE_ENABLE(); + } + return 0; +} + +/* return 0 on success */ +int wc_linuxkm_GenerateSeed_IntelRD(struct OS_Seed* os, byte* output, word32 sz) +{ + int ret; + word64 rndTmp; + + (void)os; + + wc_InitRng_IntelRD(); + + if (!IS_INTEL_RDSEED(intel_flags)) + return -1; + + for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64), + output += sizeof(word64)) { + ret = IntelRDseed64_r((word64*)output); + if (ret != 0) + return ret; + } + if (sz == 0) + return 0; + + /* handle unaligned remainder */ + ret = IntelRDseed64_r(&rndTmp); + if (ret != 0) + return ret; + + XMEMCPY(output, &rndTmp, sz); + wc_ForceZero(&rndTmp, sizeof(rndTmp)); + + return 0; +} + +#endif /* WC_LINUXKM_RDSEED_IN_GLUE_LAYER */ + #if defined(WOLFSSL_LINUXKM_USE_SAVE_VECTOR_REGISTERS) && defined(CONFIG_X86) #include "linuxkm/x86_vector_register_glue.c" #endif @@ -359,14 +457,15 @@ static int wolfssl_init(void) #endif /* HAVE_FIPS */ #ifdef WC_RNG_SEED_CB - ret = wc_SetSeed_Cb(wc_GenerateSeed); + ret = wc_SetSeed_Cb(WC_GENERATE_SEED_DEFAULT); + if (ret < 0) { pr_err("ERROR: wc_SetSeed_Cb() failed with return code %d.\n", ret); (void)libwolfssl_cleanup(); msleep(10); return -ECANCELED; } -#endif +#endif /* WC_RNG_SEED_CB */ #ifdef WOLFCRYPT_ONLY ret = wolfCrypt_Init(); diff --git a/src/ssl.c b/src/ssl.c index 26aff4f3e..5ed5a526c 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -6323,7 +6323,7 @@ int wolfSSL_Init(void) #endif #ifdef WC_RNG_SEED_CB - wc_SetSeed_Cb(wc_GenerateSeed); + wc_SetSeed_Cb(WC_GENERATE_SEED_DEFAULT); #endif #ifdef OPENSSL_EXTRA diff --git a/tests/api.c b/tests/api.c index ab8bec5f8..dac4590cd 100644 --- a/tests/api.c +++ b/tests/api.c @@ -25508,7 +25508,7 @@ static int test_wolfSSL_RAND_poll(void) ExpectIntNE(XMEMCMP(rand1, rand2, 16), 0); /* reset the seed function used */ - wc_SetSeed_Cb(wc_GenerateSeed); + wc_SetSeed_Cb(WC_GENERATE_SEED_DEFAULT); #endif RAND_cleanup(); diff --git a/tests/unit.c b/tests/unit.c index a3281c29f..17a5b5c3f 100644 --- a/tests/unit.c +++ b/tests/unit.c @@ -89,7 +89,7 @@ int unit_test(int argc, char** argv) #endif #ifdef WC_RNG_SEED_CB - wc_SetSeed_Cb(wc_GenerateSeed); + wc_SetSeed_Cb(WC_GENERATE_SEED_DEFAULT); #endif #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 8b86b065a..40ca470bc 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -4074,7 +4074,7 @@ int benchmark_init(void) #endif #ifdef WC_RNG_SEED_CB - wc_SetSeed_Cb(wc_GenerateSeed); + wc_SetSeed_Cb(WC_GENERATE_SEED_DEFAULT); #endif bench_stats_init(); diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index f58d876cf..ef20a00c0 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -1531,7 +1531,7 @@ wc_test_ret_t wolfcrypt_test(void* args) #endif #ifdef WC_RNG_SEED_CB - wc_SetSeed_Cb(wc_GenerateSeed); + wc_SetSeed_Cb(WC_GENERATE_SEED_DEFAULT); #endif printf("------------------------------------------------------------------------------\n"); @@ -18423,7 +18423,8 @@ static wc_test_ret_t rng_seed_test(void) /* The expected PRNG block depends on ENTROPY_SCALE_FACTOR and * SEED_BLOCK_SZ, which depend on which seed back end is configured. */ -#if defined(HAVE_ENTROPY_MEMUSE) && defined(HAVE_AMD_RDSEED) +#if defined(HAVE_ENTROPY_MEMUSE) && defined(HAVE_AMD_RDSEED) && \ + !(defined(HAVE_FIPS) && FIPS_VERSION_LT(6,0)) #ifdef HAVE_FIPS WOLFSSL_SMALL_STACK_STATIC const byte check[] = { @@ -18460,7 +18461,8 @@ static wc_test_ret_t rng_seed_test(void) 0x83, 0xbf, 0x41, 0xd1, 0x3e, 0x8f, 0xc0, 0x45 }; #endif -#elif defined(HAVE_AMD_RDSEED) +#elif defined(HAVE_AMD_RDSEED) && \ + !(defined(HAVE_FIPS) && FIPS_VERSION_LT(6,0)) WOLFSSL_SMALL_STACK_STATIC const byte check[] = { 0x2c, 0xd4, 0x9b, 0x1e, 0x1e, 0xe7, 0xb0, 0xb0, @@ -18468,7 +18470,8 @@ static wc_test_ret_t rng_seed_test(void) 0xf4, 0x77, 0xaf, 0xac, 0x3d, 0x2f, 0x6b, 0x1f, 0xa2, 0xe7, 0xe5, 0x90, 0x6d, 0x1f, 0x88, 0x98 }; -#elif defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) +#elif (defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)) && \ + !(defined(HAVE_FIPS) && FIPS_VERSION_LT(6,0)) #ifdef HAVE_FIPS WOLFSSL_SMALL_STACK_STATIC const byte check[] = { @@ -18486,6 +18489,15 @@ static wc_test_ret_t rng_seed_test(void) 0xd7, 0x63, 0x57, 0xe8, 0x6d, 0xf7, 0xc8, 0x6b }; #endif +#elif defined(HAVE_INTEL_RDSEED) && \ + defined(HAVE_FIPS) && FIPS_VERSION_LT(6,0) + WOLFSSL_SMALL_STACK_STATIC const byte check[] = + { + 0x27, 0xdd, 0xff, 0x5b, 0x21, 0x26, 0x0a, 0x48, + 0xb3, 0x6b, 0xd8, 0x14, 0x00, 0x55, 0xe8, 0x39, + 0x6d, 0x31, 0xf3, 0x6e, 0xe7, 0xbf, 0xce, 0x08, + 0x1f, 0x61, 0x73, 0xe6, 0x3c, 0xb9, 0x12, 0xea + }; #elif defined(HAVE_FIPS) WOLFSSL_SMALL_STACK_STATIC const byte check[] = { @@ -18527,7 +18539,7 @@ static wc_test_ret_t rng_seed_test(void) if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); } - ret = wc_SetSeed_Cb(wc_GenerateSeed); + ret = wc_SetSeed_Cb(WC_GENERATE_SEED_DEFAULT); if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); } diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 9bfa445a4..8264393b0 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -3764,7 +3764,6 @@ extern void uITRON4_free(void *p) ; #endif #endif - /* Place any other flags or defines here */ #if defined(WOLFSSL_MYSQL_COMPATIBLE) && defined(_WIN32) \ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 86c9cb62a..9ccfcb204 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1991,21 +1991,28 @@ WOLFSSL_API word32 CheckRunTimeSettings(void); #define RESTORE_VECTOR_REGISTERS() RESTORE_NO_VECTOR_REGISTERS() #endif -#ifdef WOLFSSL_NO_ASM - /* We define fallback no-op definitions for these only if asm is disabled, - * otherwise the using code must detect that these macros are undefined and - * provide its own non-vector implementation paths. - * - * Currently these macros are only used in WOLFSSL_LINUXKM code paths, which - * are always compiled either with substantive definitions from - * linuxkm_wc_port.h, or with WOLFSSL_NO_ASM defined. - */ - #ifndef DISABLE_VECTOR_REGISTERS +#if (defined(USE_INTEL_SPEEDUP) || defined(USE_INTEL_SPEEDUP_FOR_AES) || \ + defined(WOLFSSL_AESNI) || defined(WOLFSSL_ARMASM) || \ + defined(WOLFSSL_SP_ASM)) && !defined(WOLFSSL_NO_ASM) + #define WC_HAVE_VECTOR_SPEEDUPS +#endif + +/* DISABLE_VECTOR_REGISTERS() and REENABLE_VECTOR_REGISTERS() are currently only + * used by Linux kernel code. If WC_HAVE_VECTOR_SPEEDUPS, we default + * DISABLE_VECTOR_REGISTERS() to -1, to assure calling code is forced to handle + * the failure. But if the build disables vec regs globally, we can return 0 + * harmlessly. The kernel build defines real calls for these in vectorized + * builds, otherwise it uses these fallbacks. + */ +#ifndef DISABLE_VECTOR_REGISTERS + #ifdef WC_HAVE_VECTOR_SPEEDUPS + #define DISABLE_VECTOR_REGISTERS() -1 + #else #define DISABLE_VECTOR_REGISTERS() 0 #endif - #ifndef REENABLE_VECTOR_REGISTERS - #define REENABLE_VECTOR_REGISTERS() WC_DO_NOTHING - #endif +#endif +#ifndef REENABLE_VECTOR_REGISTERS + #define REENABLE_VECTOR_REGISTERS() WC_DO_NOTHING #endif #ifndef WC_SANITIZE_DISABLE diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index b30a499f5..e2ffbf4a8 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -1714,6 +1714,10 @@ WOLFSSL_ABI WOLFSSL_API int wolfCrypt_Cleanup(void); #endif #endif +#if defined(WC_RNG_SEED_CB) && !defined(WC_GENERATE_SEED_DEFAULT) + #define WC_GENERATE_SEED_DEFAULT wc_GenerateSeed +#endif + #ifdef __cplusplus } /* extern "C" */ #endif From d9467db00754b61421293783c53f1ed380db93b2 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 22 Aug 2025 23:43:36 -0500 Subject: [PATCH 2/2] wolfssl/wolfcrypt/types.h: fix bugprone-macro-parentheses in definition of DISABLE_VECTOR_REGISTERS. --- wolfssl/wolfcrypt/types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 9ccfcb204..0dca2081d 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -2006,7 +2006,7 @@ WOLFSSL_API word32 CheckRunTimeSettings(void); */ #ifndef DISABLE_VECTOR_REGISTERS #ifdef WC_HAVE_VECTOR_SPEEDUPS - #define DISABLE_VECTOR_REGISTERS() -1 + #define DISABLE_VECTOR_REGISTERS() (-1) #else #define DISABLE_VECTOR_REGISTERS() 0 #endif