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)
{
#if defined(__SUNPRO_CC)
__asm__ __volatile__
__asm__
(
"1:\n"
".byte 0x0f, 0xc7, 0xf0;\n"
".byte 0x73, 0xfb;\n"
"jnc 1b;\n"
: "=a" (*reinterpret_cast<word32*>(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<word32*>(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<word64*>(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<word64*>(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<word32*>(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<word32*>(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<word64*>(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<word64*>(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
}

View File

@ -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

View File

@ -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)

View File

@ -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,15 +828,21 @@ 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;
if (HasRDRAND())
{
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()));
Deflator deflator(new Redirector(meter));
MaurerRandomnessTest maurer;
@ -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<byte*>(&result), 3);
rdrand.GenerateBlock(reinterpret_cast<byte*>(&result), 2);
rdrand.GenerateBlock(reinterpret_cast<byte*>(&result), 1);
rdrand.GenerateBlock(reinterpret_cast<byte*>(&result), 0);
crop = true;
}
catch (const Exception&)
@ -924,16 +929,21 @@ 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;
if (HasRDSEED())
{
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()));
Deflator deflator(new Redirector(meter));
MaurerRandomnessTest maurer;
@ -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<byte*>(&result), 3);
rdseed.GenerateBlock(reinterpret_cast<byte*>(&result), 2);
rdseed.GenerateBlock(reinterpret_cast<byte*>(&result), 1);
rdseed.GenerateBlock(reinterpret_cast<byte*>(&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;