randpool.cpp
// randpool.cpp - originally written and placed in the public domain by Wei Dai
// RandomPool used to follow the design of randpool in PGP 2.6.x,
// but as of version 5.5 it has been redesigned to reduce the risk
// of reusing random numbers after state rollback (which may occur
// when running in a virtual machine like VMware).
#include "pch.h"
#ifndef CRYPTOPP_IMPORTS
#include "randpool.h"
#include "aes.h"
#include "sha.h"
#include "hrtimer.h"
#include "trap.h"
// OldRandomPool
#include "mdc.h"
#include "modes.h"
#include <time.h>
NAMESPACE_BEGIN(CryptoPP)
RandomPool::RandomPool()
: m_pCipher(new AES::Encryption), m_keySet(false)
{
std::memset(m_key, 0, m_key.SizeInBytes());
std::memset(m_seed, 0, m_seed.SizeInBytes());
}
void RandomPool::IncorporateEntropy(const byte *input, size_t length)
{
SHA256 hash;
hash.Update(m_key, 32);
hash.Update(input, length);
hash.Final(m_key);
m_keySet = false;
}
void RandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
{
if (size > 0)
{
if (!m_keySet)
m_pCipher->SetKey(m_key, 32);
CRYPTOPP_COMPILE_ASSERT(sizeof(TimerWord) <= 16);
CRYPTOPP_COMPILE_ASSERT(sizeof(time_t) <= 8);
Timer timer;
TimerWord tw = timer.GetCurrentTimerValue();
*(TimerWord *)(void*)m_seed.data() += tw;
time_t t = time(NULLPTR);
// UBsan finding: signed integer overflow: 1876017710 + 1446085457 cannot be represented in type 'long int'
// *(time_t *)(m_seed.data()+8) += t;
word64 tt1 = 0, tt2 = (word64)t;
std::memcpy(&tt1, m_seed.data()+8, 8);
std::memcpy(m_seed.data()+8, &(tt2 += tt1), 8);
// Wipe the intermediates
*((volatile TimerWord*)&tw) = 0;
*((volatile word64*)&tt1) = 0;
*((volatile word64*)&tt2) = 0;
do
{
m_pCipher->ProcessBlock(m_seed);
size_t len = UnsignedMin(16u, size);
target.ChannelPut(channel, m_seed, len);
size -= len;
} while (size > 0);
}
}
// OldRandomPool is provided for backwards compatibility for a migration path
typedef MDC<SHA1> OldRandomPoolCipher;
OldRandomPool::OldRandomPool(unsigned int poolSize)
: pool(poolSize), key(OldRandomPoolCipher::DEFAULT_KEYLENGTH), addPos(0), getPos(poolSize)
{
CRYPTOPP_ASSERT(poolSize > key.size());
std::memset(pool, 0, poolSize);
std::memset(key, 0, key.size());
}
void OldRandomPool::IncorporateEntropy(const byte *input, size_t length)
{
size_t t;
while (length > (t = pool.size() - addPos))
{
xorbuf(pool+addPos, input, t);
input += t;
length -= t;
Stir();
}
if (length)
{
xorbuf(pool+addPos, input, length);
addPos += length;
getPos = pool.size(); // Force stir on get
}
}
// GenerateWord32 is overridden and provides Crypto++ 5.4 behavior.
// Taken from RandomNumberGenerator::GenerateWord32 in cryptlib.cpp.
word32 OldRandomPool::GenerateWord32 (word32 min, word32 max)
{
const word32 range = max-min;
const unsigned int maxBytes = BytePrecision(range);
const unsigned int maxBits = BitPrecision(range);
word32 value;
do
{
value = 0;
for (unsigned int i=0; i<maxBytes; i++)
value = (value << 8) | GenerateByte();
value = Crop(value, maxBits);
} while (value > range);
return value+min;
}
void OldRandomPool::Stir()
{
CFB_Mode<OldRandomPoolCipher>::Encryption cipher;
for (int i=0; i<2; i++)
{
cipher.SetKeyWithIV(key, key.size(), pool.end()-cipher.IVSize());
cipher.ProcessString(pool, pool.size());
std::memcpy(key, pool, key.size());
}
addPos = 0;
getPos = key.size();
}
void OldRandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
{
while (size > 0)
{
if (getPos == pool.size())
Stir();
size_t t = UnsignedMin(pool.size() - getPos, size);
target.ChannelPut(channel, pool+getPos, t);
size -= t;
getPos += t;
}
}
byte OldRandomPool::GenerateByte()
{
if (getPos == pool.size())
Stir();
return pool[getPos++];
}
void OldRandomPool::GenerateBlock(byte *outString, size_t size)
{
ArraySink sink(outString, size);
GenerateIntoBufferedTransformation(sink, DEFAULT_CHANNEL, size);
}
NAMESPACE_END
#endif
aes.h
Class file for the AES cipher (Rijndael).
AES
AES block cipher (Rijndael).
Definition aes.h:23
BufferedTransformation
Interface for buffered transformations.
Definition cryptlib.h:1657
BufferedTransformation::ChannelPut
size_t ChannelPut(const std::string &channel, byte inByte, bool blocking=true)
Input a byte for processing on a channel.
Definition cryptlib.h:2199
HashTransformation::Final
virtual void Final(byte *digest)
Computes the hash of the current message.
Definition cryptlib.h:1147
IteratedHashBase::Update
void Update(const byte *input, size_t length)
Updates a hash with additional input.
Definition iterhash.cpp:13
MDC
MDC cipher.
Definition mdc.h:33
OldRandomPool::GenerateIntoBufferedTransformation
void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
Generate random bytes into a BufferedTransformation.
OldRandomPool::GenerateWord32
word32 GenerateWord32(word32 min=0, word32 max=0xffffffffUL)
Generate a random 32 bit word in the range min to max, inclusive.
OldRandomPool::GenerateByte
byte GenerateByte()
Generate new random byte and return it.
OldRandomPool::IncorporateEntropy
void IncorporateEntropy(const byte *input, size_t length)
Update RNG state with additional unpredictable values.
OldRandomPool::GenerateBlock
void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
OldRandomPool::OldRandomPool
OldRandomPool(unsigned int poolSize=384)
Construct an OldRandomPool.
RandomPool::RandomPool
RandomPool()
Construct a RandomPool.
RandomPool::IncorporateEntropy
void IncorporateEntropy(const byte *input, size_t length)
Update RNG state with additional unpredictable values.
RandomPool::GenerateIntoBufferedTransformation
void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
Generate random bytes into a BufferedTransformation.
Timer::GetCurrentTimerValue
TimerWord GetCurrentTimerValue()
Retrieve the current timer value.
word32
unsigned int word32
32-bit unsigned datatype
Definition config_int.h:72
word64
unsigned long long word64
64-bit unsigned datatype
Definition config_int.h:101
lword
word64 lword
Large word type.
Definition config_int.h:168
DEFAULT_CHANNEL
const std::string DEFAULT_CHANNEL
Default channel for BufferedTransformation.
Definition cryptlib.h:516
hrtimer.h
Classes for timers.
TimerWord
word64 TimerWord
TimerWord is a 64-bit word.
Definition hrtimer.h:19
mdc.h
Classes for the MDC message digest.
BitPrecision
unsigned int BitPrecision(const T &value)
Returns the number of bits required for a value.
Definition misc.h:1047
BytePrecision
unsigned int BytePrecision(const T &value)
Returns the number of 8-bit bytes or octets required for a value.
Definition misc.h:1024
Crop
T Crop(T value, size_t bits)
Truncates the value to the specified number of bits.
Definition misc.h:1131
CRYPTOPP_COMPILE_ASSERT
#define CRYPTOPP_COMPILE_ASSERT(expr)
Compile time assertion.
Definition misc.h:153
UnsignedMin
const T1 UnsignedMin(const T1 &a, const T2 &b)
Safe comparison of values that could be negative and incorrectly promoted.
Definition misc.h:695
xorbuf
CRYPTOPP_DLL void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
modes.h
Classes for block cipher modes of operation.
CryptoPP
Crypto++ library namespace.
pch.h
Precompiled header file.
randpool.h
Class file for Randomness Pool.
sha.h
Classes for SHA-1 and SHA-2 family of message digests.
SymmetricCipherDocumentation::Encryption
SymmetricCipher Encryption
implements the SymmetricCipher interface
Definition seckey.h:416
trap.h
Debugging and diagnostic assertions.
CRYPTOPP_ASSERT
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition trap.h:68