From ce38a411fc5324a2868da9fae890365d19a5757e Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Wed, 8 Mar 2017 16:59:24 -0500 Subject: [PATCH] Add Random Number Generator benchmarks (Issue 386) Move HTML header and footer into benchmark functions Switch to and standard math routines Switch to and standard clock and time routines Move static variable^Cinto anonymous namespace Add TimeToString function for printing start and end times --- bench.h | 40 +++-- bench1.cpp | 507 +++++++++++++++++++++++++++++++++++----------------- bench2.cpp | 204 ++++++++++----------- drbg.h | 64 ++++--- mersenne.h | 2 +- osrng.h | 2 +- regtest.cpp | 30 +++- rng.cpp | 12 +- test.cpp | 115 ++++++------ 9 files changed, 583 insertions(+), 393 deletions(-) diff --git a/bench.h b/bench.h index f393cfde..4924d778 100644 --- a/bench.h +++ b/bench.h @@ -6,26 +6,36 @@ #include "cryptlib.h" +#include +#include +#include +#include + NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(Test) -ANONYMOUS_NAMESPACE_BEGIN -#ifdef CLOCKS_PER_SEC -const double CLOCK_TICKS_PER_SECOND = (double)CLOCKS_PER_SEC; -#elif defined(CLK_TCK) -const double CLOCK_TICKS_PER_SECOND = (double)CLK_TCK; -#else -const double CLOCK_TICKS_PER_SECOND = 1000000.0; -#endif +extern const double CLOCK_TICKS_PER_SECOND; +extern double g_allocatedTime; +extern double g_hertz; +extern double g_logTotal; +extern unsigned int g_logCount; +extern const byte defaultKey[]; -static const byte defaultKey[] = "0123456789" // 168 + NULL - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - "00000000000000000000000000000000000000000000000000000" - "00000000000000000000000000000000000000000000000000000"; -NAMESPACE_END +// Test book keeping +extern time_t g_testBegin; +extern time_t g_testEnd; -void BenchmarkAll(double t, double hertz); -void BenchmarkAll2(double t, double hertz); +// Top level, prints preamble and postamble +void Benchmark(int suites, double t, double hertz); +// Unkeyed systems +void Benchmark1(double t, double hertz); +// Shared key systems +void Benchmark2(double t, double hertz); +// Public key systems +void Benchmark3(double t, double hertz); + +void OutputResultBytes(const char *name, double length, double timeTaken); +void OutputResultOperations(const char *name, const char *operation, bool pc, unsigned long iterations, double timeTaken); NAMESPACE_END // Test NAMESPACE_END // CryptoPP diff --git a/bench1.cpp b/bench1.cpp index 431ed130..b6ad4c12 100644 --- a/bench1.cpp +++ b/bench1.cpp @@ -14,18 +14,27 @@ #include "factory.h" #include "smartptr.h" #include "cpu.h" - -#include -#include -#include -#include -#include +#include "drbg.h" NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(Test) -double logTotal = 0.0, g_allocatedTime = 0, g_hertz = 0; -unsigned int logCount = 0; +#ifdef CLOCKS_PER_SEC +const double CLOCK_TICKS_PER_SECOND = (double)CLOCKS_PER_SEC; +#elif defined(CLK_TCK) +const double CLOCK_TICKS_PER_SECOND = (double)CLK_TCK; +#else +const double CLOCK_TICKS_PER_SECOND = 1000000.0; +#endif + +const byte defaultKey[] = "0123456789" // 168 + NULL + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + "00000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000"; + +double g_allocatedTime = 0.0, g_hertz = 0.0, g_logTotal = 0.0; +unsigned int g_logCount = 0; +time_t g_testBegin, g_testEnd; void OutputResultBytes(const char *name, double length, double timeTaken) { @@ -33,19 +42,17 @@ void OutputResultBytes(const char *name, double length, double timeTaken) StreamState ss(std::cout); // Coverity finding - if (length < 0.0000000001f) length = 0.000001f; - if (timeTaken < 0.0000000001f) timeTaken = 0.000001f; + if (length < 0.000001f) length = 0.000001f; + if (timeTaken < 0.000001f) timeTaken = 0.000001f; double mbs = length / timeTaken / (1024*1024); std::cout << "\n" << name; -// std::cout << "" << std::setprecision(3) << length / (1024*1024); std::cout << std::setiosflags(std::ios::fixed); -// std::cout << "" << std::setprecision(3) << timeTaken; std::cout << "" << std::setprecision(0) << std::setiosflags(std::ios::fixed) << mbs; - if (g_hertz) + if (g_hertz > 1.0f) std::cout << "" << std::setprecision(1) << std::setiosflags(std::ios::fixed) << timeTaken * g_hertz / length; - logTotal += log(mbs); - logCount++; + g_logTotal += std::log(mbs); + g_logCount++; } void OutputResultKeying(double iterations, double timeTaken) @@ -54,11 +61,13 @@ void OutputResultKeying(double iterations, double timeTaken) StreamState ss(std::cout); // Coverity finding - if (iterations < 0.0000000001f) iterations = 0.000001f; - if (timeTaken < 0.0000000001f) timeTaken = 0.000001f; + if (iterations < 0.000001f) iterations = 0.000001f; + if (timeTaken < 0.000001f) timeTaken = 0.000001f; std::cout << "" << std::setprecision(3) << std::setiosflags(std::ios::fixed) << (1000*1000*timeTaken/iterations); - if (g_hertz) + + // Coverity finding + if (g_hertz > 1.0f) std::cout << "" << std::setprecision(0) << std::setiosflags(std::ios::fixed) << timeTaken * g_hertz / iterations; } @@ -69,15 +78,17 @@ void OutputResultOperations(const char *name, const char *operation, bool pc, un // Coverity finding if (!iterations) iterations++; - if (timeTaken < 0.0000000001f) timeTaken = 0.000001f; + if (timeTaken < 0.000001f) timeTaken = 0.000001f; std::cout << "\n" << name << " " << operation << (pc ? " with precomputation" : ""); std::cout << "" << std::setprecision(2) << std::setiosflags(std::ios::fixed) << (1000*timeTaken/iterations); - if (g_hertz) + + // Coverity finding + if (g_hertz > 1.0f) std::cout << "" << std::setprecision(2) << std::setiosflags(std::ios::fixed) << timeTaken * g_hertz / iterations / 1000000; - logTotal += log(iterations/timeTaken); - logCount++; + g_logTotal += std::log(iterations/timeTaken); + g_logCount++; } /* @@ -85,17 +96,19 @@ void BenchMark(const char *name, BlockTransformation &cipher, double timeTotal) { const int BUF_SIZE = RoundUpToMultipleOf(2048U, cipher.OptimalNumberOfParallelBlocks() * cipher.BlockSize()); AlignedSecByteBlock buf(BUF_SIZE); - const int nBlocks = BUF_SIZE / cipher.BlockSize(); - clock_t start = clock(); + buf.SetMark(16); + const int nBlocks = BUF_SIZE / cipher.BlockSize(); unsigned long i=0, blocks=1; double timeTaken; + + clock_t start = ::clock(); do { blocks *= 2; for (; i"; + std::cout << "\n"; + + std::cout << "\n"; + std::cout << "\n"; + std::cout << "\nSpeed Comparison of Popular Crypto Algorithms"; + std::cout << "\n"; + std::cout << "\n"; + + std::cout << "\n"; + + std::cout << "\n

Crypto++ " << CRYPTOPP_VERSION / 100; + std::cout << '.' << (CRYPTOPP_VERSION % 100) / 10 << '.' << CRYPTOPP_VERSION % 10 << " Benchmarks

"; + + std::cout << "\n

Here are speed benchmarks for some commonly used cryptographic algorithms.

"; + + if (g_hertz > 1.0f) + std::cout << "\n

CPU frequency of the test platform is " << g_hertz << " Hz.

"; + else + std::cout << "\n

CPU frequency of the test platform was not provided.

" << std::endl; +} + +void AddHtmlFooter() +{ + std::cout << "\n"; + std::cout << "\n" << std::endl; +} + +void Benchmark(int suites, double t, double hertz) +{ + g_allocatedTime = t; + g_hertz = hertz; + + g_testBegin = std::time(NULLPTR); + + AddHtmlHeader(); + + if (suites > 7) + suites = 7; + + // Unkeyed algorithms + if (suites & 1) + Benchmark1(t, hertz); + + if (suites > 1) + std::cout << "\n
"; + + // Shared key algorithms + if (suites & 2) + Benchmark2(t, hertz); + + if (suites > 2) + std::cout << "\n
"; + + // Public key algorithms + if (suites & 4) + Benchmark3(t, hertz); + + g_testEnd = std::time(NULLPTR); + + { + StreamState state(std::cout); + std::cout << "\n

Throughput Geometric Average: " << std::setiosflags(std::ios::fixed); + std::cout << std::exp(g_logTotal/(g_logCount > 0.0f ? g_logCount : 1.0f)) << std::endl; + } + + std::cout << "\n

Test started at " << TimeToString(g_testBegin); + std::cout << "\n
Test ended at " << TimeToString(g_testEnd); + std::cout << std::endl; + + AddHtmlFooter(); +} + +void Benchmark1(double t, double hertz) +{ + g_allocatedTime = t; + g_hertz = hertz; + + const char *cpb; + if (g_hertz > 1.0f) + cpb = "Cycles Per Byte"; + else + cpb = ""; + + std::cout << "\n"; + std::cout << "\n"; + std::cout << ""; + std::cout << "\n"; + { +#ifdef NONBLOCKING_RNG_AVAILABLE + BenchMarkByNameKeyLess("NonblockingRng"); +#endif +#ifdef OS_RNG_AVAILABLE + BenchMarkByNameKeyLess("AutoSeededRandomPool"); + BenchMarkByNameKeyLess("AutoSeededX917RNG(AES)"); +#endif + BenchMarkByNameKeyLess("MT19937"); +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) + if (HasRDRAND()) + BenchMarkByNameKeyLess("RDRAND"); + if (HasRDSEED()) + BenchMarkByNameKeyLess("RDSEED"); +#endif + BenchMarkByNameKeyLess("Hash_DRBG(SHA1)"); + BenchMarkByNameKeyLess("HMAC_DRBG(SHA1)"); + } + + std::cout << "\n"; + { + BenchMarkByNameKeyLess("CRC32"); + BenchMarkByNameKeyLess("CRC32C"); + BenchMarkByNameKeyLess("Adler32"); + BenchMarkByNameKeyLess("MD5"); + BenchMarkByNameKeyLess("SHA-1"); + BenchMarkByNameKeyLess("SHA-256"); + BenchMarkByNameKeyLess("SHA-512"); + BenchMarkByNameKeyLess("Keccak-224"); + BenchMarkByNameKeyLess("Keccak-256"); + BenchMarkByNameKeyLess("Keccak-384"); + BenchMarkByNameKeyLess("Keccak-512"); + BenchMarkByNameKeyLess("SHA3-224"); + BenchMarkByNameKeyLess("SHA3-256"); + BenchMarkByNameKeyLess("SHA3-384"); + BenchMarkByNameKeyLess("SHA3-512"); + BenchMarkByNameKeyLess("Tiger"); + BenchMarkByNameKeyLess("Whirlpool"); + BenchMarkByNameKeyLess("RIPEMD-160"); + BenchMarkByNameKeyLess("RIPEMD-320"); + BenchMarkByNameKeyLess("RIPEMD-128"); + BenchMarkByNameKeyLess("RIPEMD-256"); + BenchMarkByNameKeyLess("BLAKE2s"); + BenchMarkByNameKeyLess("BLAKE2b"); + } + + std::cout << "\n
AlgorithmMiB/Second" << cpb; + + std::cout << "\n
" << std::endl; +} + +void Benchmark2(double t, double hertz) { -#if 1 - logTotal = 0; - logCount = 0; g_allocatedTime = t; g_hertz = hertz; const char *cpb, *cpk; - if (g_hertz) + if (g_hertz > 1.0f) { cpb = "Cycles Per Byte"; - cpk = "Cycles to
Setup Key and IV"; - std::cout << "CPU frequency of the test platform is " << g_hertz << " Hz.\n"; + cpk = "Cycles to
Setup Key and IV"; } else { cpb = cpk = ""; - std::cout << "CPU frequency of the test platform was not provided.\n"; } - std::cout << "" << std::endl; - std::cout << "
AlgorithmMiB/Second" << cpb << "Microseconds to
Setup Key and IV" << cpk << std::endl; + std::cout << "\n"; + std::cout << "\n"; + std::cout << "\n"; + std::cout << "\n"; + { #if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE - if (HasCLMUL()) - BenchMarkByName2("AES/GCM", 0, "AES/GCM"); - else + if (HasCLMUL()) + BenchMarkByName2("AES/GCM", 0, "GMAC(AES)"); + else #elif CRYPTOPP_BOOL_ARM_PMULL_AVAILABLE - if (HasPMULL()) - BenchMarkByName2("AES/GCM", 0, "AES/GCM"); - else + if (HasPMULL()) + BenchMarkByName2("AES/GCM", 0, "GMAC(AES)"); + else #endif - { - BenchMarkByName2("AES/GCM", 0, "AES/GCM (2K tables)", MakeParameters(Name::TableSize(), 2048)); - BenchMarkByName2("AES/GCM", 0, "AES/GCM (64K tables)", MakeParameters(Name::TableSize(), 64*1024)); - } - BenchMarkByName2("AES/CCM"); - BenchMarkByName2("AES/EAX"); + { + BenchMarkByName2("AES/GCM", 0, "GMAC(AES) (2K tables)", MakeParameters(Name::TableSize(), 2048)); + BenchMarkByName2("AES/GCM", 0, "GMAC(AES) (64K tables)", MakeParameters(Name::TableSize(), 64 * 1024)); + } - std::cout << "\n"; + BenchMarkByName("VMAC(AES)-64"); + BenchMarkByName("VMAC(AES)-128"); + BenchMarkByName("HMAC(SHA-1)"); + BenchMarkByName("Two-Track-MAC"); + BenchMarkByName("CMAC(AES)"); + BenchMarkByName("DMAC(AES)"); + BenchMarkByName("Poly1305(AES)"); + BenchMarkByName("BLAKE2s"); + BenchMarkByName("BLAKE2b"); + BenchMarkByName("SipHash-2-4"); + BenchMarkByName("SipHash-4-8"); + } + + std::cout << "\n"; + { + BenchMarkByName("Panama-LE"); + BenchMarkByName("Panama-BE"); + BenchMarkByName("Salsa20"); + BenchMarkByName("Salsa20", 0, "Salsa20/12", MakeParameters(Name::Rounds(), 12)); + BenchMarkByName("Salsa20", 0, "Salsa20/8", MakeParameters(Name::Rounds(), 8)); + BenchMarkByName("ChaCha20"); + BenchMarkByName("ChaCha12"); + BenchMarkByName("ChaCha8"); + BenchMarkByName("Sosemanuk"); + BenchMarkByName("MARC4"); + BenchMarkByName("SEAL-3.0-LE"); + BenchMarkByName("WAKE-OFB-LE"); + } + + std::cout << "\n"; + { + BenchMarkByName("AES/CTR", 16); + BenchMarkByName("AES/CTR", 24); + BenchMarkByName("AES/CTR", 32); + BenchMarkByName("AES/CBC", 16); + BenchMarkByName("AES/CBC", 24); + BenchMarkByName("AES/CBC", 32); + BenchMarkByName("AES/OFB", 16); + BenchMarkByName("AES/CFB", 16); + BenchMarkByName("AES/ECB", 16); + BenchMarkByName("Camellia/CTR", 16); + BenchMarkByName("Camellia/CTR", 32); + BenchMarkByName("Twofish/CTR"); + BenchMarkByName("Serpent/CTR"); + BenchMarkByName("CAST-256/CTR"); + BenchMarkByName("RC6/CTR"); + BenchMarkByName("MARS/CTR"); + BenchMarkByName("SHACAL-2/CTR", 16); + BenchMarkByName("SHACAL-2/CTR", 64); + BenchMarkByName("DES/CTR"); + BenchMarkByName("DES-XEX3/CTR"); + BenchMarkByName("DES-EDE3/CTR"); + BenchMarkByName("IDEA/CTR"); + BenchMarkByName("RC5/CTR", 0, "RC5 (r=16)"); + BenchMarkByName("Blowfish/CTR"); + BenchMarkByName("TEA/CTR"); + BenchMarkByName("XTEA/CTR"); + BenchMarkByName("CAST-128/CTR"); + BenchMarkByName("SKIPJACK/CTR"); + BenchMarkByName("SEED/CTR", 0, "SEED/CTR (1/2 K table)"); + } + + std::cout << "\n"; + { #if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE - if (HasCLMUL()) - BenchMarkByName2("AES/GCM", 0, "GMAC(AES)"); - else + if (HasCLMUL()) + BenchMarkByName2("AES/GCM", 0, "AES/GCM"); + else +#elif CRYPTOPP_BOOL_ARM_PMULL_AVAILABLE + if (HasPMULL()) + BenchMarkByName2("AES/GCM", 0, "AES/GCM"); + else #endif - { - BenchMarkByName2("AES/GCM", 0, "GMAC(AES) (2K tables)", MakeParameters(Name::TableSize(), 2048)); - BenchMarkByName2("AES/GCM", 0, "GMAC(AES) (64K tables)", MakeParameters(Name::TableSize(), 64*1024)); + { + BenchMarkByName2("AES/GCM", 0, "AES/GCM (2K tables)", MakeParameters(Name::TableSize(), 2048)); + BenchMarkByName2("AES/GCM", 0, "AES/GCM (64K tables)", MakeParameters(Name::TableSize(), 64 * 1024)); + } + BenchMarkByName2("AES/CCM"); + BenchMarkByName2("AES/EAX"); } - BenchMarkByName("VMAC(AES)-64"); - BenchMarkByName("VMAC(AES)-128"); - BenchMarkByName("HMAC(SHA-1)"); - BenchMarkByName("Two-Track-MAC"); - BenchMarkByName("CMAC(AES)"); - BenchMarkByName("DMAC(AES)"); - BenchMarkByName("Poly1305(AES)"); - BenchMarkByName("BLAKE2s"); - BenchMarkByName("BLAKE2b"); - BenchMarkByName("SipHash-2-4"); - BenchMarkByName("SipHash-4-8"); - std::cout << "\n"; - BenchMarkByNameKeyLess("CRC32"); - BenchMarkByNameKeyLess("CRC32C"); - BenchMarkByNameKeyLess("Adler32"); - BenchMarkByNameKeyLess("MD5"); - BenchMarkByNameKeyLess("SHA-1"); - BenchMarkByNameKeyLess("SHA-256"); - BenchMarkByNameKeyLess("SHA-512"); - BenchMarkByNameKeyLess("Keccak-224"); - BenchMarkByNameKeyLess("Keccak-256"); - BenchMarkByNameKeyLess("Keccak-384"); - BenchMarkByNameKeyLess("Keccak-512"); - BenchMarkByNameKeyLess("SHA3-224"); - BenchMarkByNameKeyLess("SHA3-256"); - BenchMarkByNameKeyLess("SHA3-384"); - BenchMarkByNameKeyLess("SHA3-512"); - BenchMarkByNameKeyLess("Tiger"); - BenchMarkByNameKeyLess("Whirlpool"); - BenchMarkByNameKeyLess("RIPEMD-160"); - BenchMarkByNameKeyLess("RIPEMD-320"); - BenchMarkByNameKeyLess("RIPEMD-128"); - BenchMarkByNameKeyLess("RIPEMD-256"); - BenchMarkByNameKeyLess("BLAKE2s"); - BenchMarkByNameKeyLess("BLAKE2b"); - - std::cout << "\n"; - BenchMarkByName("Panama-LE"); - BenchMarkByName("Panama-BE"); - BenchMarkByName("Salsa20"); - BenchMarkByName("Salsa20", 0, "Salsa20/12", MakeParameters(Name::Rounds(), 12)); - BenchMarkByName("Salsa20", 0, "Salsa20/8", MakeParameters(Name::Rounds(), 8)); - BenchMarkByName("ChaCha20"); - BenchMarkByName("ChaCha12"); - BenchMarkByName("ChaCha8"); - BenchMarkByName("Sosemanuk"); - BenchMarkByName("MARC4"); - BenchMarkByName("SEAL-3.0-LE"); - BenchMarkByName("WAKE-OFB-LE"); - - std::cout << "\n"; - BenchMarkByName("AES/CTR", 16); - BenchMarkByName("AES/CTR", 24); - BenchMarkByName("AES/CTR", 32); - BenchMarkByName("AES/CBC", 16); - BenchMarkByName("AES/CBC", 24); - BenchMarkByName("AES/CBC", 32); - BenchMarkByName("AES/OFB", 16); - BenchMarkByName("AES/CFB", 16); - BenchMarkByName("AES/ECB", 16); - BenchMarkByName("Camellia/CTR", 16); - BenchMarkByName("Camellia/CTR", 32); - BenchMarkByName("Twofish/CTR"); - BenchMarkByName("Serpent/CTR"); - BenchMarkByName("CAST-256/CTR"); - BenchMarkByName("RC6/CTR"); - BenchMarkByName("MARS/CTR"); - BenchMarkByName("SHACAL-2/CTR", 16); - BenchMarkByName("SHACAL-2/CTR", 64); - BenchMarkByName("DES/CTR"); - BenchMarkByName("DES-XEX3/CTR"); - BenchMarkByName("DES-EDE3/CTR"); - BenchMarkByName("IDEA/CTR"); - BenchMarkByName("RC5/CTR", 0, "RC5 (r=16)"); - BenchMarkByName("Blowfish/CTR"); - BenchMarkByName("TEA/CTR"); - BenchMarkByName("XTEA/CTR"); - BenchMarkByName("CAST-128/CTR"); - BenchMarkByName("SKIPJACK/CTR"); - BenchMarkByName("SEED/CTR", 0, "SEED/CTR (1/2 K table)"); - std::cout << "
AlgorithmMiB/Second" << cpb; + std::cout << "Microseconds to
Setup Key and IV" << cpk; - std::cout << "\n
" << std::endl; - - BenchmarkAll2(t, hertz); - std::cout << "Throughput Geometric Average: " << std::setiosflags(std::ios::fixed) << exp(logTotal/(logCount ? logCount : 1)) << std::endl; - -// Safer functions on Windows for C&A, https://github.com/weidai11/cryptopp/issues/55 -#if (CRYPTOPP_MSC_VERSION >= 1400) - tm localTime = {}; - char timeBuf[64]; - errno_t err; - - const time_t endTime = time(NULLPTR); - err = localtime_s(&localTime, &endTime); - CRYPTOPP_ASSERT(err == 0); - err = asctime_s(timeBuf, sizeof(timeBuf), &localTime); - CRYPTOPP_ASSERT(err == 0); - - std::cout << "\nTest ended at " << timeBuf; -#else - const time_t endTime = time(NULLPTR); - std::cout << "\nTest ended at " << asctime(localtime(&endTime)); -#endif -#endif + std::cout << "\n
" << std::endl; } NAMESPACE_END // Test diff --git a/bench2.cpp b/bench2.cpp index f85d05e7..443f71b2 100644 --- a/bench2.cpp +++ b/bench2.cpp @@ -30,26 +30,20 @@ #include "oids.h" #include "randpool.h" -#include -#include -#include -#include - NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(Test) -void OutputResultOperations(const char *name, const char *operation, bool pc, unsigned long iterations, double timeTaken); - void BenchMarkEncryption(const char *name, PK_Encryptor &key, double timeTotal, bool pc=false) { unsigned int len = 16; SecByteBlock plaintext(len), ciphertext(key.CiphertextLength(len)); Test::GlobalRNG().GenerateBlock(plaintext, len); - const clock_t start = clock(); unsigned int i; double timeTaken; - for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i++) + + const clock_t start = ::clock(); + for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND, i++) key.Encrypt(Test::GlobalRNG(), plaintext, len, ciphertext); OutputResultOperations(name, "Encryption", pc, i, timeTaken); @@ -69,10 +63,11 @@ void BenchMarkDecryption(const char *name, PK_Decryptor &priv, PK_Encryptor &pub Test::GlobalRNG().GenerateBlock(plaintext, len); pub.Encrypt(Test::GlobalRNG(), plaintext, len, ciphertext); - const clock_t start = clock(); unsigned int i; double timeTaken; - for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i++) + + const clock_t start = ::clock(); + for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND, i++) priv.Decrypt(Test::GlobalRNG(), ciphertext, ciphertext.size(), plaintext); OutputResultOperations(name, "Decryption", false, i, timeTaken); @@ -84,11 +79,12 @@ void BenchMarkSigning(const char *name, PK_Signer &key, double timeTotal, bool p AlignedSecByteBlock message(len), signature(key.SignatureLength()); Test::GlobalRNG().GenerateBlock(message, len); - const clock_t start = clock(); unsigned int i; double timeTaken; - for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i++) - key.SignMessage(Test::GlobalRNG(), message, len, signature); + + const clock_t start = ::clock(); + for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND, i++) + (void)key.SignMessage(Test::GlobalRNG(), message, len, signature); OutputResultOperations(name, "Signature", pc, i, timeTaken); @@ -106,15 +102,12 @@ void BenchMarkVerification(const char *name, const PK_Signer &priv, PK_Verifier Test::GlobalRNG().GenerateBlock(message, len); priv.SignMessage(Test::GlobalRNG(), message, len, signature); - const clock_t start = clock(); unsigned int i; double timeTaken; - for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i++) - { - // The return value is ignored because we are interested in throughput - bool unused = pub.VerifyMessage(message, len, signature, signature.size()); - CRYPTOPP_UNUSED(unused); - } + + const clock_t start = ::clock(); + for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND, i++) + (void)pub.VerifyMessage(message, len, signature, signature.size()); OutputResultOperations(name, "Verification", pc, i, timeTaken); @@ -129,10 +122,11 @@ void BenchMarkKeyGen(const char *name, SimpleKeyAgreementDomain &d, double timeT { SecByteBlock priv(d.PrivateKeyLength()), pub(d.PublicKeyLength()); - const clock_t start = clock(); unsigned int i; double timeTaken; - for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i++) + + const clock_t start = ::clock(); + for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND, i++) d.GenerateKeyPair(Test::GlobalRNG(), priv, pub); OutputResultOperations(name, "Key-Pair Generation", pc, i, timeTaken); @@ -148,10 +142,11 @@ void BenchMarkKeyGen(const char *name, AuthenticatedKeyAgreementDomain &d, doubl { SecByteBlock priv(d.EphemeralPrivateKeyLength()), pub(d.EphemeralPublicKeyLength()); - const clock_t start = clock(); unsigned int i; double timeTaken; - for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i++) + + const clock_t start = ::clock(); + for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND, i++) d.GenerateEphemeralKeyPair(Test::GlobalRNG(), priv, pub); OutputResultOperations(name, "Key-Pair Generation", pc, i, timeTaken); @@ -171,10 +166,11 @@ void BenchMarkAgreement(const char *name, SimpleKeyAgreementDomain &d, double ti d.GenerateKeyPair(Test::GlobalRNG(), priv2, pub2); SecByteBlock val(d.AgreedValueLength()); - const clock_t start = clock(); unsigned int i; double timeTaken; - for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i+=2) + + const clock_t start = ::clock(); + for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND, i+=2) { d.Agree(val, priv1, pub2); d.Agree(val, priv2, pub1); @@ -195,10 +191,11 @@ void BenchMarkAgreement(const char *name, AuthenticatedKeyAgreementDomain &d, do d.GenerateEphemeralKeyPair(Test::GlobalRNG(), epriv2, epub2); SecByteBlock val(d.AgreedValueLength()); - const clock_t start = clock(); unsigned int i; double timeTaken; - for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i+=2) + + const clock_t start = ::clock(); + for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND, i+=2) { d.Agree(val, spriv1, epriv1, spub2, epub2); d.Agree(val, spriv2, epriv2, spub1, epub1); @@ -207,36 +204,10 @@ void BenchMarkAgreement(const char *name, AuthenticatedKeyAgreementDomain &d, do OutputResultOperations(name, "Key Agreement", pc, i, timeTaken); } -#if 0 -void BenchMarkAgreement(const char *name, AuthenticatedKeyAgreementDomainWithRoles &d, double timeTotal, bool pc=false) -{ - SecByteBlock spriv1(d.StaticPrivateKeyLength()), spriv2(d.StaticPrivateKeyLength()); - SecByteBlock epriv1(d.EphemeralPrivateKeyLength()), epriv2(d.EphemeralPrivateKeyLength()); - SecByteBlock spub1(d.StaticPublicKeyLength()), spub2(d.StaticPublicKeyLength()); - SecByteBlock epub1(d.EphemeralPublicKeyLength()), epub2(d.EphemeralPublicKeyLength()); - d.GenerateStaticKeyPair(Test::GlobalRNG(), spriv1, spub1); - d.GenerateStaticKeyPair(Test::GlobalRNG(), spriv2, spub2); - d.GenerateEphemeralKeyPair(Test::GlobalRNG(), epriv1, epub1); - d.GenerateEphemeralKeyPair(Test::GlobalRNG(), epriv2, epub2); - SecByteBlock val(d.AgreedValueLength()); - - const clock_t start = clock(); - unsigned int i; - double timeTaken; - for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i+=2) - { - d.Agree(val, spriv1, epriv1, spub2, epub2); - d.Agree(val, spriv2, epriv2, spub1, epub1); - } - - OutputResultOperations(name, "Key Agreement", pc, i, timeTaken); -} -#endif - template void BenchMarkCrypto(const char *filename, const char *name, double timeTotal) { - FileSource f(filename, true, new HexDecoder()); + FileSource f(filename, true, new HexDecoder); typename SCHEME::Decryptor priv(f); typename SCHEME::Encryptor pub(priv); BenchMarkEncryption(name, pub, timeTotal); @@ -246,7 +217,7 @@ void BenchMarkCrypto(const char *filename, const char *name, double timeTotal) template void BenchMarkSignature(const char *filename, const char *name, double timeTotal) { - FileSource f(filename, true, new HexDecoder()); + FileSource f(filename, true, new HexDecoder); typename SCHEME::Signer priv(f); typename SCHEME::Verifier pub(priv); BenchMarkSigning(name, priv, timeTotal); @@ -256,74 +227,86 @@ void BenchMarkSignature(const char *filename, const char *name, double timeTotal template void BenchMarkKeyAgreement(const char *filename, const char *name, double timeTotal) { - FileSource f(filename, true, new HexDecoder()); + FileSource f(filename, true, new HexDecoder); D d(f); BenchMarkKeyGen(name, d, timeTotal); BenchMarkAgreement(name, d, timeTotal); } -extern double g_hertz; - -void BenchmarkAll2(double t, double hertz) +void Benchmark3(double t, double hertz) { + g_allocatedTime = t; g_hertz = hertz; - std::cout << "" << std::endl; - std::cout << "
OperationMilliseconds/Operation" << (g_hertz ? "Megacycles/Operation" : "") << std::endl; + std::cout << "\n"; + std::cout << "\n"; + std::cout << "\n"; - BenchMarkCrypto > >(CRYPTOPP_DATA_DIR "TestData/rsa1024.dat", "RSA 1024", t); - BenchMarkCrypto > >(CRYPTOPP_DATA_DIR "TestData/luc1024.dat", "LUC 1024", t); - BenchMarkCrypto >(CRYPTOPP_DATA_DIR "TestData/dlie1024.dat", "DLIES 1024", t); - BenchMarkCrypto >(CRYPTOPP_DATA_DIR "TestData/lucc512.dat", "LUCELG 512", t); + std::cout << "\n"; + { + BenchMarkCrypto > >(CRYPTOPP_DATA_DIR "TestData/rsa1024.dat", "RSA 1024", t); + BenchMarkCrypto > >(CRYPTOPP_DATA_DIR "TestData/luc1024.dat", "LUC 1024", t); + BenchMarkCrypto >(CRYPTOPP_DATA_DIR "TestData/dlie1024.dat", "DLIES 1024", t); + BenchMarkCrypto >(CRYPTOPP_DATA_DIR "TestData/lucc512.dat", "LUCELG 512", t); + } - std::cout << "\n"; - BenchMarkCrypto > >(CRYPTOPP_DATA_DIR "TestData/rsa2048.dat", "RSA 2048", t); - BenchMarkCrypto > >(CRYPTOPP_DATA_DIR "TestData/luc2048.dat", "LUC 2048", t); - BenchMarkCrypto >(CRYPTOPP_DATA_DIR "TestData/dlie2048.dat", "DLIES 2048", t); - BenchMarkCrypto >(CRYPTOPP_DATA_DIR "TestData/lucc1024.dat", "LUCELG 1024", t); + std::cout << "\n"; + { + BenchMarkCrypto > >(CRYPTOPP_DATA_DIR "TestData/rsa2048.dat", "RSA 2048", t); + BenchMarkCrypto > >(CRYPTOPP_DATA_DIR "TestData/luc2048.dat", "LUC 2048", t); + BenchMarkCrypto >(CRYPTOPP_DATA_DIR "TestData/dlie2048.dat", "DLIES 2048", t); + BenchMarkCrypto >(CRYPTOPP_DATA_DIR "TestData/lucc1024.dat", "LUCELG 1024", t); + } - std::cout << "\n"; - BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/rsa1024.dat", "RSA 1024", t); - BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/rw1024.dat", "RW 1024", t); - BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/luc1024.dat", "LUC 1024", t); - BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/nr1024.dat", "NR 1024", t); - BenchMarkSignature(CRYPTOPP_DATA_DIR "TestData/dsa1024.dat", "DSA 1024", t); - BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/lucs512.dat", "LUC-HMP 512", t); - BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/esig1023.dat", "ESIGN 1023", t); - BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/esig1536.dat", "ESIGN 1536", t); + std::cout << "\n"; + { + BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/rsa1024.dat", "RSA 1024", t); + BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/rw1024.dat", "RW 1024", t); + BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/luc1024.dat", "LUC 1024", t); + BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/nr1024.dat", "NR 1024", t); + BenchMarkSignature(CRYPTOPP_DATA_DIR "TestData/dsa1024.dat", "DSA 1024", t); + BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/lucs512.dat", "LUC-HMP 512", t); + BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/esig1023.dat", "ESIGN 1023", t); + BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/esig1536.dat", "ESIGN 1536", t); + } - std::cout << "\n"; - BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/rsa2048.dat", "RSA 2048", t); - BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/rw2048.dat", "RW 2048", t); - BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/luc2048.dat", "LUC 2048", t); - BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/nr2048.dat", "NR 2048", t); - BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/lucs1024.dat", "LUC-HMP 1024", t); - BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/esig2046.dat", "ESIGN 2046", t); + std::cout << "\n"; + { + BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/rsa2048.dat", "RSA 2048", t); + BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/rw2048.dat", "RW 2048", t); + BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/luc2048.dat", "LUC 2048", t); + BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/nr2048.dat", "NR 2048", t); + BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/lucs1024.dat", "LUC-HMP 1024", t); + BenchMarkSignature >(CRYPTOPP_DATA_DIR "TestData/esig2046.dat", "ESIGN 2046", t); + } - std::cout << "\n"; - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/xtrdh171.dat", "XTR-DH 171", t); - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/xtrdh342.dat", "XTR-DH 342", t); - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/dh1024.dat", "DH 1024", t); - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/dh2048.dat", "DH 2048", t); - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/lucd512.dat", "LUCDIF 512", t); - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/lucd1024.dat", "LUCDIF 1024", t); - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/mqv1024.dat", "MQV 1024", t); - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/mqv2048.dat", "MQV 2048", t); + std::cout << "\n"; + { + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/xtrdh171.dat", "XTR-DH 171", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/xtrdh342.dat", "XTR-DH 342", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/dh1024.dat", "DH 1024", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/dh2048.dat", "DH 2048", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/lucd512.dat", "LUCDIF 512", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/lucd1024.dat", "LUCDIF 1024", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/mqv1024.dat", "MQV 1024", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/mqv2048.dat", "MQV 2048", t); #if 0 - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/hmqv160.dat", "HMQV P-160", t); - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/hmqv256.dat", "HMQV P-256", t); - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/hmqv384.dat", "HMQV P-384", t); - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/hmqv512.dat", "HMQV P-512", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/hmqv160.dat", "HMQV P-160", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/hmqv256.dat", "HMQV P-256", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/hmqv384.dat", "HMQV P-384", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/hmqv512.dat", "HMQV P-512", t); - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/fhmqv160.dat", "FHMQV P-160", t); - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/fhmqv256.dat", "FHMQV P-256", t); - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/fhmqv384.dat", "FHMQV P-384", t); - BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/fhmqv512.dat", "FHMQV P-512", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/fhmqv160.dat", "FHMQV P-160", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/fhmqv256.dat", "FHMQV P-256", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/fhmqv384.dat", "FHMQV P-384", t); + BenchMarkKeyAgreement(CRYPTOPP_DATA_DIR "TestData/fhmqv512.dat", "FHMQV P-512", t); #endif + } - std::cout << "\n"; + std::cout << "\n"; { ECIES::Decryptor cpriv(Test::GlobalRNG(), ASN1::secp256k1()); ECIES::Encryptor cpub(cpriv); @@ -350,7 +333,7 @@ void BenchmarkAll2(double t, double hertz) BenchMarkAgreement("ECMQVC over GF(p) 256", ecmqvc, t); } - std::cout << "" << std::endl; + std::cout << "\n"; { ECIES::Decryptor cpriv(Test::GlobalRNG(), ASN1::sect233r1()); ECIES::Encryptor cpub(cpriv); @@ -376,8 +359,9 @@ void BenchmarkAll2(double t, double hertz) BenchMarkKeyGen("ECMQVC over GF(2^n) 233", ecmqvc, t); BenchMarkAgreement("ECMQVC over GF(2^n) 233", ecmqvc, t); } - std::cout << "
OperationMilliseconds/Operation"; + std::cout << (g_hertz > 1.0f ? "Megacycles/Operation" : "") << std::endl; - std::cout << "\n
" << std::endl; + + std::cout << "\n
" << std::endl; } NAMESPACE_END // Test -NAMESPACE_END // CryptoPP \ No newline at end of file +NAMESPACE_END // CryptoPP diff --git a/drbg.h b/drbg.h index 32dae5d2..5d79a616 100644 --- a/drbg.h +++ b/drbg.h @@ -45,9 +45,10 @@ public: //! \param input the entropy to add to the generator //! \param length the size of the input buffer //! \throws NIST_DRBG::Err if the generator is reseeded with insufficient entropy - //! \details NIST instantiation and reseed requirements demand the generator is constructed with at least MINIMUM_ENTROPY - //! entropy. The byte array for input must meet NIST - //! SP 800-90B or SP 800-90C requirements. + //! \details NIST instantiation and reseed requirements demand the generator is constructed + //! with at least MINIMUM_ENTROPY entropy. The byte array for input must + //! meet NIST SP 800-90B or + //! SP 800-90C requirements. virtual void IncorporateEntropy(const byte *input, size_t length)=0; //! \brief Update RNG state with additional unpredictable values @@ -56,10 +57,11 @@ public: //! \param additional additional input to add to the generator //! \param additionaLength the size of the additional input buffer //! \throws NIST_DRBG::Err if the generator is reseeded with insufficient entropy - //! \details IncorporateEntropy() is an overload provided to match NIST requirements. NIST instantiation and - //! reseed requirements demand the generator is constructed with at least MINIMUM_ENTROPY entropy. - //! The byte array for entropy must meet NIST - //! SP 800-90B or SP 800-90C requirements. + //! \details IncorporateEntropy() is an overload provided to match NIST requirements. NIST + //! instantiation and reseed requirements demand the generator is constructed with at least + //! MINIMUM_ENTROPY entropy. The byte array for entropy must meet + //! NIST SP 800-90B or + //!! SP 800-90C requirements. virtual void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)=0; //! \brief Generate random array of bytes @@ -76,8 +78,9 @@ public: //! \param size the length of the buffer, in bytes //! \throws NIST_DRBG::Err if a reseed is required //! \throws NIST_DRBG::Err if the size exceeds MAXIMUM_BYTES_PER_REQUEST - //! \details GenerateBlock() is an overload provided to match NIST requirements. The byte array for additional - //! input is optional. If present the additional randomness is mixed before generating the output bytes. + //! \details GenerateBlock() is an overload provided to match NIST requirements. The byte + //! array for additional input is optional. If present the additional randomness + //! is mixed before generating the output bytes. virtual void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)=0; //! \brief Provides the security strength @@ -93,31 +96,33 @@ public: //! \brief Provides the minimum entropy size //! \returns The minimum entropy size required by the generator, in bytes - //! \details The equivalent class constant is MINIMUM_ENTROPY. All NIST DRBGs must be instaniated with at least - //! MINIMUM_ENTROPY bytes of entropy. The bytes must meet NIST SP 800-90B or SP 800-90C requirements. + //! \details The equivalent class constant is MINIMUM_ENTROPY. All NIST DRBGs must + //! be instaniated with at least MINIMUM_ENTROPY bytes of entropy. The bytes must + //! meet NIST SP 800-90B or + //! SP 800-90C requirements. virtual unsigned int GetMinEntropy() const=0; //! \brief Provides the maximum entropy size //! \returns The maximum entropy size that can be consumed by the generator, in bytes - //! \details The equivalent class constant is MAXIMUM_ENTROPY. The bytes must meet NIST SP 800-90B or SP 800-90C requirements. - //! MAXIMUM_ENTROPY has been reduced from 235 to INT_MAX to fit the underlying C++ datatype. + //! \details The equivalent class constant is MAXIMUM_ENTROPY. The bytes must + //! meet NIST SP 800-90B or + //! SP 800-90C requirements. MAXIMUM_ENTROPY has been reduced from + //! 235 to INT_MAX to fit the underlying C++ datatype. virtual unsigned int GetMaxEntropy() const=0; //! \brief Provides the minimum nonce size //! \returns The minimum nonce size recommended for the generator, in bytes - //! \details The equivalent class constant is MINIMUM_NONCE. If a nonce is not required then - //! MINIMUM_NONCE is 0. Hash_DRBG does not require a nonce, while HMAC_DRBG - //! and CTR_DRBG require a nonce. + //! \details The equivalent class constant is MINIMUM_NONCE. If a nonce is not + //! required then MINIMUM_NONCE is 0. Hash_DRBG does not require a + //! nonce, while HMAC_DRBG and CTR_DRBG require a nonce. virtual unsigned int GetMinNonce() const=0; //! \brief Provides the maximum nonce size //! \returns The maximum nonce that can be consumed by the generator, in bytes - //! \details The equivalent class constant is MAXIMUM_NONCE. MAXIMUM_NONCE has been reduced from - //! 235 to INT_MAX to fit the underlying C++ datatype. If a nonce is not required then - //! MINIMUM_NONCE is 0. Hash_DRBG does not require a nonce, while HMAC_DRBG - //! and CTR_DRBG require a nonce. + //! \details The equivalent class constant is MAXIMUM_NONCE. MAXIMUM_NONCE + //! has been reduced from 235 to INT_MAX to fit the underlying C++ datatype. + //! If a nonce is not required then MINIMUM_NONCE is 0. Hash_DRBG does not + //! require a nonce, while HMAC_DRBG and CTR_DRBG require a nonce. virtual unsigned int GetMaxNonce() const=0; //! \brief Provides the maximum size of a request to GenerateBlock @@ -150,8 +155,9 @@ protected: //! Security Strength and Seed Length, depend on the hash and are specified as template parameters. //! The remaining parameters are included in the class. The parameters and their values are listed //! in NIST SP 800-90A Rev. 1, Table 2: Definitions for Hash-Based DRBG Mechanisms (p.38). -//! \details Some parameters have been reduce to fit C++ datatypes. For example, NIST allows upto 248 requests -//! before a reseed. However, Hash_DRBG limits it to INT_MAX due to the limited data range of an int. +//! \details Some parameters have been reduce to fit C++ datatypes. For example, NIST allows upto +//! 248 requests before a reseed. However, Hash_DRBG limits it to INT_MAX due +//! to the limited data range of an int. //! \sa Recommendation //! for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015) //! \since Crypto++ 6.0 @@ -199,11 +205,12 @@ public: //! Hash_DRBG drbg(entropy, 32, entropy+32, 16); //! drbg.GenerateBlock(result, result.size()); //! - Hash_DRBG(const byte* entropy, size_t entropyLength=STRENGTH, const byte* nonce=NULLPTR, + Hash_DRBG(const byte* entropy=NULLPTR, size_t entropyLength=STRENGTH, const byte* nonce=NULLPTR, size_t nonceLength=0, const byte* personalization=NULLPTR, size_t personalizationLength=0) : NIST_DRBG(), m_c(SEEDLENGTH), m_v(SEEDLENGTH) { - DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength); + if (entropy != NULLPTR && entropyLength != 0) + DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength); } unsigned int GetSecurityStrength() const {return SECURITY_STRENGTH;} @@ -312,11 +319,12 @@ public: //! HMAC_DRBG drbg(entropy, 32, entropy+32, 16); //! drbg.GenerateBlock(result, result.size()); //! - HMAC_DRBG(const byte* entropy, size_t entropyLength=STRENGTH, const byte* nonce=NULLPTR, + HMAC_DRBG(const byte* entropy=NULLPTR, size_t entropyLength=STRENGTH, const byte* nonce=NULLPTR, size_t nonceLength=0, const byte* personalization=NULLPTR, size_t personalizationLength=0) : NIST_DRBG(), m_k(HASH::DIGESTSIZE), m_v(HASH::DIGESTSIZE) { - DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength); + if (entropy != NULLPTR && entropyLength != 0) + DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength); } unsigned int GetSecurityStrength() const {return SECURITY_STRENGTH;} diff --git a/mersenne.h b/mersenne.h index 6337cb0e..57f52464 100644 --- a/mersenne.h +++ b/mersenne.h @@ -30,7 +30,7 @@ template = 1410) # pragma strict_gs_check (on) #endif -#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - USING_NAMESPACE(CryptoPP) void RegisterFactories() @@ -191,5 +193,25 @@ void RegisterFactories() RegisterDefaultFactoryFor >(); RegisterDefaultFactoryFor >(); +#ifdef BLOCKING_RNG_AVAILABLE + RegisterDefaultFactoryFor(); +#endif +#ifdef NONBLOCKING_RNG_AVAILABLE + RegisterDefaultFactoryFor(); +#endif +#ifdef OS_RNG_AVAILABLE + RegisterDefaultFactoryFor(); + RegisterDefaultFactoryFor >(); +#endif + RegisterDefaultFactoryFor(); +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) + if (HasRDRAND()) + RegisterDefaultFactoryFor(); + if (HasRDSEED()) + RegisterDefaultFactoryFor(); +#endif + RegisterDefaultFactoryFor >("Hash_DRBG(SHA1)"); + RegisterDefaultFactoryFor >("HMAC_DRBG(SHA1)"); + s_registered = true; } diff --git a/rng.cpp b/rng.cpp index 44c81e15..c1763974 100644 --- a/rng.cpp +++ b/rng.cpp @@ -5,8 +5,8 @@ #include "rng.h" #include "fips140.h" -#include -#include +#include +#include NAMESPACE_BEGIN(CryptoPP) @@ -76,7 +76,7 @@ X917RNG::X917RNG(BlockTransformation *c, const byte *seed, const byte *determini if (!deterministicTimeVector) { - time_t tstamp1 = time(NULLPTR); + time_t tstamp1 = std::time(NULLPTR); xorbuf(m_datetime, (byte *)&tstamp1, UnsignedMin(sizeof(tstamp1), m_size)); m_cipher->ProcessBlock(m_datetime); clock_t tstamp2 = clock(); @@ -102,7 +102,7 @@ void X917RNG::GenerateIntoBufferedTransformation(BufferedTransformation &target, { clock_t c = clock(); xorbuf(m_datetime, (byte *)&c, UnsignedMin(sizeof(c), m_size)); - time_t t = time(NULLPTR); + time_t t = std::time(NULLPTR); xorbuf(m_datetime+m_size-UnsignedMin(sizeof(t), m_size), (byte *)&t, UnsignedMin(sizeof(t), m_size)); m_cipher->ProcessBlock(m_datetime); } @@ -142,7 +142,7 @@ size_t MaurerRandomnessTest::Put2(const byte *inString, size_t length, int /*mes { byte inByte = *inString++; if (n >= Q) - sum += log(double(n - tab[inByte])); + sum += std::log(double(n - tab[inByte])); tab[inByte] = n; n++; } @@ -154,7 +154,7 @@ double MaurerRandomnessTest::GetTestValue() const if (BytesNeeded() > 0) throw Exception(Exception::OTHER_ERROR, "MaurerRandomnessTest: " + IntToString(BytesNeeded()) + " more bytes of input needed"); - double fTu = (sum/(n-Q))/log(2.0); // this is the test value defined by Maurer + double fTu = (sum/(n-Q))/std::log(2.0); // this is the test value defined by Maurer double value = fTu * 0.1392; // arbitrarily normalize it to return value > 1.0 ? 1.0 : value; // a number between 0 and 1 diff --git a/test.cpp b/test.cpp index bff38434..ba2e0480 100644 --- a/test.cpp +++ b/test.cpp @@ -22,18 +22,17 @@ #include "whrlpool.h" #include "tiger.h" #include "smartptr.h" +#include "stdcpp.h" #include "ossig.h" #include "trap.h" #include "validate.h" #include "bench.h" -#include #include #include -#include #include -#include +#include #ifdef CRYPTOPP_WIN32_AVAILABLE #define WIN32_LEAN_AND_MEAN @@ -118,6 +117,43 @@ int (*AdhocTest)(int argc, char *argv[]) = NULLPTR; NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(Test) +// Coverity finding +template +T StringToValue(const std::string& str) +{ + std::istringstream iss(str); + + // Arbitrary, but we need to clear a Coverity finding TAINTED_SCALAR + if (iss.str().length() > 25) + throw InvalidArgument(str + "' is too long"); + + T value; + iss >> std::noskipws >> value; + + // Use fail(), not bad() + if (iss.fail() || !iss.eof()) + throw InvalidArgument(str + "' is not a value"); + + if (NON_NEGATIVE && value < 0) + throw InvalidArgument(str + "' is negative"); + + return value; +} + +// Coverity finding +template<> +int StringToValue(const std::string& str) +{ + Integer n(str.c_str()); + long l = n.ConvertToLong(); + + int r; + if (!SafeConvert(l, r)) + throw InvalidArgument(str + "' is not an integer value"); + + return r; +} + ANONYMOUS_NAMESPACE_BEGIN OFB_Mode::Encryption s_globalRNG; NAMESPACE_END @@ -367,10 +403,14 @@ int CRYPTOPP_API main(int argc, char *argv[]) InformationRecoverFile(argc-3, argv[2], argv+3); else if (command == "v" || command == "vv") return !Validate(argc>2 ? Test::StringToValue(argv[2]) : 0, argv[1][1] == 'v', argc>3 ? argv[3] : NULLPTR); - else if (command == "b") - Test::BenchmarkAll(argc<3 ? 1 : Test::StringToValue(argv[2]), argc<4 ? 0.0f : Test::StringToValue(argv[3])*1e9); - else if (command == "b2") - Test::BenchmarkAll2(argc<3 ? 1 : Test::StringToValue(argv[2]), argc<4 ? 0.0f : Test::StringToValue(argv[3])*1e9); + else if (command == "b") // All benchmarks + Test::Benchmark(7, argc<3 ? 1 : Test::StringToValue(argv[2]), argc<4 ? 0.0f : Test::StringToValue(argv[3])*1e9); + else if (command == "b3") // Public key algorithms + Test::Benchmark(4, argc<3 ? 1 : Test::StringToValue(argv[2]), argc<4 ? 0.0f : Test::StringToValue(argv[3])*1e9); + else if (command == "b2") // Shared key algorithms + Test::Benchmark(2, argc<3 ? 1 : Test::StringToValue(argv[2]), argc<4 ? 0.0f : Test::StringToValue(argv[3])*1e9); + else if (command == "b1") // Unkeyed algorithms + Test::Benchmark(1, argc<3 ? 1 : Test::StringToValue(argv[2]), argc<4 ? 0.0f : Test::StringToValue(argv[3])*1e9); else if (command == "z") GzipFile(argv[3], argv[4], argv[2][0]-'0'); else if (command == "u") @@ -437,41 +477,6 @@ void FIPS140_GenerateRandomFiles() #endif } -template -T Test::StringToValue(const std::string& str) -{ - std::istringstream iss(str); - - // Arbitrary, but we need to clear a Coverity finding TAINTED_SCALAR - if(iss.str().length() > 25) - throw InvalidArgument("cryptest.exe: '" + str +"' is too long"); - - T value; - iss >> std::noskipws >> value; - - // Use fail(), not bad() - if (iss.fail() || !iss.eof()) - throw InvalidArgument("cryptest.exe: '" + str +"' is not a value"); - - if (NON_NEGATIVE && value < 0) - throw InvalidArgument("cryptest.exe: '" + str +"' is negative"); - - return value; -} - -template<> -int Test::StringToValue(const std::string& str) -{ - Integer n(str.c_str()); - long l = n.ConvertToLong(); - - int r; - if(!SafeConvert(l, r)) - throw InvalidArgument("cryptest.exe: '" + str +"' is not an integer value"); - - return r; -} - void PrintSeedAndThreads(const std::string& seed) { std::cout << "Using seed: " << seed << std::endl; @@ -893,12 +898,12 @@ bool Validate(int alg, bool thorough, const char *seedInput) // Some editors have problems with the '\0' character when redirecting output. // seedInput is argv[3] when issuing 'cryptest.exe v all ' - std::string seed = (seedInput ? seedInput : IntToString(time(NULLPTR))); + std::string seed = (seedInput ? seedInput : IntToString(std::time(NULLPTR))); seed.resize(16, ' '); - OFB_Mode::Encryption& prng = dynamic_cast::Encryption&>(Test::GlobalRNG()); prng.SetKeyWithIV((byte *)seed.data(), 16, (byte *)seed.data()); + Test::g_testBegin = std::time(NULLPTR); PrintSeedAndThreads(seed); switch (alg) @@ -1001,25 +1006,11 @@ bool Validate(int alg, bool thorough, const char *seedInput) default: return false; } -// Safer functions on Windows for C&A, https://github.com/weidai11/cryptopp/issues/55 -#if (CRYPTOPP_MSC_VERSION >= 1400) - tm localTime = {}; - char timeBuf[64]; - errno_t err; + Test::g_testEnd = std::time(NULLPTR); - const time_t endTime = time(NULLPTR); - err = localtime_s(&localTime, &endTime); - CRYPTOPP_ASSERT(err == 0); - err = asctime_s(timeBuf, sizeof(timeBuf), &localTime); - CRYPTOPP_ASSERT(err == 0); - - std::cout << "\nTest ended at " << timeBuf; -#else - const time_t endTime = time(NULLPTR); - std::cout << "\nTest ended at " << asctime(localtime(&endTime)); -#endif - - std::cout << "Seed used was: " << seed << std::endl; + std::cout << "\nSeed used was " << seed << std::endl; + std::cout << "Test started at " << Test::TimeToString(Test::g_testBegin) << std::endl; + std::cout << "Test ended at " << Test::TimeToString(Test::g_testEnd) << std::endl; return result; }