bug fixes and KAT for X9.17 RNG

This commit is contained in:
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
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

View File

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

View File

@ -241,7 +241,7 @@ AssignFromHelperClass<T, T> 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 BASE, class T>
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
{

View File

@ -4,7 +4,7 @@
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>
<dt>Abstract Base Classes<dd>
cryptlib.h

View File

@ -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 <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)
{
EqualityComparisonFilter comparison;
@ -208,6 +236,12 @@ void DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleSha
// algorithm tests
X917RNG_KnownAnswerTest<DES_EDE3>(
"48851090B4992453E83CDA86416534E53EA2FCE1A0B3A40C", // key
"7D00BD0A79F6B0F5", // seed
"22B590B08B53363AEB89AD65F81A5B6FB83F326CE06BF35751E6C41B43B729C4", // output
1489728269); // time vector
SymmetricEncryptionKnownAnswerTest<DES>(
"0123456789abcdef", // key
"1234567890abcdef", // IV

View File

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

25
osrng.h
View File

@ -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 <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>
void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking)
{
@ -117,15 +133,8 @@ void AutoSeededX917RNG<BLOCK_CIPHER>::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 <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),
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

5
rng.h
View File

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

View File

@ -226,7 +226,7 @@ bool TestOS_RNG()
member_ptr<RandomNumberGenerator> 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())