reduce risk of random number reuse after VM rollback
parent
c09618a557
commit
f9261eb107
76
hrtimer.cpp
76
hrtimer.cpp
|
|
@ -4,7 +4,6 @@
|
||||||
#include "hrtimer.h"
|
#include "hrtimer.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include <stddef.h> // for NULL
|
#include <stddef.h> // for NULL
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
@ -18,6 +17,8 @@
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
NAMESPACE_BEGIN(CryptoPP)
|
||||||
|
|
||||||
|
#ifndef CRYPTOPP_IMPORTS
|
||||||
|
|
||||||
double TimerBase::ConvertTo(TimerWord t, Unit unit)
|
double TimerBase::ConvertTo(TimerWord t, Unit unit)
|
||||||
{
|
{
|
||||||
static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000};
|
static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000};
|
||||||
|
|
@ -56,6 +57,46 @@ unsigned long TimerBase::ElapsedTime()
|
||||||
return (unsigned long)elapsed;
|
return (unsigned long)elapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimerWord Timer::GetCurrentTimerValue()
|
||||||
|
{
|
||||||
|
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
||||||
|
LARGE_INTEGER now;
|
||||||
|
if (!QueryPerformanceCounter(&now))
|
||||||
|
throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceCounter failed with error " + IntToString(GetLastError()));
|
||||||
|
return now.QuadPart;
|
||||||
|
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
||||||
|
timeval now;
|
||||||
|
gettimeofday(&now, NULL);
|
||||||
|
return (TimerWord)now.tv_sec * 1000000 + now.tv_usec;
|
||||||
|
#else
|
||||||
|
clock_t now;
|
||||||
|
return clock();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TimerWord Timer::TicksPerSecond()
|
||||||
|
{
|
||||||
|
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
||||||
|
static LARGE_INTEGER freq = {0};
|
||||||
|
if (freq.QuadPart == 0)
|
||||||
|
{
|
||||||
|
if (!QueryPerformanceFrequency(&freq))
|
||||||
|
throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError()));
|
||||||
|
}
|
||||||
|
return freq.QuadPart;
|
||||||
|
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
||||||
|
return 1000000;
|
||||||
|
#elif defined(CLOCKS_PER_SEC)
|
||||||
|
return CLOCKS_PER_SEC;
|
||||||
|
#elif defined(CLK_TCK)
|
||||||
|
return CLK_TCK;
|
||||||
|
#else
|
||||||
|
return 1000000;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // #ifndef CRYPTOPP_IMPORTS
|
||||||
|
|
||||||
TimerWord ThreadUserTimer::GetCurrentTimerValue()
|
TimerWord ThreadUserTimer::GetCurrentTimerValue()
|
||||||
{
|
{
|
||||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
||||||
|
|
@ -98,37 +139,4 @@ TimerWord ThreadUserTimer::TicksPerSecond()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HIGHRES_TIMER_AVAILABLE
|
|
||||||
|
|
||||||
TimerWord Timer::GetCurrentTimerValue()
|
|
||||||
{
|
|
||||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
|
||||||
LARGE_INTEGER now;
|
|
||||||
if (!QueryPerformanceCounter(&now))
|
|
||||||
throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceCounter failed with error " + IntToString(GetLastError()));
|
|
||||||
return now.QuadPart;
|
|
||||||
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
|
||||||
timeval now;
|
|
||||||
gettimeofday(&now, NULL);
|
|
||||||
return (TimerWord)now.tv_sec * 1000000 + now.tv_usec;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
TimerWord Timer::TicksPerSecond()
|
|
||||||
{
|
|
||||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
|
||||||
static LARGE_INTEGER freq = {0};
|
|
||||||
if (freq.QuadPart == 0)
|
|
||||||
{
|
|
||||||
if (!QueryPerformanceFrequency(&freq))
|
|
||||||
throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError()));
|
|
||||||
}
|
|
||||||
return freq.QuadPart;
|
|
||||||
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
|
||||||
return 1000000;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // HIGHRES_TIMER_AVAILABLE
|
|
||||||
|
|
||||||
NAMESPACE_END
|
NAMESPACE_END
|
||||||
|
|
|
||||||
17
hrtimer.h
17
hrtimer.h
|
|
@ -5,14 +5,19 @@
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
NAMESPACE_BEGIN(CryptoPP)
|
||||||
|
|
||||||
#ifdef WORD64_AVAILABLE
|
#ifdef HIGHRES_TIMER_AVAILABLE
|
||||||
|
#ifdef WORD64_AVAILABLE
|
||||||
typedef word64 TimerWord;
|
typedef word64 TimerWord;
|
||||||
#else
|
#else
|
||||||
typedef word32 TimerWord;
|
typedef word32 TimerWord;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#include <time.h>
|
||||||
|
typedef clock_t TimerWord;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//! _
|
//! _
|
||||||
class TimerBase
|
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TimerBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Unit {SECONDS = 0, MILLISECONDS, MICROSECONDS, NANOSECONDS};
|
enum Unit {SECONDS = 0, MILLISECONDS, MICROSECONDS, NANOSECONDS};
|
||||||
|
|
@ -44,10 +49,8 @@ public:
|
||||||
TimerWord TicksPerSecond();
|
TimerWord TicksPerSecond();
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HIGHRES_TIMER_AVAILABLE
|
|
||||||
|
|
||||||
//! high resolution timer
|
//! high resolution timer
|
||||||
class Timer : public TimerBase
|
class CRYPTOPP_DLL Timer : public TimerBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Timer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false) : TimerBase(unit, stuckAtZero) {}
|
Timer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false) : TimerBase(unit, stuckAtZero) {}
|
||||||
|
|
@ -55,8 +58,6 @@ public:
|
||||||
TimerWord TicksPerSecond();
|
TimerWord TicksPerSecond();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HIGHRES_TIMER_AVAILABLE
|
|
||||||
|
|
||||||
NAMESPACE_END
|
NAMESPACE_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
16
osrng.cpp
16
osrng.cpp
|
|
@ -74,13 +74,6 @@ NonblockingRng::~NonblockingRng()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
byte NonblockingRng::GenerateByte()
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
GenerateBlock(&b, 1);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NonblockingRng::GenerateBlock(byte *output, size_t size)
|
void NonblockingRng::GenerateBlock(byte *output, size_t size)
|
||||||
{
|
{
|
||||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||||
|
|
@ -121,13 +114,6 @@ BlockingRng::~BlockingRng()
|
||||||
close(m_fd);
|
close(m_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte BlockingRng::GenerateByte()
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
GenerateBlock(&b, 1);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockingRng::GenerateBlock(byte *output, size_t size)
|
void BlockingRng::GenerateBlock(byte *output, size_t size)
|
||||||
{
|
{
|
||||||
while (size)
|
while (size)
|
||||||
|
|
@ -175,7 +161,7 @@ void AutoSeededRandomPool::Reseed(bool blocking, unsigned int seedSize)
|
||||||
{
|
{
|
||||||
SecByteBlock seed(seedSize);
|
SecByteBlock seed(seedSize);
|
||||||
OS_GenerateRandomBlock(blocking, seed, seedSize);
|
OS_GenerateRandomBlock(blocking, seed, seedSize);
|
||||||
Put(seed, seedSize);
|
IncorporateEntropy(seed, seedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
NAMESPACE_END
|
NAMESPACE_END
|
||||||
|
|
|
||||||
54
osrng.h
54
osrng.h
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#include "randpool.h"
|
#include "randpool.h"
|
||||||
#include "rng.h"
|
#include "rng.h"
|
||||||
#include "des.h"
|
#include "aes.h"
|
||||||
#include "fips140.h"
|
#include "fips140.h"
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
NAMESPACE_BEGIN(CryptoPP)
|
||||||
|
|
@ -46,7 +46,6 @@ class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator
|
||||||
public:
|
public:
|
||||||
NonblockingRng();
|
NonblockingRng();
|
||||||
~NonblockingRng();
|
~NonblockingRng();
|
||||||
byte GenerateByte();
|
|
||||||
void GenerateBlock(byte *output, size_t size);
|
void GenerateBlock(byte *output, size_t size);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -69,7 +68,6 @@ class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator
|
||||||
public:
|
public:
|
||||||
BlockingRng();
|
BlockingRng();
|
||||||
~BlockingRng();
|
~BlockingRng();
|
||||||
byte GenerateByte();
|
|
||||||
void GenerateBlock(byte *output, size_t size);
|
void GenerateBlock(byte *output, size_t size);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -99,39 +97,39 @@ public:
|
||||||
//! use blocking to choose seeding with BlockingRng or NonblockingRng. the parameter is ignored if only one of these is available
|
//! use blocking to choose seeding with BlockingRng or NonblockingRng. the parameter is ignored if only one of these is available
|
||||||
explicit AutoSeededX917RNG(bool blocking = false)
|
explicit AutoSeededX917RNG(bool blocking = false)
|
||||||
{Reseed(blocking);}
|
{Reseed(blocking);}
|
||||||
void Reseed(bool blocking = false);
|
void Reseed(bool blocking = false, const byte *additionalEntropy = NULL, size_t length = 0);
|
||||||
// exposed for testing
|
// exposed for testing
|
||||||
void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector);
|
void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector);
|
||||||
|
|
||||||
byte GenerateByte();
|
bool CanIncorporateEntropy() const {return true;}
|
||||||
|
void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);}
|
||||||
|
void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length) {m_rng->GenerateIntoBufferedTransformation(target, channel, length);}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
member_ptr<RandomNumberGenerator> m_rng;
|
member_ptr<RandomNumberGenerator> m_rng;
|
||||||
SecByteBlock m_lastBlock;
|
|
||||||
bool m_isDifferent;
|
|
||||||
unsigned int m_counter;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class BLOCK_CIPHER>
|
template <class BLOCK_CIPHER>
|
||||||
void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector)
|
void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector)
|
||||||
{
|
{
|
||||||
m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector));
|
m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector));
|
||||||
|
|
||||||
// for FIPS 140-2
|
|
||||||
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, const byte *input, size_t length)
|
||||||
{
|
{
|
||||||
SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH);
|
SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH);
|
||||||
const byte *key;
|
const byte *key;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
OS_GenerateRandomBlock(blocking, seed, seed.size());
|
OS_GenerateRandomBlock(blocking, seed, seed.size());
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
SHA256 hash;
|
||||||
|
hash.Update(seed, seed.size());
|
||||||
|
hash.Update(input, length);
|
||||||
|
hash.TruncatedFinal(seed, UnsignedMin(hash.DigestSize(), seed.size()));
|
||||||
|
}
|
||||||
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);
|
||||||
|
|
@ -139,27 +137,13 @@ void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking)
|
||||||
Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, NULL);
|
Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class BLOCK_CIPHER>
|
CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG<AES>;
|
||||||
byte AutoSeededX917RNG<BLOCK_CIPHER>::GenerateByte()
|
|
||||||
{
|
|
||||||
byte b = m_rng->GenerateByte();
|
|
||||||
|
|
||||||
// for FIPS 140-2
|
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
||||||
m_isDifferent = m_isDifferent || b != m_lastBlock[m_counter];
|
typedef AutoSeededX917RNG<AES> DefaultAutoSeededRNG;
|
||||||
m_lastBlock[m_counter] = b;
|
#else
|
||||||
++m_counter;
|
typedef AutoSeededRandomPool DefaultAutoSeededRNG;
|
||||||
if (m_counter == m_lastBlock.size())
|
#endif
|
||||||
{
|
|
||||||
if (!m_isDifferent)
|
|
||||||
throw SelfTestFailure("AutoSeededX917RNG: Continuous random number generator test failed.");
|
|
||||||
m_counter = 0;
|
|
||||||
m_isDifferent = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG<DES_EDE3>;
|
|
||||||
|
|
||||||
NAMESPACE_END
|
NAMESPACE_END
|
||||||
|
|
||||||
|
|
|
||||||
44
rng.cpp
44
rng.cpp
|
|
@ -3,6 +3,7 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
#include "rng.h"
|
#include "rng.h"
|
||||||
|
#include "fips140.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
@ -35,8 +36,10 @@ const word16 LC_RNG::a=16807;
|
||||||
const word16 LC_RNG::r=2836;
|
const word16 LC_RNG::r=2836;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
byte LC_RNG::GenerateByte()
|
void LC_RNG::GenerateBlock(byte *output, size_t size)
|
||||||
{
|
{
|
||||||
|
while (size--)
|
||||||
|
{
|
||||||
word32 hi = seed/q;
|
word32 hi = seed/q;
|
||||||
word32 lo = seed%q;
|
word32 lo = seed%q;
|
||||||
|
|
||||||
|
|
@ -47,7 +50,8 @@ byte LC_RNG::GenerateByte()
|
||||||
else
|
else
|
||||||
seed = test+ m;
|
seed = test+ m;
|
||||||
|
|
||||||
return (GETBYTE(seed, 0) ^ GETBYTE(seed, 1) ^ GETBYTE(seed, 2) ^ GETBYTE(seed, 3));
|
*output++ = (GETBYTE(seed, 0) ^ GETBYTE(seed, 1) ^ GETBYTE(seed, 2) ^ GETBYTE(seed, 3));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ********************************************************
|
// ********************************************************
|
||||||
|
|
@ -59,24 +63,26 @@ X917RNG::X917RNG(BlockTransformation *c, const byte *seed, const byte *determini
|
||||||
S(cipher->BlockSize()),
|
S(cipher->BlockSize()),
|
||||||
dtbuf(S),
|
dtbuf(S),
|
||||||
randseed(seed, S),
|
randseed(seed, S),
|
||||||
randbuf(S),
|
m_lastBlock(S),
|
||||||
randbuf_counter(0),
|
|
||||||
m_deterministicTimeVector(deterministicTimeVector, deterministicTimeVector ? S : 0)
|
m_deterministicTimeVector(deterministicTimeVector, deterministicTimeVector ? S : 0)
|
||||||
{
|
{
|
||||||
if (!deterministicTimeVector)
|
if (!deterministicTimeVector)
|
||||||
{
|
{
|
||||||
time_t tstamp1 = time(0);
|
time_t tstamp1 = time(0);
|
||||||
xorbuf(dtbuf, (byte *)&tstamp1, STDMIN((int)sizeof(tstamp1), S));
|
xorbuf(dtbuf, (byte *)&tstamp1, UnsignedMin(sizeof(tstamp1), S));
|
||||||
cipher->ProcessBlock(dtbuf);
|
cipher->ProcessBlock(dtbuf);
|
||||||
clock_t tstamp2 = clock();
|
clock_t tstamp2 = clock();
|
||||||
xorbuf(dtbuf, (byte *)&tstamp2, STDMIN((int)sizeof(tstamp2), S));
|
xorbuf(dtbuf, (byte *)&tstamp2, UnsignedMin(sizeof(tstamp2), S));
|
||||||
cipher->ProcessBlock(dtbuf);
|
cipher->ProcessBlock(dtbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for FIPS 140-2
|
||||||
|
GenerateBlock(m_lastBlock, S);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte X917RNG::GenerateByte()
|
void X917RNG::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
|
||||||
{
|
{
|
||||||
if (randbuf_counter==0)
|
while (size > 0)
|
||||||
{
|
{
|
||||||
// calculate new enciphered timestamp
|
// calculate new enciphered timestamp
|
||||||
if (m_deterministicTimeVector.size())
|
if (m_deterministicTimeVector.size())
|
||||||
|
|
@ -86,8 +92,10 @@ byte X917RNG::GenerateByte()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clock_t tstamp = clock();
|
clock_t c = clock();
|
||||||
xorbuf(dtbuf, (byte *)&tstamp, STDMIN((int)sizeof(tstamp), S));
|
xorbuf(dtbuf, (byte *)&c, UnsignedMin(sizeof(c), S));
|
||||||
|
time_t t = time(NULL);
|
||||||
|
xorbuf(dtbuf+S-UnsignedMin(sizeof(t), S), (byte *)&t, UnsignedMin(sizeof(t), S));
|
||||||
cipher->ProcessBlock(dtbuf);
|
cipher->ProcessBlock(dtbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,16 +103,20 @@ byte X917RNG::GenerateByte()
|
||||||
xorbuf(randseed, dtbuf, S);
|
xorbuf(randseed, dtbuf, S);
|
||||||
|
|
||||||
// generate a new block of random bytes
|
// generate a new block of random bytes
|
||||||
cipher->ProcessBlock(randseed, randbuf);
|
cipher->ProcessBlock(randseed);
|
||||||
|
if (memcmp(m_lastBlock, randseed, S) == 0)
|
||||||
|
throw SelfTestFailure("X917RNG: Continuous random number generator test failed.");
|
||||||
|
|
||||||
|
// output random bytes
|
||||||
|
size_t len = UnsignedMin(size, S);
|
||||||
|
target.ChannelPut(channel, randseed, len);
|
||||||
|
size -= len;
|
||||||
|
|
||||||
// compute new seed vector
|
// compute new seed vector
|
||||||
for (int i=0; i<S; i++)
|
memcpy(m_lastBlock, randseed, S);
|
||||||
randseed[i] = randbuf[i] ^ dtbuf[i];
|
xorbuf(randseed, dtbuf, S);
|
||||||
cipher->ProcessBlock(randseed);
|
cipher->ProcessBlock(randseed);
|
||||||
|
|
||||||
randbuf_counter=S;
|
|
||||||
}
|
}
|
||||||
return(randbuf[S-randbuf_counter--]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
9
rng.h
9
rng.h
|
|
@ -16,7 +16,7 @@ public:
|
||||||
LC_RNG(word32 init_seed)
|
LC_RNG(word32 init_seed)
|
||||||
: seed(init_seed) {}
|
: seed(init_seed) {}
|
||||||
|
|
||||||
byte GenerateByte();
|
void GenerateBlock(byte *output, size_t size);
|
||||||
|
|
||||||
word32 GetSeed() {return seed;}
|
word32 GetSeed() {return seed;}
|
||||||
|
|
||||||
|
|
@ -37,14 +37,13 @@ public:
|
||||||
// cipher will be deleted by destructor, deterministicTimeVector = 0 means obtain time vector from system
|
// cipher will be deleted by destructor, deterministicTimeVector = 0 means obtain time vector from system
|
||||||
X917RNG(BlockTransformation *cipher, const byte *seed, const byte *deterministicTimeVector = 0);
|
X917RNG(BlockTransformation *cipher, const byte *seed, const byte *deterministicTimeVector = 0);
|
||||||
|
|
||||||
byte GenerateByte();
|
void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
member_ptr<BlockTransformation> cipher;
|
member_ptr<BlockTransformation> cipher;
|
||||||
const int S; // blocksize of cipher
|
unsigned int S; // blocksize of cipher
|
||||||
SecByteBlock dtbuf; // buffer for enciphered timestamp
|
SecByteBlock dtbuf; // buffer for enciphered timestamp
|
||||||
SecByteBlock randseed, randbuf, m_deterministicTimeVector;
|
SecByteBlock randseed, m_lastBlock, m_deterministicTimeVector;
|
||||||
int randbuf_counter; // # of unused bytes left in randbuf
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** This class implements Maurer's Universal Statistical Test for Random Bit Generators
|
/** This class implements Maurer's Universal Statistical Test for Random Bit Generators
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue