From 4f7fee38d6acd63eafc86fd9bdb5bee7e27548d2 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Tue, 9 May 2017 13:20:53 -0400 Subject: [PATCH] Mkaake RDRAND and RDSEED throw if not available Fix Carmichael pseudo-prime tests --- rdrand.cpp | 68 ++++++++++++++++++++++++++++++---------------- rdrand.h | 9 +++--- validat0.cpp | 10 ++++--- validat1.cpp | 77 +++++++++++++++++++++++++++++----------------------- 4 files changed, 98 insertions(+), 66 deletions(-) diff --git a/rdrand.cpp b/rdrand.cpp index 75889f1d..d18f3bd0 100644 --- a/rdrand.cpp +++ b/rdrand.cpp @@ -126,15 +126,16 @@ NAMESPACE_BEGIN(CryptoPP) inline void RDRAND32(void* output) { #if defined(__SUNPRO_CC) - __asm__ __volatile__ + __asm__ ( + "1:\n" ".byte 0x0f, 0xc7, 0xf0;\n" - ".byte 0x73, 0xfb;\n" + "jnc 1b;\n" : "=a" (*reinterpret_cast(output)) : : "cc" ); #elif defined(GCC_RDRAND_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 40600) - __asm__ __volatile__ + __asm__ ( INTEL_NOPREFIX ASL(1) @@ -145,10 +146,11 @@ inline void RDRAND32(void* output) : : "cc" ); #elif defined(GCC_RDRAND_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 30200) - __asm__ __volatile__ + __asm__ ( + "1:\n" ".byte 0x0f, 0xc7, 0xf0;\n" - ".byte 0x73, 0xfb;\n" + "jnc 1b;\n" : "=a" (*reinterpret_cast(output)) : : "cc" ); @@ -165,15 +167,16 @@ inline void RDRAND32(void* output) inline void RDRAND64(void* output) { #if defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5100) - __asm__ __volatile__ + __asm__ ( + "1:\n" ".byte 0x48, 0x0f, 0xc7, 0xf0;\n" - ".byte 0x73, 0xfa;\n" + "jnc 1b;\n" : "=a" (*reinterpret_cast(output)) : : "cc" ); #elif defined(GCC_RDRAND_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 40600) - __asm__ __volatile__ + __asm__ ( INTEL_NOPREFIX ASL(1) @@ -184,10 +187,11 @@ inline void RDRAND64(void* output) : : "cc" ); #elif defined(GCC_RDRAND_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 30200) - __asm__ __volatile__ + __asm__ ( + "1:\n" ".byte 0x48, 0x0f, 0xc7, 0xf0;\n" - ".byte 0x73, 0xfa;\n" + "jnc 1b;\n" : "=a" (*reinterpret_cast(output)) : : "cc" ); @@ -200,6 +204,12 @@ inline void RDRAND64(void* output) } #endif // CRYPTOPP_BOOL_X64, CRYPTOPP_BOOL_X32 and RDRAND64 +RDRAND::RDRAND() +{ + if (!HasRDRAND()) + throw RDRAND_Err("HasRDRAND"); +} + void RDRAND::GenerateBlock(byte *output, size_t size) { CRYPTOPP_ASSERT((output && size) || !(output || size)); @@ -225,7 +235,7 @@ void RDRAND::GenerateBlock(byte *output, size_t size) { word64 val; RDRAND64(&val); - std::memcpy(output, &val, size); + ::memcpy(output, &val, size); } #elif CRYPTOPP_BOOL_X86 size_t i = 0; @@ -239,7 +249,7 @@ void RDRAND::GenerateBlock(byte *output, size_t size) { word32 val; RDRAND32(&val); - std::memcpy(output, &val, size); + ::memcpy(output, &val, size); } #else // RDRAND not detected at compile time, or no suitable compiler found @@ -270,15 +280,16 @@ void RDRAND::DiscardBytes(size_t n) inline void RDSEED32(void* output) { #if defined(__SUNPRO_CC) - __asm__ __volatile__ + __asm__ ( + "1:\n" ".byte 0x0f, 0xc7, 0xf8;\n" - ".byte 0x73, 0xfb;\n" + "jnc 1b;\n" : "=a" (*reinterpret_cast(output)) : : "cc" ); #elif defined(GCC_RDSEED_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 40600) - __asm__ __volatile__ + __asm__ ( INTEL_NOPREFIX ASL(1) @@ -289,10 +300,11 @@ inline void RDSEED32(void* output) : : "cc" ); #elif defined(GCC_RDSEED_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 30200) - __asm__ __volatile__ + __asm__ ( + "1:\n" ".byte 0x0f, 0xc7, 0xf8;\n" - ".byte 0x73, 0xfb;\n" + "jnc 1b;\n" : "=a" (*reinterpret_cast(output)) : : "cc" ); @@ -309,15 +321,16 @@ inline void RDSEED32(void* output) inline void RDSEED64(void* output) { #if defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5100) - __asm__ __volatile__ + __asm__ ( + "1:\n" ".byte 0x48, 0x0f, 0xc7, 0xf8;\n" - ".byte 0x73, 0xfa;\n" + "jnc 1b;\n" : "=a" (*reinterpret_cast(output)) : : "cc" ); #elif defined(GCC_RDSEED_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 40600) - __asm__ __volatile__ + __asm__ ( INTEL_NOPREFIX ASL(1) @@ -328,10 +341,11 @@ inline void RDSEED64(void* output) : : "cc" ); #elif defined(GCC_RDSEED_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 30200) - __asm__ __volatile__ + __asm__ ( + "1:\n" ".byte 0x48, 0x0f, 0xc7, 0xf8;\n" - ".byte 0x73, 0xfa;\n" + "jnc 1b;\n" : "=a" (*reinterpret_cast(output)) : : "cc" ); @@ -344,6 +358,12 @@ inline void RDSEED64(void* output) } #endif // CRYPTOPP_BOOL_X64 and RDSEED64 +RDSEED::RDSEED() +{ + if (!HasRDSEED()) + throw RDSEED_Err("HasRDSEED"); +} + void RDSEED::GenerateBlock(byte *output, size_t size) { CRYPTOPP_ASSERT((output && size) || !(output || size)); @@ -369,7 +389,7 @@ void RDSEED::GenerateBlock(byte *output, size_t size) { word64 val; RDSEED64(&val); - std::memcpy(output, &val, size); + ::memcpy(output, &val, size); } #elif CRYPTOPP_BOOL_X86 size_t i = 0; @@ -383,7 +403,7 @@ void RDSEED::GenerateBlock(byte *output, size_t size) { word32 val; RDSEED32(&val); - std::memcpy(output, &val, size); + ::memcpy(output, &val, size); } #endif // CRYPTOPP_BOOL_X64, CRYPTOPP_BOOL_X32 and RDSEED64 } diff --git a/rdrand.h b/rdrand.h index dba3ad70..03a186f4 100644 --- a/rdrand.h +++ b/rdrand.h @@ -56,9 +56,9 @@ public: //! \brief Construct a RDRAND generator //! \details According to DJ of Intel, the Intel RDRAND circuit does not underflow. //! If it did hypothetically underflow, then it would return 0 for the random value. - //! AMD's RDRAND implementation appears to provide the same behavior except the - //! values are not generated consistent with FIPS 140. - RDRAND() {} + //! AMD's RDRAND implementation appears to provide the same behavior. + //! \throws RDRAND_Err if the random number generator is not available + RDRAND(); //! \brief Generate random array of bytes //! \param output the byte buffer @@ -107,7 +107,8 @@ public: //! \details Empirical testing under a 6th generaton i7 (6200U) shows RDSEED fails //! to fulfill requests at about once every for every 256 bytes requested. //! The generator runs about 4 times slower than RDRAND. - RDSEED() {} + //! \throws RDSEED_Err if the random number generator is not available + RDSEED(); //! \brief Generate random array of bytes //! \param output the byte buffer diff --git a/validat0.cpp b/validat0.cpp index b5f589a1..4d3c5c90 100644 --- a/validat0.cpp +++ b/validat0.cpp @@ -2169,13 +2169,15 @@ bool TestIntegerBitops() pass=true; if (IsPrime(Integer("561"))) pass = false; - if (!IsPrime(Integer("41041"))) + if (IsPrime(Integer("41041"))) pass = false; - if (!IsPrime(Integer("321197185"))) + if (IsPrime(Integer("321197185"))) pass = false; - if (!IsPrime(Integer("232250619601"))) + if (IsPrime(Integer("5394826801"))) pass = false; - if (!IsPrime(Integer("974637772161"))) + if (IsPrime(Integer("232250619601"))) + pass = false; + if (IsPrime(Integer("974637772161"))) pass = false; if (pass) diff --git a/validat1.cpp b/validat1.cpp index 16c5d83b..af8299ed 100644 --- a/validat1.cpp +++ b/validat1.cpp @@ -376,7 +376,7 @@ bool TestOS_RNG() #ifdef BLOCKING_RNG_AVAILABLE try {rng.reset(new BlockingRng);} - catch (OS_RNG_Err &) {} + catch (const OS_RNG_Err &) {} #endif if (rng.get()) @@ -565,7 +565,7 @@ bool TestAutoSeeded() { prng.DiscardBytes(100000); } - catch(const Exception&) + catch (const Exception&) { discard = false; } @@ -591,7 +591,7 @@ bool TestAutoSeeded() incorporate = true; } } - catch(const Exception& /*ex*/) + catch (const Exception& /*ex*/) { } @@ -653,7 +653,7 @@ bool TestAutoSeededX917() { prng.DiscardBytes(100000); } - catch(const Exception&) + catch (const Exception&) { discard = false; } @@ -679,7 +679,7 @@ bool TestAutoSeededX917() incorporate = true; } } - catch(const Exception& /*ex*/) + catch (const Exception& /*ex*/) { } @@ -761,7 +761,7 @@ bool TestMersenne() { prng.DiscardBytes(100000); } - catch(const Exception&) + catch (const Exception&) { discard = false; } @@ -787,7 +787,7 @@ bool TestMersenne() incorporate = true; } } - catch(const Exception& /*ex*/) + catch (const Exception& /*ex*/) { } @@ -828,14 +828,20 @@ bool TestMersenne() #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) bool TestRDRAND() { - // Testing on 6th generation i7 shows RDRAND needs less than 8 retries for 10K bytes. - RDRAND rdrand; - bool entropy = true, compress = true, discard = true, crop = true; - static const unsigned int SIZE = 10000; + std::cout << "\nTesting RDRAND generator...\n\n"; - if (HasRDRAND()) + bool entropy = true, compress = true, discard = true, crop = true; + member_ptr rng; + +#ifdef BLOCKING_RNG_AVAILABLE + try {rng.reset(new RDRAND);} + catch (const RDRAND_Err &) {} +#endif + + if (rng.get()) { - std::cout << "\nTesting RDRAND generator...\n\n"; + RDRAND& rdrand = dynamic_cast(*rng.get()); + static const unsigned int SIZE = 10000; MeterFilter meter(new Redirector(TheBitBucket())); Deflator deflator(new Redirector(meter)); @@ -876,7 +882,7 @@ bool TestRDRAND() { rdrand.DiscardBytes(SIZE); } - catch(const Exception&) + catch (const Exception&) { discard = false; } @@ -900,7 +906,6 @@ bool TestRDRAND() rdrand.GenerateBlock(reinterpret_cast(&result), 3); rdrand.GenerateBlock(reinterpret_cast(&result), 2); rdrand.GenerateBlock(reinterpret_cast(&result), 1); - rdrand.GenerateBlock(reinterpret_cast(&result), 0); crop = true; } catch (const Exception&) @@ -924,15 +929,20 @@ bool TestRDRAND() #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) bool TestRDSEED() { - // Testing on 5th generation i5 shows RDSEED needs about 128 retries for 10K bytes - // on 64-bit/amd64 VM, and it needs more for an 32-bit/i686 VM. - RDSEED rdseed; - bool entropy = true, compress = true, discard = true, crop = true; - static const unsigned int SIZE = 10000; + std::cout << "\nTesting RDSEED generator...\n\n"; - if (HasRDSEED()) + bool entropy = true, compress = true, discard = true, crop = true; + member_ptr rng; + +#ifdef BLOCKING_RNG_AVAILABLE + try {rng.reset(new RDSEED);} + catch (const RDSEED_Err &) {} +#endif + + if (rng.get()) { - std::cout << "\nTesting RDSEED generator...\n\n"; + RDSEED& rdseed = dynamic_cast(*rng.get()); + static const unsigned int SIZE = 10000; MeterFilter meter(new Redirector(TheBitBucket())); Deflator deflator(new Redirector(meter)); @@ -958,7 +968,7 @@ bool TestRDSEED() // Coverity finding, also see http://stackoverflow.com/a/34509163/608639. StreamState ss(std::cout); std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(6); - std::cout << " Maurer Randomness Test returned value " << mv << std::endl; + std::cout << " Maurer Randomness Test returned value " << mv << "\n"; if (meter.GetTotalBytes() < SIZE) { @@ -973,7 +983,7 @@ bool TestRDSEED() { rdseed.DiscardBytes(SIZE); } - catch(const Exception&) + catch (const Exception&) { discard = false; } @@ -997,7 +1007,6 @@ bool TestRDSEED() rdseed.GenerateBlock(reinterpret_cast(&result), 3); rdseed.GenerateBlock(reinterpret_cast(&result), 2); rdseed.GenerateBlock(reinterpret_cast(&result), 1); - rdseed.GenerateBlock(reinterpret_cast(&result), 0); crop = true; } catch (const Exception&) @@ -1014,7 +1023,7 @@ bool TestRDSEED() else std::cout << "\nRDSEED generator not available, skipping test.\n"; - return entropy && compress && discard; + return entropy && compress && discard && crop; } #endif @@ -2724,56 +2733,56 @@ bool ValidateBaseCode() fail = !TestFilter(HexEncoder().Ref(), data, 255, (const byte *)hexEncoded, strlen(hexEncoded)); try {HexEncoder().IsolatedInitialize(g_nullNameValuePairs);} - catch(const Exception&) {fail=true;} + catch (const Exception&) {fail=true;} std::cout << (fail ? "FAILED:" : "passed:"); std::cout << " Hex Encoding\n"; pass = pass && !fail; fail = !TestFilter(HexDecoder().Ref(), (const byte *)hexEncoded, strlen(hexEncoded), data, 255); try {HexDecoder().IsolatedInitialize(g_nullNameValuePairs);} - catch(const Exception&) {fail=true;} + catch (const Exception&) {fail=true;} std::cout << (fail ? "FAILED:" : "passed:"); std::cout << " Hex Decoding\n"; pass = pass && !fail; fail = !TestFilter(Base32Encoder().Ref(), data, 255, (const byte *)base32Encoded, strlen(base32Encoded)); try {Base32Encoder().IsolatedInitialize(g_nullNameValuePairs);} - catch(const Exception&) {fail=true;} + catch (const Exception&) {fail=true;} std::cout << (fail ? "FAILED:" : "passed:"); std::cout << " Base32 Encoding\n"; pass = pass && !fail; fail = !TestFilter(Base32Decoder().Ref(), (const byte *)base32Encoded, strlen(base32Encoded), data, 255); try {Base32Decoder().IsolatedInitialize(g_nullNameValuePairs);} - catch(const Exception&) {fail=true;} + catch (const Exception&) {fail=true;} std::cout << (fail ? "FAILED:" : "passed:"); std::cout << " Base32 Decoding\n"; pass = pass && !fail; fail = !TestFilter(Base64Encoder(new HexEncoder).Ref(), data, 255, (const byte *)base64AndHexEncoded, strlen(base64AndHexEncoded)); try {Base64Encoder().IsolatedInitialize(g_nullNameValuePairs);} - catch(const Exception&) {fail=true;} + catch (const Exception&) {fail=true;} std::cout << (fail ? "FAILED:" : "passed:"); std::cout << " Base64 Encoding\n"; pass = pass && !fail; fail = !TestFilter(HexDecoder(new Base64Decoder).Ref(), (const byte *)base64AndHexEncoded, strlen(base64AndHexEncoded), data, 255); try {Base64Decoder().IsolatedInitialize(g_nullNameValuePairs);} - catch(const Exception&) {fail=true;} + catch (const Exception&) {fail=true;} std::cout << (fail ? "FAILED:" : "passed:"); std::cout << " Base64 Decoding\n"; pass = pass && !fail; fail = !TestFilter(Base64URLEncoder(new HexEncoder).Ref(), data, 255, (const byte *)base64URLAndHexEncoded, strlen(base64URLAndHexEncoded)); try {Base64URLEncoder().IsolatedInitialize(g_nullNameValuePairs);} - catch(const Exception&) {fail=true;} + catch (const Exception&) {fail=true;} std::cout << (fail ? "FAILED:" : "passed:"); std::cout << " Base64 URL Encoding\n"; pass = pass && !fail; fail = !TestFilter(HexDecoder(new Base64URLDecoder).Ref(), (const byte *)base64URLAndHexEncoded, strlen(base64URLAndHexEncoded), data, 255); try {Base64URLDecoder().IsolatedInitialize(g_nullNameValuePairs);} - catch(const Exception&) {fail=true;} + catch (const Exception&) {fail=true;} std::cout << (fail ? "FAILED:" : "passed:"); std::cout << " Base64 URL Decoding\n"; pass = pass && !fail;