diff --git a/IDE/apple-universal/wolfssl-multiplatform/wolfssl-multiplatform/wolfssl_test_driver.c b/IDE/apple-universal/wolfssl-multiplatform/wolfssl-multiplatform/wolfssl_test_driver.c index ab9cc83ac..bf36871ec 100644 --- a/IDE/apple-universal/wolfssl-multiplatform/wolfssl-multiplatform/wolfssl_test_driver.c +++ b/IDE/apple-universal/wolfssl-multiplatform/wolfssl-multiplatform/wolfssl_test_driver.c @@ -44,7 +44,7 @@ void wolfssl_test(void) test_func_args args = {0}; #ifdef WC_RNG_SEED_CB - wc_SetSeed_Cb(wc_GenerateSeed); + wc_SetSeed_Cb(WC_GENERATE_SEED_DEFAULT); #endif printf("Run wolfCrypt Test:\n"); diff --git a/examples/server/server.c b/examples/server/server.c index daba2a0a7..934074274 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -4082,7 +4082,7 @@ exit: #endif wolfSSL_Init(); #ifdef WC_RNG_SEED_CB - wc_SetSeed_Cb(wc_GenerateSeed); + wc_SetSeed_Cb(WC_GENERATE_SEED_DEFAULT); #endif ChangeToWolfRoot(); diff --git a/linuxkm/linuxkm_wc_port.h b/linuxkm/linuxkm_wc_port.h index c4e451b3e..7d2d2d3a4 100644 --- a/linuxkm/linuxkm_wc_port.h +++ b/linuxkm/linuxkm_wc_port.h @@ -161,10 +161,17 @@ #ifndef WOLFSSL_LINUXKM_USE_SAVE_VECTOR_REGISTERS #define WOLFSSL_LINUXKM_USE_SAVE_VECTOR_REGISTERS #endif - #else - #ifndef WOLFSSL_NO_ASM - #define WOLFSSL_NO_ASM - #endif + #endif + + #if defined(HAVE_HASHDRBG) && defined(HAVE_FIPS) && FIPS_VERSION3_LT(6, 0, 0) && \ + (defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)) && \ + !defined(WC_LINUXKM_RDSEED_IN_GLUE_LAYER) + #define WC_LINUXKM_RDSEED_IN_GLUE_LAYER + #endif + #ifdef WC_LINUXKM_RDSEED_IN_GLUE_LAYER + struct OS_Seed; + extern int wc_linuxkm_GenerateSeed_IntelRD(struct OS_Seed* os, unsigned char* output, unsigned int sz); + #define WC_GENERATE_SEED_DEFAULT wc_linuxkm_GenerateSeed_IntelRD #endif #ifdef BUILDING_WOLFSSL diff --git a/linuxkm/lkcapi_sha_glue.c b/linuxkm/lkcapi_sha_glue.c index 0ba8a6c1e..0e73dd981 100644 --- a/linuxkm/lkcapi_sha_glue.c +++ b/linuxkm/lkcapi_sha_glue.c @@ -1292,7 +1292,7 @@ static int wc_linuxkm_drbg_loaded = 0; #ifdef LINUXKM_DRBG_GET_RANDOM_BYTES #if !(defined(HAVE_ENTROPY_MEMUSE) || defined(HAVE_INTEL_RDSEED) || \ - defined(HAVE_AMD_RDSEED)) + defined(HAVE_AMD_RDSEED) || defined(WC_LINUXKM_RDSEED_IN_GLUE_LAYER)) #error LINUXKM_DRBG_GET_RANDOM_BYTES requires a native or intrinsic entropy source. #endif diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index d9e0064fb..aedd1a04c 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -264,6 +264,104 @@ void wc_linuxkm_relax_long_loop(void) { #endif } +/* backported wc_GenerateSeed_IntelRD() for FIPS v5. */ +#ifdef WC_LINUXKM_RDSEED_IN_GLUE_LAYER + +#include +#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..0dca2081d 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