From 5e3d8e705e6b66cb2aa0cac4c2a3df61b937d03b Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 17 Mar 2017 13:29:03 -0700 Subject: [PATCH 1/5] Fix RNG issue with Intel RDRAND and RDSEED accelerations not being used because HAVE_HASHDRBG was always being defined if !WOLFSSL_FORCE_RC4_DRBG. Added new --enable-intelrand option to indicate use of RDRAND preference for RNG source (if RDRAND not supported by CPU then HASHDRBG will be used). The --enable-intelasm option enables the RDSEED support for seeding HASHDRBG if CPU supports it. Allow use of seed as RNG source if --disable-hashdbrg (shows build warning). Cleanup to remove old ARC4 RNG support. Fixed random_test return code with !HAVE_HASHDRBG. Cleanup of ./configure --help alignment. --- configure.ac | 27 +- wolfcrypt/src/random.c | 795 ++++++++++++++++------------------- wolfcrypt/test/test.c | 10 +- wolfssl/wolfcrypt/random.h | 70 ++- wolfssl/wolfcrypt/settings.h | 6 - 5 files changed, 428 insertions(+), 480 deletions(-) diff --git a/configure.ac b/configure.ac index 12e6fed6f..77bf2fbe5 100644 --- a/configure.ac +++ b/configure.ac @@ -228,7 +228,7 @@ fi AC_ARG_ENABLE([rng], - [AS_HELP_STRING([ --enable-rng Enable compiling and using RNG (default: enabled)])], + [AS_HELP_STRING([--enable-rng Enable compiling and using RNG (default: enabled)])], [ ENABLED_RNG=$enableval ], [ ENABLED_RNG=yes ] ) @@ -334,7 +334,7 @@ AM_CONDITIONAL([BUILD_IPV6], [test "x$ENABLED_IPV6" = "xyes"]) # wpa_supplicant support AC_ARG_ENABLE([wpas], - [ --enable-wpas Enable wpa_supplicant support (default: disabled)], + [ --enable-wpas Enable wpa_supplicant support (default: disabled)], [ ENABLED_WPAS=$enableval ], [ ENABLED_WPAS=no ] ) @@ -612,7 +612,7 @@ fi AM_CONDITIONAL([BUILD_ARMASM], [test "x$ENABLED_ARMASM" = "xyes"]) -# AES-NI +# INTEL AES-NI AC_ARG_ENABLE([aesni], [AS_HELP_STRING([--enable-aesni],[Enable wolfSSL AES-NI support (default: disabled)])], [ ENABLED_AESNI=$enableval ], @@ -626,6 +626,7 @@ AC_ARG_ENABLE([intelasm], [ ENABLED_INTELASM=no ] ) + if test "$ENABLED_AESNI" = "yes" || test "$ENABLED_INTELASM" = "yes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AESNI" @@ -643,10 +644,22 @@ fi if test "$ENABLED_INTELASM" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DHAVE_INTEL_RDGEN -DUSE_INTEL_SPEEDUP" + AM_CFLAGS="$AM_CFLAGS -DHAVE_INTEL_RDSEED -DUSE_INTEL_SPEEDUP" ENABLED_AESNI=yes fi +# INTEL RDRAND +AC_ARG_ENABLE([intelrand], + [AS_HELP_STRING([--enable-intelrand],[Enable Intel rdrand as preferred RNG source (default: disabled)])], + [ ENABLED_INTELRDRAND=$enableval ], + [ ENABLED_INTELRDRAND=no ] + ) + +if test "$ENABLED_INTELRDRAND" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_INTEL_RDRAND" +fi + AM_CONDITIONAL([BUILD_AESNI], [test "x$ENABLED_AESNI" = "xyes"]) @@ -1678,7 +1691,7 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_HASHDRBG" else # turn on Hash DRBG if FIPS is on or ARC4 is off - if test "x$ENABLED_FIPS" = "xyes" || test "x$ENABLED_ARC4" = "xno" + if test "x$ENABLED_FIPS" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_HASHDRBG" ENABLED_HASHDRBG=yes @@ -2018,7 +2031,7 @@ AC_ARG_ENABLE([maxfragment], # ALPN AC_ARG_ENABLE([alpn], - [ --enable-alpn Enable ALPN (default: disabled)], + [ --enable-alpn Enable ALPN (default: disabled)], [ ENABLED_ALPN=$enableval ], [ ENABLED_ALPN=no ] ) @@ -2956,7 +2969,7 @@ AM_CONDITIONAL([BUILD_MCAPI], [test "x$ENABLED_MCAPI" = "xyes"]) # Asynchronous Crypto AC_ARG_ENABLE([asynccrypt], - [ --enable-asynccrypt Enable Asynchronous Crypto (default: disabled)], + [ --enable-asynccrypt Enable Asynchronous Crypto (default: disabled)], [ ENABLED_ASYNCCRYPT=$enableval ], [ ENABLED_ASYNCCRYPT=no ] ) diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index cf0201ed6..a783141e8 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -33,13 +33,6 @@ #include -#if defined(CUSTOM_RAND_GENERATE) && !defined(CUSTOM_RAND_TYPE) -/* To maintain compatibility the default return value from CUSTOM_RAND_GENERATE is byte */ -#define CUSTOM_RAND_TYPE byte -#endif - -#define RNG_HEALTH_TEST_CHECK_SIZE (SHA256_DIGEST_SIZE * 4) - #ifdef HAVE_FIPS int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz) @@ -64,14 +57,13 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) return RNG_GenerateByte(rng, b); } -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#ifdef HAVE_HASHDRBG int wc_FreeRng(WC_RNG* rng) { return FreeRng_fips(rng); } - int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, const byte* entropyB, word32 entropyBSz, @@ -80,11 +72,15 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) return RNG_HealthTest_fips(reseed, entropyA, entropyASz, entropyB, entropyBSz, output, outputSz); } -#endif /* HAVE_HASHDRBG || NO_RC4 */ +#endif /* HAVE_HASHDRBG */ + #else /* else build without fips */ + #ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */ + #include + /* Allow custom RNG system */ #ifdef CUSTOM_RAND_GENERATE_BLOCK @@ -122,71 +118,65 @@ int wc_FreeRng(WC_RNG* rng) #else -/* Use HASHDRGB with SHA256 */ -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#include - #include - - #ifdef NO_INLINE - #include - #else - #define WOLFSSL_MISC_INCLUDED - #include - #endif -#endif /* HAVE_HASHDRBG || NO_RC4 */ +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif #if defined(WOLFSSL_SGX) -#include + #include #elif defined(USE_WINDOWS_API) #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #endif #include #include +#elif defined(HAVE_WNR) + #include + #include + wolfSSL_Mutex wnr_mutex; /* global netRandom mutex */ + int wnr_timeout = 0; /* entropy timeout, mililseconds */ + int wnr_mutex_init = 0; /* flag for mutex init */ + wnr_context* wnr_ctx; /* global netRandom context */ +#elif !defined(NO_DEV_RANDOM) && !defined(CUSTOM_RAND_GENERATE) && \ + !defined(WOLFSSL_GENSEED_FORTEST) && !defined(WOLFSSL_MDK_ARM) && \ + !defined(WOLFSSL_IAR_ARM) && !defined(WOLFSSL_ROWLEY_ARM) && \ + !defined(WOLFSSL_EMBOS) + #include + #ifndef EBSNET + #include + #endif +#elif defined(FREESCALE_KSDK_2_0_TRNG) + #include "fsl_trng.h" +#elif defined(FREESCALE_KSDK_2_0_RNGA) + #include "fsl_rnga.h" #else - #ifdef HAVE_WNR - #include - #include - wolfSSL_Mutex wnr_mutex; /* global netRandom mutex */ - int wnr_timeout = 0; /* entropy timeout, mililseconds */ - int wnr_mutex_init = 0; /* flag for mutex init */ - wnr_context* wnr_ctx; /* global netRandom context */ - #elif !defined(NO_DEV_RANDOM) && !defined(CUSTOM_RAND_GENERATE) && \ - !defined(WOLFSSL_GENSEED_FORTEST) && !defined(WOLFSSL_MDK_ARM) && \ - !defined(WOLFSSL_IAR_ARM) && !defined(WOLFSSL_ROWLEY_ARM) && \ - !defined(WOLFSSL_EMBOS) - #include - #ifndef EBSNET - #include - #endif - #elif defined(FREESCALE_KSDK_2_0_TRNG) - #include "fsl_trng.h" - #elif defined(FREESCALE_KSDK_2_0_RNGA) - #include "fsl_rnga.h" - #else - /* include headers that may be needed to get good seed */ - #endif -#endif /* USE_WINDOWS_API */ - -#ifdef HAVE_INTEL_RDGEN - static int wc_InitRng_IntelRD(void) ; - #if defined(HAVE_HASHDRBG) || defined(NO_RC4) - static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz) ; - #else - static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz) ; - #endif - static word32 cpuid_check = 0 ; - static word32 cpuid_flags = 0 ; - #define CPUID_RDRAND 0x4 - #define CPUID_RDSEED 0x8 - #define IS_INTEL_RDRAND (cpuid_flags&CPUID_RDRAND) - #define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) + /* include headers that may be needed to get good seed */ #endif -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) + static void wc_InitRng_IntelRD(void); + #ifdef HAVE_INTEL_RDSEED + static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz); + #endif + #ifdef HAVE_INTEL_RDRAND + static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz); + #endif + static word32 cpuid_check = 0; + static word32 cpuid_flags = 0; + #define CPUID_RDRAND 0x4 + #define CPUID_RDSEED 0x8 + #define IS_INTEL_RDRAND (cpuid_flags & CPUID_RDRAND) + #define IS_INTEL_RDSEED (cpuid_flags & CPUID_RDSEED) +#endif /* Start NIST DRBG code */ +#ifdef HAVE_HASHDRBG #define OUTPUT_BLOCK_LEN (SHA256_DIGEST_SIZE) #define MAX_REQUEST_LEN (0x10000) @@ -209,12 +199,13 @@ int wc_FreeRng(WC_RNG* rng) #define DRBG_FAILED 2 #define DRBG_CONT_FAILED 3 +#define RNG_HEALTH_TEST_CHECK_SIZE (SHA256_DIGEST_SIZE * 4) + /* Verify max gen block len */ #if RNG_MAX_BLOCK_LEN > MAX_REQUEST_LEN #error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length #endif - enum { drbgInitC = 0, drbgReseed = 1, @@ -295,7 +286,6 @@ static int Hash_df(DRBG* drbg, byte* out, word32 outSz, byte type, return DRBG_SUCCESS; } - /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_DRBG_Reseed(DRBG* drbg, const byte* entropy, word32 entropySz) { @@ -331,7 +321,6 @@ static INLINE void array_add_one(byte* data, word32 dataSz) } } - /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V) { @@ -393,7 +382,6 @@ static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V) return DRBG_SUCCESS; } - static INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen) { word16 carry = 0; @@ -416,7 +404,6 @@ static INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen) } } - /* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */ static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz) { @@ -455,7 +442,6 @@ static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz) return ret; } - /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz, const byte* nonce, word32 nonceSz) @@ -478,7 +464,6 @@ static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz, return ret; } - /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_DRBG_Uninstantiate(DRBG* drbg) { @@ -493,65 +478,93 @@ static int Hash_DRBG_Uninstantiate(DRBG* drbg) return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE; } - +#endif /* HAVE_HASHDRBG */ /* End NIST DRBG Code */ -/* Get seed and key cipher */ int wc_InitRng_ex(WC_RNG* rng, void* heap) { - int ret = BAD_FUNC_ARG; + int ret = RNG_FAILURE_E; + + if (rng == NULL) + return BAD_FUNC_ARG; - if (rng != NULL) { #ifdef WOLFSSL_HEAP_TEST - rng->heap = (void*)WOLFSSL_HEAP_TEST; - (void)heap; + rng->heap = (void*)WOLFSSL_HEAP_TEST; + (void)heap; #else - rng->heap = heap; + rng->heap = heap; #endif - if (wc_RNG_HealthTestLocal(0) == 0) { - byte entropy[ENTROPY_NONCE_SZ]; - rng->drbg = - (struct DRBG*)XMALLOC(sizeof(DRBG), rng->heap, - DYNAMIC_TYPE_RNG); - if (rng->drbg == NULL) { - ret = MEMORY_E; - } - /* This doesn't use a separate nonce. The entropy input will be - * the default size plus the size of the nonce making the seed - * size. */ - else if (wc_GenerateSeed(&rng->seed, - entropy, ENTROPY_NONCE_SZ) == 0 && - Hash_DRBG_Instantiate(rng->drbg, - entropy, ENTROPY_NONCE_SZ, NULL, 0) == DRBG_SUCCESS) { +#ifdef HAVE_HASHDRBG + /* init the DBRG to known values */ + rng->drbg = NULL; + rng->status = DRBG_NOT_INIT; +#endif - ret = Hash_DRBG_Generate(rng->drbg, NULL, 0); - } - else - ret = DRBG_FAILURE; +#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) + /* init the intel RD seed and/or rand */ + wc_InitRng_IntelRD(); +#endif - ForceZero(entropy, ENTROPY_NONCE_SZ); + /* configure async RNG source if available */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG, INVALID_DEVID); + if (ret != 0) + return ret; +#endif + + +#ifdef HAVE_INTEL_RDRAND + /* if CPU supports RDRAND, use it directly and by-pass DRBG init */ + if (IS_INTEL_RDRAND) + return 0; +#endif + +#ifdef HAVE_HASHDRBG + if (wc_RNG_HealthTestLocal(0) == 0) { + byte entropy[ENTROPY_NONCE_SZ]; + + rng->drbg = + (struct DRBG*)XMALLOC(sizeof(DRBG), rng->heap, + DYNAMIC_TYPE_RNG); + if (rng->drbg == NULL) { + ret = MEMORY_E; + } + /* This doesn't use a separate nonce. The entropy input will be + * the default size plus the size of the nonce making the seed + * size. */ + else if (wc_GenerateSeed(&rng->seed, + entropy, ENTROPY_NONCE_SZ) == 0 && + Hash_DRBG_Instantiate(rng->drbg, + entropy, ENTROPY_NONCE_SZ, NULL, 0) == DRBG_SUCCESS) { + + ret = Hash_DRBG_Generate(rng->drbg, NULL, 0); } else - ret = DRBG_CONT_FAILURE; + ret = DRBG_FAILURE; - if (ret == DRBG_SUCCESS) { - rng->status = DRBG_OK; - ret = 0; - } - else if (ret == DRBG_CONT_FAILURE) { - rng->status = DRBG_CONT_FAILED; - ret = DRBG_CONT_FIPS_E; - } - else if (ret == DRBG_FAILURE) { - rng->status = DRBG_FAILED; - ret = RNG_FAILURE_E; - } - else { - rng->status = DRBG_FAILED; - } + ForceZero(entropy, ENTROPY_NONCE_SZ); } + else + ret = DRBG_CONT_FAILURE; + + if (ret == DRBG_SUCCESS) { + rng->status = DRBG_OK; + ret = 0; + } + else if (ret == DRBG_CONT_FAILURE) { + rng->status = DRBG_CONT_FAILED; + ret = DRBG_CONT_FIPS_E; + } + else if (ret == DRBG_FAILURE) { + rng->status = DRBG_FAILED; + ret = RNG_FAILURE_E; + } + else { + rng->status = DRBG_FAILED; + } +#endif /* HAVE_HASHDRBG */ return ret; } @@ -567,14 +580,28 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) { int ret; - if (rng == NULL || output == NULL || sz > RNG_MAX_BLOCK_LEN) + if (rng == NULL || output == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_INTEL_RDRAND + if (IS_INTEL_RDRAND) + return wc_GenerateRand_IntelRD(NULL, output, sz); +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) { + return NitroxRngGenerateBlock(rng, output, sz); + } +#endif + +#ifdef HAVE_HASHDRBG + if (sz > RNG_MAX_BLOCK_LEN) return BAD_FUNC_ARG; if (rng->status != DRBG_OK) return RNG_FAILURE_E; ret = Hash_DRBG_Generate(rng->drbg, output, sz); - if (ret == DRBG_NEED_RESEED) { if (wc_RNG_HealthTestLocal(1) == 0) { byte entropy[ENTROPY_SZ]; @@ -607,8 +634,18 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) ret = RNG_FAILURE_E; rng->status = DRBG_FAILED; } - return ret; +#endif /* HAVE_HASHDRBG */ + + /* try using the generate seed direectly */ + ret = wc_GenerateSeed(&rng->seed, output, sz); + if (ret == 0) + return 0; + + /* if we get here then there is an RNG configuration error */ + (void)ret; + (void)sz; + return RNG_FAILURE_E; } @@ -620,26 +657,31 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) int wc_FreeRng(WC_RNG* rng) { - int ret = BAD_FUNC_ARG; + int ret = 0; - if (rng != NULL) { - if (rng->drbg != NULL) { - if (Hash_DRBG_Uninstantiate(rng->drbg) == DRBG_SUCCESS) - ret = 0; - else - ret = RNG_FAILURE_E; + if (rng == NULL) + return BAD_FUNC_ARG; - XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG); - rng->drbg = NULL; - } +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + wolfAsync_DevCtxFree(&rng->asyncDev); +#endif - rng->status = DRBG_NOT_INIT; +#ifdef HAVE_HASHDRBG + if (rng->drbg != NULL) { + if (Hash_DRBG_Uninstantiate(rng->drbg) != DRBG_SUCCESS) + ret = RNG_FAILURE_E; + + XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG); + rng->drbg = NULL; } + rng->status = DRBG_NOT_INIT; +#endif /* HAVE_HASHDRBG */ + return ret; } - +#ifdef HAVE_HASHDRBG int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, const byte* entropyB, word32 entropyBSz, byte* output, word32 outputSz) @@ -801,97 +843,7 @@ static int wc_RNG_HealthTestLocal(int reseed) return ret; } - -#else /* HAVE_HASHDRBG || NO_RC4 */ - -/* Get seed and key cipher */ -int wc_InitRng(WC_RNG* rng) -{ - int ret; -#ifdef WOLFSSL_SMALL_STACK - byte* key; - byte* junk; -#else - byte key[32]; - byte junk[256]; -#endif - -#ifdef HAVE_INTEL_RDGEN - wc_InitRng_IntelRD(); - if(IS_INTEL_RDRAND) return 0; -#endif - -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG, INVALID_DEVID); - if (ret != 0) return ret; -#endif - -#ifdef WOLFSSL_SMALL_STACK - key = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (key == NULL) - return MEMORY_E; - - junk = (byte*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (junk == NULL) { - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); - key = NULL; - return MEMORY_E; - } -#endif - - ret = wc_GenerateSeed(&rng->seed, key, 32); - - if (ret == 0) { - wc_Arc4SetKey(&rng->cipher, key, sizeof(key)); - - ret = wc_RNG_GenerateBlock(rng, junk, 256); /*rid initial state*/ - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(junk, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - -/* place a generated block in output */ -int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) -{ -#ifdef HAVE_INTEL_RDGEN - if(IS_INTEL_RDRAND) - return wc_GenerateRand_IntelRD(NULL, output, sz) ; -#endif -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) { - return NitroxRngGenerateBlock(rng, output, sz); - } -#endif - XMEMSET(output, 0, sz); - wc_Arc4Process(&rng->cipher, output, output, sz); - - return 0; -} - - -int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) -{ - return wc_RNG_GenerateBlock(rng, b, 1); -} - - -int wc_FreeRng(WC_RNG* rng) -{ - (void)rng; - -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - wolfAsync_DevCtxFree(&rng->asyncDev); -#endif - - return 0; -} - -#endif /* HAVE_HASHDRBG || NO_RC4 */ +#endif /* HAVE_HASHDRBG */ #ifdef HAVE_WNR @@ -992,7 +944,7 @@ int wc_FreeNetRandom(void) #endif /* HAVE_WNR */ -#if defined(HAVE_INTEL_RDGEN) +#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) #ifndef _MSC_VER #define cpuid(reg, leaf, sub)\ @@ -1016,36 +968,35 @@ int wc_FreeNetRandom(void) #define EDX 3 static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { - int got_intel_cpu=0; + int got_intel_cpu = 0; unsigned int reg[5]; - reg[4] = '\0' ; + reg[4] = '\0'; cpuid(reg, 0, 0); - if(XMEMCMP((char *)&(reg[EBX]), "Genu", 4) == 0 && - XMEMCMP((char *)&(reg[EDX]), "ineI", 4) == 0 && - XMEMCMP((char *)&(reg[ECX]), "ntel", 4) == 0) { + if (XMEMCMP((char *)&(reg[EBX]), "Genu", 4) == 0 && + XMEMCMP((char *)&(reg[EDX]), "ineI", 4) == 0 && + XMEMCMP((char *)&(reg[ECX]), "ntel", 4) == 0) + { got_intel_cpu = 1; } if (got_intel_cpu) { cpuid(reg, leaf, sub); - return((reg[num]>>bit)&0x1) ; + return ((reg[num] >> bit) & 0x1); } - return 0 ; + return 0; } -static int wc_InitRng_IntelRD() -{ - if(cpuid_check==0) { - if(cpuid_flag(1, 0, ECX, 30)){ cpuid_flags |= CPUID_RDRAND ;} - if(cpuid_flag(7, 0, EBX, 18)){ cpuid_flags |= CPUID_RDSEED ;} - cpuid_check = 1 ; +static void wc_InitRng_IntelRD(void) { + if (cpuid_check==0) { + if (cpuid_flag(1, 0, ECX, 30)) { cpuid_flags |= CPUID_RDRAND; } + if (cpuid_flag(7, 0, EBX, 18)) { cpuid_flags |= CPUID_RDSEED; } + cpuid_check = 1; } - return 1 ; } #define INTELRD_RETRY 32 -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#ifdef HAVE_INTEL_RDSEED /* return 0 on success */ static INLINE int IntelRDseed64(word64* seed) @@ -1053,97 +1004,110 @@ static INLINE int IntelRDseed64(word64* seed) unsigned char ok; __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok)); - if(ok){ - return 0 ; - } else - return 1; + return (ok) ? 0 : -1; } /* return 0 on success */ static INLINE int IntelRDseed64_r(word64* rnd) { int i; - for(i=0; i 0; sz-=8, output+=8) { - if(IS_INTEL_RDSEED)ret = IntelRDseed64_r((word64*)output); - else return 1 ; - if(ret) - return 1 ; + (void)os; + + if (!IS_INTEL_RDSEED) + 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 ; + if (sz == 0) + return 0; + + /* handle unaligned remainder */ + ret = IntelRDseed64_r(&rndTmp); + if (ret != 0) + return ret; + + XMEMCPY(output, &rndTmp, sz); - if(IS_INTEL_RDSEED)ret = IntelRDseed64_r(&rndTmp) ; - else return 1 ; - if(ret) - return 1 ; - XMEMCPY(output, &rndTmp, sz) ; return 0; } -#else /* HAVE_HASHDRBG || NO_RC4 */ +#endif /* HAVE_INTEL_RDSEED */ + +#ifdef HAVE_INTEL_RDRAND /* return 0 on success */ static INLINE int IntelRDrand32(unsigned int *rnd) { - int rdrand; unsigned char ok ; - __asm__ volatile("rdrand %0; setc %1":"=r"(rdrand), "=qm"(ok)); - if(ok){ - *rnd = rdrand; - return 0 ; - } else - return 1; + unsigned char ok; + + __asm__ volatile("rdrand %0; setc %1":"=r"(*rnd), "=qm"(ok)); + + return (ok) ? 0 : -1; } /* return 0 on success */ static INLINE int IntelRDrand32_r(unsigned int *rnd) { - int i ; - for(i=0; i 0; sz-=4, output+=4) { - if(IS_INTEL_RDRAND)ret = IntelRDrand32_r((word32 *)output); - else return 1 ; - if(ret) - return 1 ; - } - if(sz == 0)return 0 ; + (void)os; + + if (!IS_INTEL_RDRAND) + return -1; + + for (; (sz / sizeof(word32)) > 0; sz -= sizeof(word32), + output += sizeof(word32)) { + ret = IntelRDrand32_r((word32 *)output); + if (ret != 0) + return ret; + } + if (sz == 0) + return 0; + + /* handle unaligned remainder */ + ret = IntelRDrand32_r(&rndTmp); + if (ret != 0) + return ret; + + XMEMCPY(output, &rndTmp, sz); - if(IS_INTEL_RDRAND)ret = IntelRDrand32_r(&rndTmp); - else return 1 ; - if(ret) - return 1 ; - XMEMCPY(output, &rndTmp, sz) ; return 0; } -#endif /* defined(HAVE_HASHDRBG) || defined(NO_RC4) */ -#endif /* HAVE_INTEL_RDGEN */ +#endif /* HAVE_INTEL_RDRAND */ +#endif /* HAVE_INTEL_RDRAND || HAVE_INTEL_RDSEED */ -/* wc_GenerateSeed Implementations */ +/* Begin wc_GenerateSeed Implementations */ #if defined(CUSTOM_RAND_GENERATE_SEED) /* Implement your own random generation function @@ -1170,7 +1134,6 @@ static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz) return CUSTOM_RAND_GENERATE_SEED_OS(os, output, sz); } - #elif defined(CUSTOM_RAND_GENERATE) /* Implement your own random generation function @@ -1267,49 +1230,50 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #elif defined(MICROCHIP_PIC32) -#ifdef MICROCHIP_MPLAB_HARMONY - #define PIC32_SEED_COUNT _CP0_GET_COUNT -#else - #if !defined(WOLFSSL_MICROCHIP_PIC32MZ) - #include + #ifdef MICROCHIP_MPLAB_HARMONY + #define PIC32_SEED_COUNT _CP0_GET_COUNT + #else + #if !defined(WOLFSSL_MICROCHIP_PIC32MZ) + #include + #endif + #define PIC32_SEED_COUNT ReadCoreTimer #endif - #define PIC32_SEED_COUNT ReadCoreTimer -#endif + #ifdef WOLFSSL_MIC32MZ_RNG #include "xc.h" int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { - int i ; - byte rnd[8] ; - word32 *rnd32 = (word32 *)rnd ; - word32 size = sz ; - byte* op = output ; + int i; + byte rnd[8]; + word32 *rnd32 = (word32 *)rnd; + word32 size = sz; + byte* op = output; /* This part has to be replaced with better random seed */ RNGNUMGEN1 = ReadCoreTimer(); RNGPOLY1 = ReadCoreTimer(); RNGPOLY2 = ReadCoreTimer(); RNGNUMGEN2 = ReadCoreTimer(); -#ifdef DEBUG_WOLFSSL - printf("GenerateSeed::Seed=%08x, %08x\n", RNGNUMGEN1, RNGNUMGEN2) ; -#endif + #ifdef DEBUG_WOLFSSL + printf("GenerateSeed::Seed=%08x, %08x\n", RNGNUMGEN1, RNGNUMGEN2); + #endif RNGCONbits.PLEN = 0x40; RNGCONbits.PRNGEN = 1; for(i=0; i<5; i++) { /* wait for RNGNUMGEN ready */ - volatile int x ; - x = RNGNUMGEN1 ; - x = RNGNUMGEN2 ; + volatile int x; + x = RNGNUMGEN1; + x = RNGNUMGEN2; } do { rnd32[0] = RNGNUMGEN1; rnd32[1] = RNGNUMGEN2; for(i=0; i<8; i++, op++) { - *op = rnd[i] ; - size -- ; - if(size==0)break ; + *op = rnd[i]; + size --; + if(size==0)break; } - } while(size) ; + } while(size); return 0; } #else /* WOLFSSL_MIC32MZ_RNG */ @@ -1451,46 +1415,15 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) } #else - #warning "write a real random seed!!!!, just for testing now" - - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - int i; - for (i = 0; i < sz; i++ ) - output[i] = i; - - return 0; - } + #define USE_TEST_GENSEED #endif /* FREESCALE_K70_RNGA */ -#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) \ - || defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_MDK_ARM) \ - || defined(WOLFSSL_uITRON4) || defined(WOLFSSL_uTKERNEL2)\ - || defined(WOLFSSL_GENSEED_FORTEST) - -#ifndef _MSC_VER -#warning "write a real random seed!!!!, just for testing now" -#else -#pragma message("Warning: write a real random seed!!!!, just for testing now") -#endif - -int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - word32 i; - for (i = 0; i < sz; i++ ) - output[i] = i; - - (void)os; - - return 0; -} - #elif defined(STM32F2_RNG) || defined(STM32F4_RNG) /* * wc_Generate a RNG seed using the hardware random number generator * on the STM32F2/F4. */ -#ifdef WOLFSSL_STM32_CUBEMX + #ifdef WOLFSSL_STM32_CUBEMX int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { RNG_HandleTypeDef hrng; @@ -1511,7 +1444,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } -#else + #else int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { int i; @@ -1533,22 +1466,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } -#endif /* WOLFSSL_STM32_CUBEMX */ - -#elif defined(WOLFSSL_LPC43xx) || defined(WOLFSSL_STM32F2xx) || defined(MBED) \ - || defined(WOLFSSL_EMBOS) - - #warning "write a real random seed!!!!, just for testing now" - - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - int i; - - for (i = 0; i < sz; i++ ) - output[i] = i; - - return 0; - } + #endif /* WOLFSSL_STM32_CUBEMX */ #elif defined(WOLFSSL_TIRTOS) @@ -1693,93 +1611,122 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return ret; } -#elif defined(NO_DEV_RANDOM) - -#error "you need to write an os specific wc_GenerateSeed() here" - -/* -int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - return 0; -} -*/ - - #elif defined(IDIRECT_DEV_RANDOM) -extern int getRandom( int sz, unsigned char *output ); + extern int getRandom( int sz, unsigned char *output ); -int GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - int num_bytes_returned = 0; + int GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int num_bytes_returned = 0; - num_bytes_returned = getRandom( (int) sz, (unsigned char *) output ); + num_bytes_returned = getRandom( (int) sz, (unsigned char *) output ); - return 0; -} + return 0; + } +#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) \ + || defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_MDK_ARM) \ + || defined(WOLFSSL_uITRON4) || defined(WOLFSSL_uTKERNEL2) \ + || defined(WOLFSSL_LPC43xx) || defined(WOLFSSL_STM32F2xx) \ + || defined(MBED) || defined(WOLFSSL_EMBOS) \ + || defined(WOLFSSL_GENSEED_FORTEST) -#else /* !USE_WINDOWS_API && !HAVE_RPT_SYS && !MICRIUM && !NO_DEV_RANDOM */ + /* these platforms do not have a default random seed and + you need to implement your own wc_GenerateSeed */ -/* may block */ -int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - int ret = 0; + #define USE_TEST_GENSEED +#elif defined(NO_DEV_RANDOM) -#if defined(HAVE_INTEL_RDGEN) && (defined(HAVE_HASHDRBG) || defined(NO_RC4)) - wc_InitRng_IntelRD() ; /* set cpuid_flags if not yet */ - if(IS_INTEL_RDSEED) { - ret = wc_GenerateSeed_IntelRD(NULL, output, sz); - if (ret == 0) { - /* success, we're done */ + #error "you need to write an os specific wc_GenerateSeed() here" + + /* + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + return 0; + } + */ + +#else + + /* may block */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret = 0; + + #ifdef HAVE_INTEL_RDSEED + if (IS_INTEL_RDSEED) { + ret = wc_GenerateSeed_IntelRD(NULL, output, sz); + if (ret == 0) { + /* success, we're done */ + return ret; + } + #ifdef FORCE_FAILURE_RDSEED + /* don't fallback to /dev/urandom */ return ret; - } -#ifdef FORCE_FAILURE_RDSEED - /* don't fallback to /dev/urandom */ - return ret; -#else - /* fallback to /dev/urandom attempt */ - ret = 0; -#endif - } - -#endif - - os->fd = open("/dev/urandom",O_RDONLY); - if (os->fd == -1) { - /* may still have /dev/random */ - os->fd = open("/dev/random",O_RDONLY); - if (os->fd == -1) - return OPEN_RAN_E; - } - - while (sz) { - int len = (int)read(os->fd, output, sz); - if (len == -1) { - ret = READ_RAN_E; - break; + #else + /* fallback to /dev/urandom attempt */ + ret = 0; + #endif } - sz -= len; - output += len; + #endif /* HAVE_INTEL_RDSEED */ - if (sz) { -#ifdef BLOCKING - sleep(0); /* context switch */ -#else - ret = RAN_BLOCK_E; - break; -#endif + os->fd = open("/dev/urandom",O_RDONLY); + if (os->fd == -1) { + /* may still have /dev/random */ + os->fd = open("/dev/random",O_RDONLY); + if (os->fd == -1) + return OPEN_RAN_E; } + + while (sz) { + int len = (int)read(os->fd, output, sz); + if (len == -1) { + ret = READ_RAN_E; + break; + } + + sz -= len; + output += len; + + if (sz) { + #ifdef BLOCKING + sleep(0); /* context switch */ + #else + ret = RAN_BLOCK_E; + break; + #endif + } + } + close(os->fd); + + return ret; } - close(os->fd); - return ret; -} +#endif + +#ifdef USE_TEST_GENSEED + #ifndef _MSC_VER + #warning "write a real random seed!!!!, just for testing now" + #else + #pragma message("Warning: write a real random seed!!!!, just for testing now") + #endif + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 i; + for (i = 0; i < sz; i++ ) + output[i] = i; + + (void)os; + + return 0; + } +#endif + +/* End wc_GenerateSeed */ -#endif /* USE_WINDOWS_API */ #endif /* CUSTOM_RAND_GENERATE_BLOCK */ #endif /* WC_NO_RNG */ #endif /* HAVE_FIPS */ - diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 654742bfa..0981a0b04 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -5047,7 +5047,7 @@ exit: return ret; } -#if (defined(HAVE_HASHDRBG) || defined(NO_RC4)) && !defined(CUSTOM_RAND_GENERATE_BLOCK) +#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) int random_test(void) { @@ -5126,17 +5126,15 @@ int random_test(void) return 0; } -#else /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ +#else int random_test(void) { /* Basic RNG generate block test */ - random_rng_test(); - - return 0; + return random_rng_test(); } -#endif /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ +#endif /* HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK */ #endif /* WC_NO_RNG */ diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index 1669a6e26..a44ff8103 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -36,43 +36,59 @@ #endif /* Maximum generate block length */ -#define RNG_MAX_BLOCK_LEN (0x10000) +#ifndef RNG_MAX_BLOCK_LEN + #define RNG_MAX_BLOCK_LEN (0x10000) +#endif + +#if defined(CUSTOM_RAND_GENERATE) && !defined(CUSTOM_RAND_TYPE) + /* To maintain compatibility the default is byte */ + #define CUSTOM_RAND_TYPE byte +#endif + #ifndef HAVE_FIPS /* avoid redefining structs and macros */ -#if defined(WOLFSSL_FORCE_RC4_DRBG) && defined(NO_RC4) - #error Cannot have WOLFSSL_FORCE_RC4_DRBG and NO_RC4 defined. -#endif /* WOLFSSL_FORCE_RC4_DRBG && NO_RC4 */ - /* RNG supports the following sources (in order): * 1. CUSTOM_RAND_GENERATE_BLOCK: Defines name of function as RNG source and - * bypasses the P-RNG. - * 2. HAVE_HASHDRBG && !NO_SHA256 (SHA256 enabled): Uses SHA256 based P-RNG + * bypasses the options below. + * 2. HAVE_INTEL_RDRAND: Uses the Intel RDRAND if supported by CPU. + * 3. HAVE_HASHDRBG (requires SHA256 enabled): Uses SHA256 based P-RNG * seeded via wc_GenerateSeed. This is the default source. - * 3. !NO_RC4 (RC4 enabled): Uses RC4 + * 4. Fallback to using wc_GenerateSeed directly. */ + /* Seed source can be overriden by defining one of these: + CUSTOM_RAND_GENERATE_SEED + CUSTOM_RAND_GENERATE_SEED_OS + CUSTOM_RAND_GENERATE */ + + #if defined(CUSTOM_RAND_GENERATE_BLOCK) /* To use define the following: * #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc * extern int myRngFunc(byte* output, word32 sz); */ -#elif (defined(HAVE_HASHDRBG) || defined(NO_RC4)) +#elif defined(HAVE_HASHDRBG) #ifdef NO_SHA256 #error "Hash DRBG requires SHA-256." #endif /* NO_SHA256 */ - #include +#elif defined(HAVE_INTEL_RDRAND) +#elif defined(HAVE_WNR) #else - #include + #warning No RNG source defined. Using wc_GenerateSeed directly #endif - #ifdef HAVE_WNR #include #endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + + #if defined(USE_WINDOWS_API) #if defined(_WIN64) typedef unsigned __int64 ProviderHandle; @@ -98,46 +114,26 @@ typedef struct OS_Seed { #define WC_RNG_TYPE_DEFINED #endif -#if (defined(HAVE_HASHDRBG) || defined(NO_RC4)) && !defined(CUSTOM_RAND_GENERATE_BLOCK) +#ifndef CUSTOM_RAND_GENERATE_BLOCK #define DRBG_SEED_LEN (440/8) - struct DRBG; /* Private DRBG state */ - /* Hash-based Deterministic Random Bit Generator */ struct WC_RNG { +#ifdef HAVE_HASHDRBG struct DRBG* drbg; + byte status; +#endif OS_Seed seed; void* heap; - byte status; -}; - - - -#else /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ - -#ifdef WOLFSSL_ASYNC_CRYPT - #include -#endif - -/* secure Random Number Generator */ - - -struct WC_RNG { - OS_Seed seed; -#ifndef NO_RC4 - Arc4 cipher; -#endif #ifdef WOLFSSL_ASYNC_CRYPT AsyncCryptDev asyncDev; #endif }; - - -#endif /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ +#endif /* !CUSTOM_RAND_GENERATE_BLOCK */ #endif /* HAVE_FIPS */ /* NO_OLD_RNGNAME removes RNG struct name to prevent possible type conflicts, diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 9e16be339..1a9212d36 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -1405,12 +1405,6 @@ extern void uITRON4_free(void *p) ; #define WOLFSSL_MIN_AUTH_TAG_SZ 12 #endif -/* If not forcing ARC4 as the DRBG or using custom RNG block gen, enable Hash_DRBG */ -#undef HAVE_HASHDRBG -#if !defined(WOLFSSL_FORCE_RC4_DRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) - #define HAVE_HASHDRBG -#endif - /* sniffer requires: * static RSA cipher suites From 1251607b046a2900bb6c1857d7d690f44b96926a Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 17 Mar 2017 13:44:53 -0700 Subject: [PATCH 2/5] Retain existing HAVE_HASHDRBG functionality and only disable if ./configure --disable-hashdrbg or WC_NO_HASHDRBG defined. Fix use of warning with VS. Fix to only use rng seed as source if no DRBG. --- configure.ac | 4 +++- wolfcrypt/src/random.c | 10 +++++----- wolfssl/wolfcrypt/random.h | 13 +++++++++++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index 77bf2fbe5..93c766194 100644 --- a/configure.ac +++ b/configure.ac @@ -1690,11 +1690,13 @@ if test "x$ENABLED_HASHDRBG" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_HASHDRBG" else - # turn on Hash DRBG if FIPS is on or ARC4 is off + # turn on Hash DRBG if FIPS is on if test "x$ENABLED_FIPS" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_HASHDRBG" ENABLED_HASHDRBG=yes + else + AM_CFLAGS="$AM_CFLAGS -DWC_NO_HASHDRBG" fi fi diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index a783141e8..1c45f0872 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -634,8 +634,7 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) ret = RNG_FAILURE_E; rng->status = DRBG_FAILED; } - return ret; -#endif /* HAVE_HASHDRBG */ +#else /* try using the generate seed direectly */ ret = wc_GenerateSeed(&rng->seed, output, sz); @@ -643,9 +642,10 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) return 0; /* if we get here then there is an RNG configuration error */ - (void)ret; - (void)sz; - return RNG_FAILURE_E; + ret = RNG_FAILURE_E; +#endif /* HAVE_HASHDRBG */ + + return ret; } diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index a44ff8103..7ab7c7d06 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -45,10 +45,15 @@ #define CUSTOM_RAND_TYPE byte #endif +/* make sure Hash DRBG is enabled, unless WC_NO_HASHDRBG is defined */ +#ifndef WC_NO_HASHDRBG + #undef HAVE_HASHDRBG + #define HAVE_HASHDRBG +#endif + #ifndef HAVE_FIPS /* avoid redefining structs and macros */ - /* RNG supports the following sources (in order): * 1. CUSTOM_RAND_GENERATE_BLOCK: Defines name of function as RNG source and * bypasses the options below. @@ -77,7 +82,11 @@ #elif defined(HAVE_INTEL_RDRAND) #elif defined(HAVE_WNR) #else - #warning No RNG source defined. Using wc_GenerateSeed directly + #ifndef _MSC_VER + #warning "No RNG source defined. Using wc_GenerateSeed directly" + #else + #pragma message("Warning: No RNG source defined. Using wc_GenerateSeed directly") + #endif #endif #ifdef HAVE_WNR From 69535198ca0db34f86185843c9538a4b2f1004b8 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 20 Mar 2017 09:08:44 -0700 Subject: [PATCH 3/5] Fix RNG to only allow disabling HASHDRBG if CUSTOM_RAND_GENERATE_BLOCK is defined. Added support for CUSTOM_RAND_GENERATE_BLOCK with Intel RDRAND. --- wolfcrypt/src/random.c | 65 +++++++++++--------------------------- wolfssl/wolfcrypt/random.h | 11 ++++--- 2 files changed, 24 insertions(+), 52 deletions(-) diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 1c45f0872..f2b6ec2da 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -79,45 +79,6 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) #ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */ #include - - -/* Allow custom RNG system */ -#ifdef CUSTOM_RAND_GENERATE_BLOCK - -int wc_InitRng_ex(WC_RNG* rng, void* heap) -{ - (void)rng; - (void)heap; - return 0; -} - -int wc_InitRng(WC_RNG* rng) -{ - return wc_InitRng_ex(rng, NULL); -} - -int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) -{ - (void)rng; - XMEMSET(output, 0, sz); - return CUSTOM_RAND_GENERATE_BLOCK(output, sz); -} - - -int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) -{ - return wc_RNG_GenerateBlock(rng, b, 1); -} - - -int wc_FreeRng(WC_RNG* rng) -{ - (void)rng; - return 0; -} - -#else - #include #ifdef NO_INLINE @@ -594,6 +555,11 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) } #endif +#ifdef CUSTOM_RAND_GENERATE_BLOCK + XMEMSET(output, 0, sz); + return CUSTOM_RAND_GENERATE_BLOCK(output, sz); +#endif + #ifdef HAVE_HASHDRBG if (sz > RNG_MAX_BLOCK_LEN) return BAD_FUNC_ARG; @@ -1624,15 +1590,21 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } -#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) \ - || defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_MDK_ARM) \ - || defined(WOLFSSL_uITRON4) || defined(WOLFSSL_uTKERNEL2) \ - || defined(WOLFSSL_LPC43xx) || defined(WOLFSSL_STM32F2xx) \ - || defined(MBED) || defined(WOLFSSL_EMBOS) \ - || defined(WOLFSSL_GENSEED_FORTEST) +#elif defined(WOLFSSL_SAFERTOS) +#elif defined(WOLFSSL_LEANPSK) +#elif defined(WOLFSSL_IAR_ARM) +#elif defined(WOLFSSL_MDK_ARM) +#elif defined(WOLFSSL_uITRON4) +#elif defined(WOLFSSL_uTKERNEL2) +#elif defined(WOLFSSL_LPC43xx) +#elif defined(WOLFSSL_STM32F2xx) +#elif defined(MBED) +#elif defined(WOLFSSL_EMBOS) +#elif defined(WOLFSSL_GENSEED_FORTEST) /* these platforms do not have a default random seed and - you need to implement your own wc_GenerateSeed */ + you'll need to implement your own wc_GenerateSeed or define via + CUSTOM_RAND_GENERATE_BLOCK */ #define USE_TEST_GENSEED @@ -1727,6 +1699,5 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) /* End wc_GenerateSeed */ -#endif /* CUSTOM_RAND_GENERATE_BLOCK */ #endif /* WC_NO_RNG */ #endif /* HAVE_FIPS */ diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index 7ab7c7d06..a4e068f1d 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -45,8 +45,9 @@ #define CUSTOM_RAND_TYPE byte #endif -/* make sure Hash DRBG is enabled, unless WC_NO_HASHDRBG is defined */ -#ifndef WC_NO_HASHDRBG +/* make sure Hash DRBG is enabled, unless WC_NO_HASHDRBG is defined + or CUSTOM_RAND_GENERATE_BLOCK is defined*/ +#if !defined(WC_NO_HASHDRBG) || !defined(CUSTOM_RAND_GENERATE_BLOCK) #undef HAVE_HASHDRBG #define HAVE_HASHDRBG #endif @@ -79,8 +80,8 @@ #error "Hash DRBG requires SHA-256." #endif /* NO_SHA256 */ #include -#elif defined(HAVE_INTEL_RDRAND) #elif defined(HAVE_WNR) + /* allow whitewood as direct RNG source using wc_GenerateSeed directly */ #else #ifndef _MSC_VER #warning "No RNG source defined. Using wc_GenerateSeed directly" @@ -169,12 +170,12 @@ WOLFSSL_API int wc_RNG_GenerateByte(WC_RNG*, byte*); WOLFSSL_API int wc_FreeRng(WC_RNG*); -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#ifdef HAVE_HASHDRBG WOLFSSL_API int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, const byte* entropyB, word32 entropyBSz, byte* output, word32 outputSz); -#endif /* HAVE_HASHDRBG || NO_RC4 */ +#endif /* HAVE_HASHDRBG */ #ifdef __cplusplus } /* extern "C" */ From c5328196595199ecc5aeac898e61014422980e5d Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 22 Mar 2017 10:23:37 -0700 Subject: [PATCH 4/5] =?UTF-8?q?Fixes=20for=20building=20with=20=E2=80=9CCU?= =?UTF-8?q?STOM=5FRAND=5FGENERATE=5FBLOCK=E2=80=9D.=20Removed=20seed=20as?= =?UTF-8?q?=20backup=20RNG=20source.=20Fixed=20building=20on=20embedded=20?= =?UTF-8?q?system=20with=20time=5Ft=20not=20defined=20(test.c=20should=20u?= =?UTF-8?q?se=20long=20for=20asn=5Ftest).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IDE/ROWLEY-CROSSWORKS-ARM/user_settings.h | 12 +++++--- IDE/ROWLEY-CROSSWORKS-ARM/wolfssl.hzp | 26 ++++++++++++---- wolfcrypt/src/random.c | 32 ++++++++++++-------- wolfcrypt/test/test.c | 4 +-- wolfssl/wolfcrypt/random.h | 37 ++++++++++++----------- 5 files changed, 67 insertions(+), 44 deletions(-) diff --git a/IDE/ROWLEY-CROSSWORKS-ARM/user_settings.h b/IDE/ROWLEY-CROSSWORKS-ARM/user_settings.h index 5641973c9..95a795e02 100644 --- a/IDE/ROWLEY-CROSSWORKS-ARM/user_settings.h +++ b/IDE/ROWLEY-CROSSWORKS-ARM/user_settings.h @@ -278,17 +278,21 @@ extern "C" { /* Size of returned HW RNG value */ #define CUSTOM_RAND_TYPE unsigned int +/* Seed source */ +extern unsigned int custom_rand_generate(void); +#undef CUSTOM_RAND_GENERATE +#define CUSTOM_RAND_GENERATE custom_rand_generate + /* Choose RNG method */ #if 1 /* Use built-in P-RNG (SHA256 based) with HW RNG */ /* P-RNG + HW RNG (P-RNG is ~8K) */ #undef HAVE_HASHDRBG #define HAVE_HASHDRBG - - extern unsigned int custom_rand_generate(void); - #undef CUSTOM_RAND_GENERATE - #define CUSTOM_RAND_GENERATE custom_rand_generate #else + #undef WC_NO_HASHDRBG + #define WC_NO_HASHDRBG + /* Bypass P-RNG and use only HW RNG */ extern int custom_rand_generate_block(unsigned char* output, unsigned int sz); #undef CUSTOM_RAND_GENERATE_BLOCK diff --git a/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl.hzp b/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl.hzp index 3deb98b3e..8b228c4c4 100644 --- a/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl.hzp +++ b/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl.hzp @@ -122,12 +122,26 @@ recurse="Yes" /> - + + + + + + + + + + + + + + + + + + + + diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index f2b6ec2da..0adbd6413 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -103,20 +103,25 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) int wnr_timeout = 0; /* entropy timeout, mililseconds */ int wnr_mutex_init = 0; /* flag for mutex init */ wnr_context* wnr_ctx; /* global netRandom context */ -#elif !defined(NO_DEV_RANDOM) && !defined(CUSTOM_RAND_GENERATE) && \ - !defined(WOLFSSL_GENSEED_FORTEST) && !defined(WOLFSSL_MDK_ARM) && \ - !defined(WOLFSSL_IAR_ARM) && !defined(WOLFSSL_ROWLEY_ARM) && \ - !defined(WOLFSSL_EMBOS) - #include - #ifndef EBSNET - #include - #endif #elif defined(FREESCALE_KSDK_2_0_TRNG) #include "fsl_trng.h" #elif defined(FREESCALE_KSDK_2_0_RNGA) #include "fsl_rnga.h" + +#elif defined(NO_DEV_RANDOM) +#elif defined(CUSTOM_RAND_GENERATE) +#elif defined(CUSTOM_RAND_GENERATE_BLOCK) +#elif defined(WOLFSSL_GENSEED_FORTEST) +#elif defined(WOLFSSL_MDK_ARM) +#elif defined(WOLFSSL_IAR_ARM) +#elif defined(WOLFSSL_ROWLEY_ARM) +#elif defined(WOLFSSL_EMBOS) #else /* include headers that may be needed to get good seed */ + #include + #ifndef EBSNET + #include + #endif #endif @@ -602,13 +607,9 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) } #else - /* try using the generate seed direectly */ - ret = wc_GenerateSeed(&rng->seed, output, sz); - if (ret == 0) - return 0; - /* if we get here then there is an RNG configuration error */ ret = RNG_FAILURE_E; + #endif /* HAVE_HASHDRBG */ return ret; @@ -1590,6 +1591,11 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } +#elif defined(CUSTOM_RAND_GENERATE_BLOCK) + /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc + * extern int myRngFunc(byte* output, word32 sz); + */ + #elif defined(WOLFSSL_SAFERTOS) #elif defined(WOLFSSL_LEANPSK) #elif defined(WOLFSSL_IAR_ARM) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 0981a0b04..c624a892b 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -1025,8 +1025,7 @@ int base64_test() int asn_test() { #ifndef NO_ASN_TIME - { - time_t now; + long now; /* Parameter Validation tests. */ if (wc_GetTime(NULL, sizeof(now)) != BAD_FUNC_ARG) @@ -1039,7 +1038,6 @@ int asn_test() return -102; if (now == 0) return -103; - } #endif return 0; diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index a4e068f1d..75fc5ebd9 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -35,11 +35,17 @@ extern "C" { #endif -/* Maximum generate block length */ + /* Maximum generate block length */ #ifndef RNG_MAX_BLOCK_LEN #define RNG_MAX_BLOCK_LEN (0x10000) #endif +/* Size of the BRBG seed */ +#ifndef DRBG_SEED_LEN + #define DRBG_SEED_LEN (440/8) +#endif + + #if defined(CUSTOM_RAND_GENERATE) && !defined(CUSTOM_RAND_TYPE) /* To maintain compatibility the default is byte */ #define CUSTOM_RAND_TYPE byte @@ -61,7 +67,6 @@ * 2. HAVE_INTEL_RDRAND: Uses the Intel RDRAND if supported by CPU. * 3. HAVE_HASHDRBG (requires SHA256 enabled): Uses SHA256 based P-RNG * seeded via wc_GenerateSeed. This is the default source. - * 4. Fallback to using wc_GenerateSeed directly. */ /* Seed source can be overriden by defining one of these: @@ -83,11 +88,7 @@ #elif defined(HAVE_WNR) /* allow whitewood as direct RNG source using wc_GenerateSeed directly */ #else - #ifndef _MSC_VER - #warning "No RNG source defined. Using wc_GenerateSeed directly" - #else - #pragma message("Warning: No RNG source defined. Using wc_GenerateSeed directly") - #endif + #error No RNG source defined! #endif #ifdef HAVE_WNR @@ -124,26 +125,25 @@ typedef struct OS_Seed { #define WC_RNG_TYPE_DEFINED #endif -#ifndef CUSTOM_RAND_GENERATE_BLOCK - -#define DRBG_SEED_LEN (440/8) - -struct DRBG; /* Private DRBG state */ - -/* Hash-based Deterministic Random Bit Generator */ -struct WC_RNG { #ifdef HAVE_HASHDRBG + /* Private DRBG state */ + struct DRBG; +#endif + +/* RNG context */ +struct WC_RNG { + OS_Seed seed; + void* heap; +#ifdef HAVE_HASHDRBG + /* Hash-based Deterministic Random Bit Generator */ struct DRBG* drbg; byte status; #endif - OS_Seed seed; - void* heap; #ifdef WOLFSSL_ASYNC_CRYPT AsyncCryptDev asyncDev; #endif }; -#endif /* !CUSTOM_RAND_GENERATE_BLOCK */ #endif /* HAVE_FIPS */ /* NO_OLD_RNGNAME removes RNG struct name to prevent possible type conflicts, @@ -152,6 +152,7 @@ struct WC_RNG { #define RNG WC_RNG #endif + WOLFSSL_LOCAL int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz); From d69c860ab87f3e70160e8768e3eabe7ca01c2bd7 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 27 Mar 2017 08:53:54 -0700 Subject: [PATCH 5/5] =?UTF-8?q?Fix=20bad=20#elif=20logic=20cleanup=20for?= =?UTF-8?q?=20using=20=E2=80=9CUSE=5FTEST=5FGENSEED=E2=80=9D.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wolfcrypt/src/random.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 0adbd6413..905a10479 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -1596,17 +1596,12 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) * extern int myRngFunc(byte* output, word32 sz); */ -#elif defined(WOLFSSL_SAFERTOS) -#elif defined(WOLFSSL_LEANPSK) -#elif defined(WOLFSSL_IAR_ARM) -#elif defined(WOLFSSL_MDK_ARM) -#elif defined(WOLFSSL_uITRON4) -#elif defined(WOLFSSL_uTKERNEL2) -#elif defined(WOLFSSL_LPC43xx) -#elif defined(WOLFSSL_STM32F2xx) -#elif defined(MBED) -#elif defined(WOLFSSL_EMBOS) -#elif defined(WOLFSSL_GENSEED_FORTEST) +#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) || \ + defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_MDK_ARM) || \ + defined(WOLFSSL_uITRON4) || defined(WOLFSSL_uTKERNEL2) || \ + defined(WOLFSSL_LPC43xx) || defined(WOLFSSL_STM32F2xx) || \ + defined(MBED) || defined(WOLFSSL_EMBOS) || \ + defined(WOLFSSL_GENSEED_FORTEST) /* these platforms do not have a default random seed and you'll need to implement your own wc_GenerateSeed or define via