From 99a481b28e880060237e4146b654869df8edc76c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 22 Sep 2020 09:45:46 +0300 Subject: [PATCH] Use Intel intrinsic functions for RDSEED and RDRAND Starting with GCC 9 or clang 9, we can actually use without any problems. We only have to flag such functions where such instructions are being used. The benefit of using intrinsic functions over inline assembler is that the compiler is given more flexibility. In particular, clang -fsanitize=memory (MemorySanitizer, MSAN) will not raise bogus alarms about memory being uninitialized. Both intrinsic functions are available starting with GCC 5 and clang 3.8. The RDRAND wrapper is available starting with clang 3.7 via . Before GCC 9 and clang 9, the RDSEED wrapper is not available via but via , and only after jumping through some hoops to enable it. --- wolfcrypt/src/random.c | 47 +++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 0bc3443f4..c60906ce0 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -184,7 +184,32 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) #endif #ifdef USE_WINDOWS_API + #define USE_INTEL_INTRINSICS +#elif !defined __GNUC__ || defined __clang__ || __GNUC__ > 4 + #define USE_INTEL_INTRINSICS +#else + #undef USE_INTEL_INTRINSICS +#endif + +#ifdef USE_INTEL_INTRINSICS #include + /* Before clang 7 or GCC 9, immintrin.h did not define _rdseed64_step() */ + #ifndef HAVE_INTEL_RDSEED + #elif defined __clang__ && __clang_major__ > 6 + #elif !defined __GNUC__ + #elif __GNUC__ > 8 + #else + #ifndef __clang__ + #pragma GCC push_options + #pragma GCC target("rdseed") + #else + #define __RDSEED__ + #endif + #include + #ifndef __clang__ + #pragma GCC pop_options + #endif + #endif #endif /* USE_WINDOWS_API */ #endif @@ -1392,7 +1417,7 @@ int wc_FreeNetRandom(void) #ifdef HAVE_INTEL_RDSEED -#ifndef USE_WINDOWS_API +#ifndef USE_INTEL_INTRINSICS /* return 0 on success */ static WC_INLINE int IntelRDseed64(word64* seed) @@ -1403,20 +1428,23 @@ int wc_FreeNetRandom(void) return (ok) ? 0 : -1; } -#else /* USE_WINDOWS_API */ +#else /* USE_INTEL_INTRINSICS */ /* The compiler Visual Studio uses does not allow inline assembly. * It does allow for Intel intrinsic functions. */ /* return 0 on success */ +# ifdef __GNUC__ + __attribute__((target("rdseed"))) +# endif static WC_INLINE int IntelRDseed64(word64* seed) { int ok; - ok = _rdseed64_step(seed); + ok = _rdseed64_step((unsigned long long*) seed); return (ok) ? 0 : -1; } -#endif /* USE_WINDOWS_API */ +#endif /* USE_INTEL_INTRINSICS */ /* return 0 on success */ static WC_INLINE int IntelRDseed64_r(word64* rnd) @@ -1464,7 +1492,7 @@ static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz) #ifdef HAVE_INTEL_RDRAND -#ifndef USE_WINDOWS_API +#ifndef USE_INTEL_INTRINSICS /* return 0 on success */ static WC_INLINE int IntelRDrand64(word64 *rnd) @@ -1476,21 +1504,24 @@ static WC_INLINE int IntelRDrand64(word64 *rnd) return (ok) ? 0 : -1; } -#else /* USE_WINDOWS_API */ +#else /* USE_INTEL_INTRINSICS */ /* The compiler Visual Studio uses does not allow inline assembly. * It does allow for Intel intrinsic functions. */ /* return 0 on success */ +# ifdef __GNUC__ +__attribute__((target("rdrnd"))) +# endif static WC_INLINE int IntelRDrand64(word64 *rnd) { int ok; - ok = _rdrand64_step(rnd); + ok = _rdrand64_step((unsigned long long*) rnd); return (ok) ? 0 : -1; } -#endif /* USE_WINDOWS_API */ +#endif /* USE_INTEL_INTRINSICS */ /* return 0 on success */ static WC_INLINE int IntelRDrand64_r(word64 *rnd)