Mkaake RDRAND and RDSEED throw if not available

Fix Carmichael pseudo-prime tests
pull/416/head
Jeffrey Walton 2017-05-09 13:20:53 -04:00
parent 8a177c58e6
commit 4f7fee38d6
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
4 changed files with 98 additions and 66 deletions

View File

@ -126,15 +126,16 @@ NAMESPACE_BEGIN(CryptoPP)
inline void RDRAND32(void* output) inline void RDRAND32(void* output)
{ {
#if defined(__SUNPRO_CC) #if defined(__SUNPRO_CC)
__asm__ __volatile__ __asm__
( (
"1:\n"
".byte 0x0f, 0xc7, 0xf0;\n" ".byte 0x0f, 0xc7, 0xf0;\n"
".byte 0x73, 0xfb;\n" "jnc 1b;\n"
: "=a" (*reinterpret_cast<word32*>(output)) : "=a" (*reinterpret_cast<word32*>(output))
: : "cc" : : "cc"
); );
#elif defined(GCC_RDRAND_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 40600) #elif defined(GCC_RDRAND_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 40600)
__asm__ __volatile__ __asm__
( (
INTEL_NOPREFIX INTEL_NOPREFIX
ASL(1) ASL(1)
@ -145,10 +146,11 @@ inline void RDRAND32(void* output)
: : "cc" : : "cc"
); );
#elif defined(GCC_RDRAND_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 30200) #elif defined(GCC_RDRAND_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 30200)
__asm__ __volatile__ __asm__
( (
"1:\n"
".byte 0x0f, 0xc7, 0xf0;\n" ".byte 0x0f, 0xc7, 0xf0;\n"
".byte 0x73, 0xfb;\n" "jnc 1b;\n"
: "=a" (*reinterpret_cast<word32*>(output)) : "=a" (*reinterpret_cast<word32*>(output))
: : "cc" : : "cc"
); );
@ -165,15 +167,16 @@ inline void RDRAND32(void* output)
inline void RDRAND64(void* output) inline void RDRAND64(void* output)
{ {
#if defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5100) #if defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5100)
__asm__ __volatile__ __asm__
( (
"1:\n"
".byte 0x48, 0x0f, 0xc7, 0xf0;\n" ".byte 0x48, 0x0f, 0xc7, 0xf0;\n"
".byte 0x73, 0xfa;\n" "jnc 1b;\n"
: "=a" (*reinterpret_cast<word64*>(output)) : "=a" (*reinterpret_cast<word64*>(output))
: : "cc" : : "cc"
); );
#elif defined(GCC_RDRAND_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 40600) #elif defined(GCC_RDRAND_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 40600)
__asm__ __volatile__ __asm__
( (
INTEL_NOPREFIX INTEL_NOPREFIX
ASL(1) ASL(1)
@ -184,10 +187,11 @@ inline void RDRAND64(void* output)
: : "cc" : : "cc"
); );
#elif defined(GCC_RDRAND_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 30200) #elif defined(GCC_RDRAND_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 30200)
__asm__ __volatile__ __asm__
( (
"1:\n"
".byte 0x48, 0x0f, 0xc7, 0xf0;\n" ".byte 0x48, 0x0f, 0xc7, 0xf0;\n"
".byte 0x73, 0xfa;\n" "jnc 1b;\n"
: "=a" (*reinterpret_cast<word64*>(output)) : "=a" (*reinterpret_cast<word64*>(output))
: : "cc" : : "cc"
); );
@ -200,6 +204,12 @@ inline void RDRAND64(void* output)
} }
#endif // CRYPTOPP_BOOL_X64, CRYPTOPP_BOOL_X32 and RDRAND64 #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) void RDRAND::GenerateBlock(byte *output, size_t size)
{ {
CRYPTOPP_ASSERT((output && size) || !(output || size)); CRYPTOPP_ASSERT((output && size) || !(output || size));
@ -225,7 +235,7 @@ void RDRAND::GenerateBlock(byte *output, size_t size)
{ {
word64 val; word64 val;
RDRAND64(&val); RDRAND64(&val);
std::memcpy(output, &val, size); ::memcpy(output, &val, size);
} }
#elif CRYPTOPP_BOOL_X86 #elif CRYPTOPP_BOOL_X86
size_t i = 0; size_t i = 0;
@ -239,7 +249,7 @@ void RDRAND::GenerateBlock(byte *output, size_t size)
{ {
word32 val; word32 val;
RDRAND32(&val); RDRAND32(&val);
std::memcpy(output, &val, size); ::memcpy(output, &val, size);
} }
#else #else
// RDRAND not detected at compile time, or no suitable compiler found // 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) inline void RDSEED32(void* output)
{ {
#if defined(__SUNPRO_CC) #if defined(__SUNPRO_CC)
__asm__ __volatile__ __asm__
( (
"1:\n"
".byte 0x0f, 0xc7, 0xf8;\n" ".byte 0x0f, 0xc7, 0xf8;\n"
".byte 0x73, 0xfb;\n" "jnc 1b;\n"
: "=a" (*reinterpret_cast<word32*>(output)) : "=a" (*reinterpret_cast<word32*>(output))
: : "cc" : : "cc"
); );
#elif defined(GCC_RDSEED_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 40600) #elif defined(GCC_RDSEED_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 40600)
__asm__ __volatile__ __asm__
( (
INTEL_NOPREFIX INTEL_NOPREFIX
ASL(1) ASL(1)
@ -289,10 +300,11 @@ inline void RDSEED32(void* output)
: : "cc" : : "cc"
); );
#elif defined(GCC_RDSEED_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 30200) #elif defined(GCC_RDSEED_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 30200)
__asm__ __volatile__ __asm__
( (
"1:\n"
".byte 0x0f, 0xc7, 0xf8;\n" ".byte 0x0f, 0xc7, 0xf8;\n"
".byte 0x73, 0xfb;\n" "jnc 1b;\n"
: "=a" (*reinterpret_cast<word32*>(output)) : "=a" (*reinterpret_cast<word32*>(output))
: : "cc" : : "cc"
); );
@ -309,15 +321,16 @@ inline void RDSEED32(void* output)
inline void RDSEED64(void* output) inline void RDSEED64(void* output)
{ {
#if defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5100) #if defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5100)
__asm__ __volatile__ __asm__
( (
"1:\n"
".byte 0x48, 0x0f, 0xc7, 0xf8;\n" ".byte 0x48, 0x0f, 0xc7, 0xf8;\n"
".byte 0x73, 0xfa;\n" "jnc 1b;\n"
: "=a" (*reinterpret_cast<word64*>(output)) : "=a" (*reinterpret_cast<word64*>(output))
: : "cc" : : "cc"
); );
#elif defined(GCC_RDSEED_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 40600) #elif defined(GCC_RDSEED_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 40600)
__asm__ __volatile__ __asm__
( (
INTEL_NOPREFIX INTEL_NOPREFIX
ASL(1) ASL(1)
@ -328,10 +341,11 @@ inline void RDSEED64(void* output)
: : "cc" : : "cc"
); );
#elif defined(GCC_RDSEED_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 30200) #elif defined(GCC_RDSEED_ASM_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 30200)
__asm__ __volatile__ __asm__
( (
"1:\n"
".byte 0x48, 0x0f, 0xc7, 0xf8;\n" ".byte 0x48, 0x0f, 0xc7, 0xf8;\n"
".byte 0x73, 0xfa;\n" "jnc 1b;\n"
: "=a" (*reinterpret_cast<word64*>(output)) : "=a" (*reinterpret_cast<word64*>(output))
: : "cc" : : "cc"
); );
@ -344,6 +358,12 @@ inline void RDSEED64(void* output)
} }
#endif // CRYPTOPP_BOOL_X64 and RDSEED64 #endif // CRYPTOPP_BOOL_X64 and RDSEED64
RDSEED::RDSEED()
{
if (!HasRDSEED())
throw RDSEED_Err("HasRDSEED");
}
void RDSEED::GenerateBlock(byte *output, size_t size) void RDSEED::GenerateBlock(byte *output, size_t size)
{ {
CRYPTOPP_ASSERT((output && size) || !(output || size)); CRYPTOPP_ASSERT((output && size) || !(output || size));
@ -369,7 +389,7 @@ void RDSEED::GenerateBlock(byte *output, size_t size)
{ {
word64 val; word64 val;
RDSEED64(&val); RDSEED64(&val);
std::memcpy(output, &val, size); ::memcpy(output, &val, size);
} }
#elif CRYPTOPP_BOOL_X86 #elif CRYPTOPP_BOOL_X86
size_t i = 0; size_t i = 0;
@ -383,7 +403,7 @@ void RDSEED::GenerateBlock(byte *output, size_t size)
{ {
word32 val; word32 val;
RDSEED32(&val); RDSEED32(&val);
std::memcpy(output, &val, size); ::memcpy(output, &val, size);
} }
#endif // CRYPTOPP_BOOL_X64, CRYPTOPP_BOOL_X32 and RDSEED64 #endif // CRYPTOPP_BOOL_X64, CRYPTOPP_BOOL_X32 and RDSEED64
} }

View File

@ -56,9 +56,9 @@ public:
//! \brief Construct a RDRAND generator //! \brief Construct a RDRAND generator
//! \details According to DJ of Intel, the Intel RDRAND circuit does not underflow. //! \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. //! 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 //! AMD's RDRAND implementation appears to provide the same behavior.
//! values are not generated consistent with FIPS 140. //! \throws RDRAND_Err if the random number generator is not available
RDRAND() {} RDRAND();
//! \brief Generate random array of bytes //! \brief Generate random array of bytes
//! \param output the byte buffer //! \param output the byte buffer
@ -107,7 +107,8 @@ public:
//! \details Empirical testing under a 6th generaton i7 (6200U) shows RDSEED fails //! \details Empirical testing under a 6th generaton i7 (6200U) shows RDSEED fails
//! to fulfill requests at about once every for every 256 bytes requested. //! to fulfill requests at about once every for every 256 bytes requested.
//! The generator runs about 4 times slower than RDRAND. //! 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 //! \brief Generate random array of bytes
//! \param output the byte buffer //! \param output the byte buffer

View File

@ -2169,13 +2169,15 @@ bool TestIntegerBitops()
pass=true; pass=true;
if (IsPrime(Integer("561"))) if (IsPrime(Integer("561")))
pass = false; pass = false;
if (!IsPrime(Integer("41041"))) if (IsPrime(Integer("41041")))
pass = false; pass = false;
if (!IsPrime(Integer("321197185"))) if (IsPrime(Integer("321197185")))
pass = false; pass = false;
if (!IsPrime(Integer("232250619601"))) if (IsPrime(Integer("5394826801")))
pass = false; pass = false;
if (!IsPrime(Integer("974637772161"))) if (IsPrime(Integer("232250619601")))
pass = false;
if (IsPrime(Integer("974637772161")))
pass = false; pass = false;
if (pass) if (pass)

View File

@ -376,7 +376,7 @@ bool TestOS_RNG()
#ifdef BLOCKING_RNG_AVAILABLE #ifdef BLOCKING_RNG_AVAILABLE
try {rng.reset(new BlockingRng);} try {rng.reset(new BlockingRng);}
catch (OS_RNG_Err &) {} catch (const OS_RNG_Err &) {}
#endif #endif
if (rng.get()) if (rng.get())
@ -827,16 +827,22 @@ bool TestMersenne()
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
bool TestRDRAND() 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;
if (HasRDRAND())
{ {
std::cout << "\nTesting RDRAND generator...\n\n"; std::cout << "\nTesting RDRAND generator...\n\n";
bool entropy = true, compress = true, discard = true, crop = true;
member_ptr<RandomNumberGenerator> rng;
#ifdef BLOCKING_RNG_AVAILABLE
try {rng.reset(new RDRAND);}
catch (const RDRAND_Err &) {}
#endif
if (rng.get())
{
RDRAND& rdrand = dynamic_cast<RDRAND&>(*rng.get());
static const unsigned int SIZE = 10000;
MeterFilter meter(new Redirector(TheBitBucket())); MeterFilter meter(new Redirector(TheBitBucket()));
Deflator deflator(new Redirector(meter)); Deflator deflator(new Redirector(meter));
MaurerRandomnessTest maurer; MaurerRandomnessTest maurer;
@ -900,7 +906,6 @@ bool TestRDRAND()
rdrand.GenerateBlock(reinterpret_cast<byte*>(&result), 3); rdrand.GenerateBlock(reinterpret_cast<byte*>(&result), 3);
rdrand.GenerateBlock(reinterpret_cast<byte*>(&result), 2); rdrand.GenerateBlock(reinterpret_cast<byte*>(&result), 2);
rdrand.GenerateBlock(reinterpret_cast<byte*>(&result), 1); rdrand.GenerateBlock(reinterpret_cast<byte*>(&result), 1);
rdrand.GenerateBlock(reinterpret_cast<byte*>(&result), 0);
crop = true; crop = true;
} }
catch (const Exception&) catch (const Exception&)
@ -923,17 +928,22 @@ bool TestRDRAND()
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
bool TestRDSEED() 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;
if (HasRDSEED())
{ {
std::cout << "\nTesting RDSEED generator...\n\n"; std::cout << "\nTesting RDSEED generator...\n\n";
bool entropy = true, compress = true, discard = true, crop = true;
member_ptr<RandomNumberGenerator> rng;
#ifdef BLOCKING_RNG_AVAILABLE
try {rng.reset(new RDSEED);}
catch (const RDSEED_Err &) {}
#endif
if (rng.get())
{
RDSEED& rdseed = dynamic_cast<RDSEED&>(*rng.get());
static const unsigned int SIZE = 10000;
MeterFilter meter(new Redirector(TheBitBucket())); MeterFilter meter(new Redirector(TheBitBucket()));
Deflator deflator(new Redirector(meter)); Deflator deflator(new Redirector(meter));
MaurerRandomnessTest maurer; MaurerRandomnessTest maurer;
@ -958,7 +968,7 @@ bool TestRDSEED()
// Coverity finding, also see http://stackoverflow.com/a/34509163/608639. // Coverity finding, also see http://stackoverflow.com/a/34509163/608639.
StreamState ss(std::cout); StreamState ss(std::cout);
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(6); 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) if (meter.GetTotalBytes() < SIZE)
{ {
@ -997,7 +1007,6 @@ bool TestRDSEED()
rdseed.GenerateBlock(reinterpret_cast<byte*>(&result), 3); rdseed.GenerateBlock(reinterpret_cast<byte*>(&result), 3);
rdseed.GenerateBlock(reinterpret_cast<byte*>(&result), 2); rdseed.GenerateBlock(reinterpret_cast<byte*>(&result), 2);
rdseed.GenerateBlock(reinterpret_cast<byte*>(&result), 1); rdseed.GenerateBlock(reinterpret_cast<byte*>(&result), 1);
rdseed.GenerateBlock(reinterpret_cast<byte*>(&result), 0);
crop = true; crop = true;
} }
catch (const Exception&) catch (const Exception&)
@ -1014,7 +1023,7 @@ bool TestRDSEED()
else else
std::cout << "\nRDSEED generator not available, skipping test.\n"; std::cout << "\nRDSEED generator not available, skipping test.\n";
return entropy && compress && discard; return entropy && compress && discard && crop;
} }
#endif #endif