From deea52fd3b8059dc61d503d4a125d85cb4e2cc81 Mon Sep 17 00:00:00 2001 From: weidai Date: Thu, 17 Oct 2002 16:32:28 +0000 Subject: [PATCH] bug fixes and KAT for X9.17 RNG --- Readme.txt | 8 +++++++- algparam.cpp | 6 +++++- algparam.h | 4 ++-- cryptlib.h | 2 +- fipstest.cpp | 34 ++++++++++++++++++++++++++++++++++ modes.cpp | 8 +++++--- osrng.h | 25 +++++++++++++++++-------- rng.cpp | 37 +++++++++++++++++++++++++++---------- rng.h | 5 +++-- validat1.cpp | 4 ++-- 10 files changed, 103 insertions(+), 30 deletions(-) diff --git a/Readme.txt b/Readme.txt index 37f53273..8c3c3bbd 100644 --- a/Readme.txt +++ b/Readme.txt @@ -1,5 +1,5 @@ Crypto++: a C++ Class Library of Cryptographic Primitives -Version 5.0 9/11/2002 +Version 5.1 (in development) This library includes: @@ -241,3 +241,9 @@ History - is being evaluated for FIPS 140-2 compliance - fixed a bug in HMAC::TruncatedFinal() - fixed SKIPJACK byte ordering following NIST clarification dated 5/9/02 + +5.01 (special FIPS 140-2 release, in development) + - added known answer test for X9.17 RNG in FIPS 140 power-up self test + +5.1 (in development) + - fixed a bug in CBC and ECB modes with processing non-aligned data diff --git a/algparam.cpp b/algparam.cpp index 1ef7de44..1b980b6e 100644 --- a/algparam.cpp +++ b/algparam.cpp @@ -6,7 +6,11 @@ NAMESPACE_BEGIN(CryptoPP) -const std::type_info &g_typeidInteger = typeid(Integer); +const std::type_info & IntegerTypeId() +{ + static const std::type_info &s_typeidInteger = typeid(Integer); + return s_typeidInteger; +} void AssignIntToInteger(void *pInteger, const void *pInt) { diff --git a/algparam.h b/algparam.h index 3e09d1f2..624fcdc7 100644 --- a/algparam.h +++ b/algparam.h @@ -241,7 +241,7 @@ AssignFromHelperClass AssignFromHelper(T *pObject, const NameValuePairs &s void AssignIntToInteger(void *pInteger, const void *pInt); -extern const std::type_info &g_typeidInteger; +const std::type_info & IntegerTypeId(); template class AlgorithmParameters : public NameValuePairs @@ -283,7 +283,7 @@ public: else if (strcmp(name, m_name) == 0) { // special case for retrieving an Integer parameter when an int was passed in - if (valueType == g_typeidInteger && typeid(T) == typeid(int)) + if (valueType == IntegerTypeId() && typeid(T) == typeid(int)) AssignIntToInteger(pValue, &m_value); else { diff --git a/cryptlib.h b/cryptlib.h index 9be8849e..b73669d3 100644 --- a/cryptlib.h +++ b/cryptlib.h @@ -4,7 +4,7 @@ classes that provide a uniform interface to this library. */ -/*! \mainpage Crypto++TM Library 5.0 Reference Manual +/*! \mainpage Crypto++TM Library 5.1 Reference Manual
Abstract Base Classes
cryptlib.h diff --git a/fipstest.cpp b/fipstest.cpp index 063ab6bf..56993906 100644 --- a/fipstest.cpp +++ b/fipstest.cpp @@ -23,6 +23,34 @@ NAMESPACE_BEGIN(CryptoPP) extern PowerUpSelfTestStatus g_powerUpSelfTestStatus; +void KnownAnswerTest(RandomNumberGenerator &rng, const char *output) +{ + EqualityComparisonFilter comparison; + + RandomNumberStore(rng, strlen(output)/2).TransferAllTo(comparison, "0"); + StringSource(output, true, new HexDecoder(new ChannelSwitch(comparison, "1"))); + + comparison.ChannelMessageSeriesEnd("0"); + comparison.ChannelMessageSeriesEnd("1"); +} + +template +void X917RNG_KnownAnswerTest( + const char *key, + const char *seed, + const char *output, + unsigned int deterministicTimeVector, + CIPHER *dummy = NULL) +{ + std::string decodedKey, decodedSeed; + StringSource(key, true, new HexDecoder(new StringSink(decodedKey))); + StringSource(seed, true, new HexDecoder(new StringSink(decodedSeed))); + + AutoSeededX917RNG rng; + rng.Reseed((const byte *)decodedKey.data(), decodedKey.size(), (const byte *)decodedSeed.data(), deterministicTimeVector); + KnownAnswerTest(rng, output); +} + void KnownAnswerTest(StreamTransformation &encryption, StreamTransformation &decryption, const char *plaintext, const char *ciphertext) { EqualityComparisonFilter comparison; @@ -208,6 +236,12 @@ void DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleSha // algorithm tests + X917RNG_KnownAnswerTest( + "48851090B4992453E83CDA86416534E53EA2FCE1A0B3A40C", // key + "7D00BD0A79F6B0F5", // seed + "22B590B08B53363AEB89AD65F81A5B6FB83F326CE06BF35751E6C41B43B729C4", // output + 1489728269); // time vector + SymmetricEncryptionKnownAnswerTest( "0123456789abcdef", // key "1234567890abcdef", // IV diff --git a/modes.cpp b/modes.cpp index 1b5f8538..a517c719 100644 --- a/modes.cpp +++ b/modes.cpp @@ -144,11 +144,11 @@ void BlockOrientedCipherModeBase::ProcessData(byte *outString, const byte *inStr unsigned int s = BlockSize(); assert(length % s == 0); unsigned int alignment = m_cipher->BlockAlignment(); - bool requireAlignedInput = RequireAlignedInput(); + bool inputAlignmentOk = !RequireAlignedInput() || IsAlignedOn(inString, alignment); if (IsAlignedOn(outString, alignment)) { - if (!requireAlignedInput || IsAlignedOn(inString, alignment)) + if (inputAlignmentOk) ProcessBlocks(outString, inString, length / s); else { @@ -160,7 +160,7 @@ void BlockOrientedCipherModeBase::ProcessData(byte *outString, const byte *inStr { while (length) { - if (!requireAlignedInput || IsAlignedOn(inString, alignment)) + if (inputAlignmentOk) ProcessBlocks(m_buffer, inString, 1); else { @@ -168,6 +168,8 @@ void BlockOrientedCipherModeBase::ProcessData(byte *outString, const byte *inStr ProcessBlocks(m_buffer, m_buffer, 1); } memcpy(outString, m_buffer, s); + inString += s; + outString += s; length -= s; } } diff --git a/osrng.h b/osrng.h index 3a40560b..c5814a51 100644 --- a/osrng.h +++ b/osrng.h @@ -96,6 +96,8 @@ public: explicit AutoSeededX917RNG(bool blocking = false) {Reseed(blocking);} void Reseed(bool blocking = false); + // exposed for testing + void Reseed(const byte *key, unsigned int keylength, const byte *seed, unsigned long timeVector); byte GenerateByte(); @@ -106,6 +108,20 @@ private: unsigned int m_counter; }; +template +void AutoSeededX917RNG::Reseed(const byte *key, unsigned int keylength, const byte *seed, unsigned long timeVector) +{ + m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector)); + + if (FIPS_140_2_ComplianceEnabled()) + { + m_lastBlock.resize(16); + m_rng->GenerateBlock(m_lastBlock, m_lastBlock.size()); + m_counter = 0; + m_isDifferent = false; + } +} + template void AutoSeededX917RNG::Reseed(bool blocking) { @@ -117,15 +133,8 @@ void AutoSeededX917RNG::Reseed(bool blocking) key = seed + BLOCK_CIPHER::BLOCKSIZE; } // check that seed and key don't have same value while (memcmp(key, seed, STDMIN((unsigned int)BLOCK_CIPHER::BLOCKSIZE, (unsigned int)BLOCK_CIPHER::DEFAULT_KEYLENGTH)) == 0); - m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH), seed)); - if (FIPS_140_2_ComplianceEnabled()) - { - m_lastBlock.resize(16); - m_rng->GenerateBlock(m_lastBlock, m_lastBlock.size()); - m_counter = 0; - m_isDifferent = false; - } + Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, 0); } template diff --git a/rng.cpp b/rng.cpp index b16e6bd3..0119d301 100644 --- a/rng.cpp +++ b/rng.cpp @@ -51,20 +51,29 @@ byte LC_RNG::GenerateByte() // ******************************************************** -X917RNG::X917RNG(BlockTransformation *c, const byte *seed) +X917RNG::X917RNG(BlockTransformation *c, const byte *seed, unsigned long deterministicTimeVector) : cipher(c), S(cipher->BlockSize()), dtbuf(S), randseed(seed, S), randbuf(S), - randbuf_counter(0) + randbuf_counter(0), + m_deterministicTimeVector(deterministicTimeVector) { - time_t tstamp1 = time(0); - xorbuf(dtbuf, (byte *)&tstamp1, STDMIN((int)sizeof(tstamp1), S)); - cipher->ProcessBlock(dtbuf); - clock_t tstamp2 = clock(); - xorbuf(dtbuf, (byte *)&tstamp2, STDMIN((int)sizeof(tstamp2), S)); - cipher->ProcessBlock(dtbuf); + if (m_deterministicTimeVector) + { + memset(dtbuf, 0, S); + memcpy(dtbuf, (byte *)&m_deterministicTimeVector, STDMIN((int)sizeof(m_deterministicTimeVector), S)); + } + else + { + time_t tstamp1 = time(0); + xorbuf(dtbuf, (byte *)&tstamp1, STDMIN((int)sizeof(tstamp1), S)); + cipher->ProcessBlock(dtbuf); + clock_t tstamp2 = clock(); + xorbuf(dtbuf, (byte *)&tstamp2, STDMIN((int)sizeof(tstamp2), S)); + cipher->ProcessBlock(dtbuf); + } } byte X917RNG::GenerateByte() @@ -72,8 +81,16 @@ byte X917RNG::GenerateByte() if (randbuf_counter==0) { // calculate new enciphered timestamp - clock_t tstamp = clock(); - xorbuf(dtbuf, (byte *)&tstamp, STDMIN((int)sizeof(tstamp), S)); + if (m_deterministicTimeVector) + { + xorbuf(dtbuf, (byte *)&m_deterministicTimeVector, STDMIN((int)sizeof(m_deterministicTimeVector), S)); + while (++m_deterministicTimeVector == 0) {} // skip 0 + } + else + { + clock_t tstamp = clock(); + xorbuf(dtbuf, (byte *)&tstamp, STDMIN((int)sizeof(tstamp), S)); + } cipher->ProcessBlock(dtbuf); // combine enciphered timestamp with seed diff --git a/rng.h b/rng.h index f4afaeb5..5b0998d4 100644 --- a/rng.h +++ b/rng.h @@ -32,8 +32,8 @@ private: class X917RNG : public RandomNumberGenerator { public: - // cipher will be deleted by destructor - X917RNG(BlockTransformation *cipher, const byte *seed); + // cipher will be deleted by destructor, deterministicTimeVector = 0 means obtain time vector from system + X917RNG(BlockTransformation *cipher, const byte *seed, unsigned long deterministicTimeVector = 0); byte GenerateByte(); @@ -43,6 +43,7 @@ private: SecByteBlock dtbuf; // buffer for enciphered timestamp SecByteBlock randseed, randbuf; int randbuf_counter; // # of unused bytes left in randbuf + unsigned long m_deterministicTimeVector; }; /** This class implements Maurer's Universal Statistical Test for Random Bit Generators diff --git a/validat1.cpp b/validat1.cpp index b96a5228..9c03951f 100644 --- a/validat1.cpp +++ b/validat1.cpp @@ -226,7 +226,7 @@ bool TestOS_RNG() member_ptr rng; #ifdef BLOCKING_RNG_AVAILABLE try {rng.reset(new BlockingRng);} - catch (OS_RNG_Err &e) {} + catch (OS_RNG_Err &) {} #endif if (rng.get()) @@ -304,7 +304,7 @@ bool TestOS_RNG() rng.reset(NULL); #ifdef NONBLOCKING_RNG_AVAILABLE try {rng.reset(new NonblockingRng);} - catch (OS_RNG_Err &e) {} + catch (OS_RNG_Err &) {} #endif if (rng.get())