bug fixes and KAT for X9.17 RNG

pull/2/head
weidai 2002-10-17 16:32:28 +00:00
parent 0e0049180d
commit deea52fd3b
10 changed files with 103 additions and 30 deletions

View File

@ -1,5 +1,5 @@
Crypto++: a C++ Class Library of Cryptographic Primitives Crypto++: a C++ Class Library of Cryptographic Primitives
Version 5.0 9/11/2002 Version 5.1 (in development)
This library includes: This library includes:
@ -241,3 +241,9 @@ History
- is being evaluated for FIPS 140-2 compliance - is being evaluated for FIPS 140-2 compliance
- fixed a bug in HMAC::TruncatedFinal() - fixed a bug in HMAC::TruncatedFinal()
- fixed SKIPJACK byte ordering following NIST clarification dated 5/9/02 - 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

View File

@ -6,7 +6,11 @@
NAMESPACE_BEGIN(CryptoPP) 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) void AssignIntToInteger(void *pInteger, const void *pInt)
{ {

View File

@ -241,7 +241,7 @@ AssignFromHelperClass<T, T> AssignFromHelper(T *pObject, const NameValuePairs &s
void AssignIntToInteger(void *pInteger, const void *pInt); void AssignIntToInteger(void *pInteger, const void *pInt);
extern const std::type_info &g_typeidInteger; const std::type_info & IntegerTypeId();
template <class BASE, class T> template <class BASE, class T>
class AlgorithmParameters : public NameValuePairs class AlgorithmParameters : public NameValuePairs
@ -283,7 +283,7 @@ public:
else if (strcmp(name, m_name) == 0) else if (strcmp(name, m_name) == 0)
{ {
// special case for retrieving an Integer parameter when an int was passed in // 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); AssignIntToInteger(pValue, &m_value);
else else
{ {

View File

@ -4,7 +4,7 @@
classes that provide a uniform interface to this library. classes that provide a uniform interface to this library.
*/ */
/*! \mainpage <a href="http://www.cryptopp.com">Crypto++</a><sup><small>TM</small></sup> Library 5.0 Reference Manual /*! \mainpage <a href="http://www.cryptopp.com">Crypto++</a><sup><small>TM</small></sup> Library 5.1 Reference Manual
<dl> <dl>
<dt>Abstract Base Classes<dd> <dt>Abstract Base Classes<dd>
cryptlib.h cryptlib.h

View File

@ -23,6 +23,34 @@ NAMESPACE_BEGIN(CryptoPP)
extern PowerUpSelfTestStatus g_powerUpSelfTestStatus; 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 <class CIPHER>
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<CIPHER> 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) void KnownAnswerTest(StreamTransformation &encryption, StreamTransformation &decryption, const char *plaintext, const char *ciphertext)
{ {
EqualityComparisonFilter comparison; EqualityComparisonFilter comparison;
@ -208,6 +236,12 @@ void DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleSha
// algorithm tests // algorithm tests
X917RNG_KnownAnswerTest<DES_EDE3>(
"48851090B4992453E83CDA86416534E53EA2FCE1A0B3A40C", // key
"7D00BD0A79F6B0F5", // seed
"22B590B08B53363AEB89AD65F81A5B6FB83F326CE06BF35751E6C41B43B729C4", // output
1489728269); // time vector
SymmetricEncryptionKnownAnswerTest<DES>( SymmetricEncryptionKnownAnswerTest<DES>(
"0123456789abcdef", // key "0123456789abcdef", // key
"1234567890abcdef", // IV "1234567890abcdef", // IV

View File

@ -144,11 +144,11 @@ void BlockOrientedCipherModeBase::ProcessData(byte *outString, const byte *inStr
unsigned int s = BlockSize(); unsigned int s = BlockSize();
assert(length % s == 0); assert(length % s == 0);
unsigned int alignment = m_cipher->BlockAlignment(); unsigned int alignment = m_cipher->BlockAlignment();
bool requireAlignedInput = RequireAlignedInput(); bool inputAlignmentOk = !RequireAlignedInput() || IsAlignedOn(inString, alignment);
if (IsAlignedOn(outString, alignment)) if (IsAlignedOn(outString, alignment))
{ {
if (!requireAlignedInput || IsAlignedOn(inString, alignment)) if (inputAlignmentOk)
ProcessBlocks(outString, inString, length / s); ProcessBlocks(outString, inString, length / s);
else else
{ {
@ -160,7 +160,7 @@ void BlockOrientedCipherModeBase::ProcessData(byte *outString, const byte *inStr
{ {
while (length) while (length)
{ {
if (!requireAlignedInput || IsAlignedOn(inString, alignment)) if (inputAlignmentOk)
ProcessBlocks(m_buffer, inString, 1); ProcessBlocks(m_buffer, inString, 1);
else else
{ {
@ -168,6 +168,8 @@ void BlockOrientedCipherModeBase::ProcessData(byte *outString, const byte *inStr
ProcessBlocks(m_buffer, m_buffer, 1); ProcessBlocks(m_buffer, m_buffer, 1);
} }
memcpy(outString, m_buffer, s); memcpy(outString, m_buffer, s);
inString += s;
outString += s;
length -= s; length -= s;
} }
} }

25
osrng.h
View File

@ -96,6 +96,8 @@ public:
explicit AutoSeededX917RNG(bool blocking = false) explicit AutoSeededX917RNG(bool blocking = false)
{Reseed(blocking);} {Reseed(blocking);}
void Reseed(bool blocking = false); void Reseed(bool blocking = false);
// exposed for testing
void Reseed(const byte *key, unsigned int keylength, const byte *seed, unsigned long timeVector);
byte GenerateByte(); byte GenerateByte();
@ -106,6 +108,20 @@ private:
unsigned int m_counter; unsigned int m_counter;
}; };
template <class BLOCK_CIPHER>
void AutoSeededX917RNG<BLOCK_CIPHER>::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 <class BLOCK_CIPHER> template <class BLOCK_CIPHER>
void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking) void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking)
{ {
@ -117,15 +133,8 @@ void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking)
key = seed + BLOCK_CIPHER::BLOCKSIZE; key = seed + BLOCK_CIPHER::BLOCKSIZE;
} // check that seed and key don't have same value } // 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); 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()) Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, 0);
{
m_lastBlock.resize(16);
m_rng->GenerateBlock(m_lastBlock, m_lastBlock.size());
m_counter = 0;
m_isDifferent = false;
}
} }
template <class BLOCK_CIPHER> template <class BLOCK_CIPHER>

37
rng.cpp
View File

@ -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), : cipher(c),
S(cipher->BlockSize()), S(cipher->BlockSize()),
dtbuf(S), dtbuf(S),
randseed(seed, S), randseed(seed, S),
randbuf(S), randbuf(S),
randbuf_counter(0) randbuf_counter(0),
m_deterministicTimeVector(deterministicTimeVector)
{ {
time_t tstamp1 = time(0); if (m_deterministicTimeVector)
xorbuf(dtbuf, (byte *)&tstamp1, STDMIN((int)sizeof(tstamp1), S)); {
cipher->ProcessBlock(dtbuf); memset(dtbuf, 0, S);
clock_t tstamp2 = clock(); memcpy(dtbuf, (byte *)&m_deterministicTimeVector, STDMIN((int)sizeof(m_deterministicTimeVector), S));
xorbuf(dtbuf, (byte *)&tstamp2, STDMIN((int)sizeof(tstamp2), S)); }
cipher->ProcessBlock(dtbuf); 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() byte X917RNG::GenerateByte()
@ -72,8 +81,16 @@ byte X917RNG::GenerateByte()
if (randbuf_counter==0) if (randbuf_counter==0)
{ {
// calculate new enciphered timestamp // calculate new enciphered timestamp
clock_t tstamp = clock(); if (m_deterministicTimeVector)
xorbuf(dtbuf, (byte *)&tstamp, STDMIN((int)sizeof(tstamp), S)); {
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); cipher->ProcessBlock(dtbuf);
// combine enciphered timestamp with seed // combine enciphered timestamp with seed

5
rng.h
View File

@ -32,8 +32,8 @@ private:
class X917RNG : public RandomNumberGenerator class X917RNG : public RandomNumberGenerator
{ {
public: public:
// cipher will be deleted by destructor // cipher will be deleted by destructor, deterministicTimeVector = 0 means obtain time vector from system
X917RNG(BlockTransformation *cipher, const byte *seed); X917RNG(BlockTransformation *cipher, const byte *seed, unsigned long deterministicTimeVector = 0);
byte GenerateByte(); byte GenerateByte();
@ -43,6 +43,7 @@ private:
SecByteBlock dtbuf; // buffer for enciphered timestamp SecByteBlock dtbuf; // buffer for enciphered timestamp
SecByteBlock randseed, randbuf; SecByteBlock randseed, randbuf;
int randbuf_counter; // # of unused bytes left in 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 /** This class implements Maurer's Universal Statistical Test for Random Bit Generators

View File

@ -226,7 +226,7 @@ bool TestOS_RNG()
member_ptr<RandomNumberGenerator> rng; member_ptr<RandomNumberGenerator> rng;
#ifdef BLOCKING_RNG_AVAILABLE #ifdef BLOCKING_RNG_AVAILABLE
try {rng.reset(new BlockingRng);} try {rng.reset(new BlockingRng);}
catch (OS_RNG_Err &e) {} catch (OS_RNG_Err &) {}
#endif #endif
if (rng.get()) if (rng.get())
@ -304,7 +304,7 @@ bool TestOS_RNG()
rng.reset(NULL); rng.reset(NULL);
#ifdef NONBLOCKING_RNG_AVAILABLE #ifdef NONBLOCKING_RNG_AVAILABLE
try {rng.reset(new NonblockingRng);} try {rng.reset(new NonblockingRng);}
catch (OS_RNG_Err &e) {} catch (OS_RNG_Err &) {}
#endif #endif
if (rng.get()) if (rng.get())