2017-01-27 12:05:45 +00:00
|
|
|
// randpool.cpp - originally written and placed in the public domain by Wei Dai
|
2015-11-05 06:59:46 +00:00
|
|
|
// 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"
|
2017-08-01 22:53:31 +00:00
|
|
|
#include "trap.h"
|
|
|
|
|
|
|
|
// OldRandomPool
|
|
|
|
#include "mdc.h"
|
|
|
|
#include "modes.h"
|
|
|
|
|
2017-09-20 22:10:07 +00:00
|
|
|
#include <time.h>
|
2015-11-05 06:59:46 +00:00
|
|
|
|
|
|
|
NAMESPACE_BEGIN(CryptoPP)
|
|
|
|
|
|
|
|
RandomPool::RandomPool()
|
|
|
|
: m_pCipher(new AES::Encryption), m_keySet(false)
|
|
|
|
{
|
2020-12-28 21:44:29 +00:00
|
|
|
std::memset(m_key, 0, m_key.SizeInBytes());
|
|
|
|
std::memset(m_seed, 0, m_seed.SizeInBytes());
|
2015-11-05 06:59:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2016-01-25 04:09:28 +00:00
|
|
|
CRYPTOPP_COMPILE_ASSERT(sizeof(TimerWord) <= 16);
|
|
|
|
CRYPTOPP_COMPILE_ASSERT(sizeof(time_t) <= 8);
|
|
|
|
|
2015-11-05 06:59:46 +00:00
|
|
|
Timer timer;
|
|
|
|
TimerWord tw = timer.GetCurrentTimerValue();
|
|
|
|
|
2016-01-25 04:09:28 +00:00
|
|
|
*(TimerWord *)(void*)m_seed.data() += tw;
|
2017-03-01 11:10:06 +00:00
|
|
|
time_t t = time(NULLPTR);
|
2016-09-10 08:57:48 +00:00
|
|
|
|
2015-11-05 06:59:46 +00:00
|
|
|
// UBsan finding: signed integer overflow: 1876017710 + 1446085457 cannot be represented in type 'long int'
|
|
|
|
// *(time_t *)(m_seed.data()+8) += t;
|
2016-01-25 04:09:28 +00:00
|
|
|
word64 tt1 = 0, tt2 = (word64)t;
|
2020-12-28 21:44:29 +00:00
|
|
|
std::memcpy(&tt1, m_seed.data()+8, 8);
|
|
|
|
std::memcpy(m_seed.data()+8, &(tt2 += tt1), 8);
|
2016-09-10 08:57:48 +00:00
|
|
|
|
2015-11-05 06:59:46 +00:00
|
|
|
// 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(16, size);
|
|
|
|
target.ChannelPut(channel, m_seed, len);
|
|
|
|
size -= len;
|
|
|
|
} while (size > 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-01 22:53:31 +00:00
|
|
|
// 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)
|
|
|
|
{
|
2017-08-02 00:42:55 +00:00
|
|
|
CRYPTOPP_ASSERT(poolSize > key.size());
|
2020-12-28 21:44:29 +00:00
|
|
|
std::memset(pool, 0, poolSize);
|
|
|
|
std::memset(key, 0, key.size());
|
2017-08-01 22:53:31 +00:00
|
|
|
}
|
|
|
|
|
2017-08-02 22:55:10 +00:00
|
|
|
void OldRandomPool::IncorporateEntropy(const byte *input, size_t length)
|
|
|
|
{
|
2017-08-02 23:43:56 +00:00
|
|
|
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
|
|
|
|
}
|
2017-08-02 22:55:10 +00:00
|
|
|
}
|
|
|
|
|
2022-01-04 10:06:35 +00:00
|
|
|
// GenerateWord32 is overridden and provides Crypto++ 5.4 behavior.
|
2021-06-17 21:55:45 +00:00
|
|
|
// Taken from RandomNumberGenerator::GenerateWord32 in cryptlib.cpp.
|
2021-06-17 21:23:18 +00:00
|
|
|
word32 OldRandomPool::GenerateWord32 (word32 min, word32 max)
|
2021-06-17 21:19:50 +00:00
|
|
|
{
|
|
|
|
const word32 range = max-min;
|
2021-06-17 21:51:52 +00:00
|
|
|
const unsigned int maxBytes = BytePrecision(range);
|
2021-06-17 21:19:50 +00:00
|
|
|
const unsigned int maxBits = BitPrecision(range);
|
|
|
|
|
|
|
|
word32 value;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2021-06-17 21:51:52 +00:00
|
|
|
value = 0;
|
2021-06-17 21:55:45 +00:00
|
|
|
for (unsigned int i=0; i<maxBytes; i++)
|
2021-06-17 21:51:52 +00:00
|
|
|
value = (value << 8) | GenerateByte();
|
|
|
|
|
2021-06-17 21:19:50 +00:00
|
|
|
value = Crop(value, maxBits);
|
|
|
|
} while (value > range);
|
|
|
|
|
|
|
|
return value+min;
|
|
|
|
}
|
|
|
|
|
2017-08-01 22:53:31 +00:00
|
|
|
void OldRandomPool::Stir()
|
|
|
|
{
|
2017-08-02 00:42:55 +00:00
|
|
|
CFB_Mode<OldRandomPoolCipher>::Encryption cipher;
|
2017-08-01 22:53:31 +00:00
|
|
|
|
2017-08-02 00:42:55 +00:00
|
|
|
for (int i=0; i<2; i++)
|
|
|
|
{
|
|
|
|
cipher.SetKeyWithIV(key, key.size(), pool.end()-cipher.IVSize());
|
|
|
|
cipher.ProcessString(pool, pool.size());
|
2020-12-28 21:44:29 +00:00
|
|
|
std::memcpy(key, pool, key.size());
|
2017-08-02 00:42:55 +00:00
|
|
|
}
|
2017-08-01 22:53:31 +00:00
|
|
|
|
2017-08-02 00:42:55 +00:00
|
|
|
addPos = 0;
|
|
|
|
getPos = key.size();
|
2017-08-01 22:53:31 +00:00
|
|
|
}
|
|
|
|
|
2017-08-02 23:43:56 +00:00
|
|
|
void OldRandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
|
2017-08-01 22:53:31 +00:00
|
|
|
{
|
2017-08-02 00:42:55 +00:00
|
|
|
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;
|
2020-12-28 21:44:29 +00:00
|
|
|
}
|
|
|
|
}
|
2017-08-01 22:53:31 +00:00
|
|
|
|
|
|
|
byte OldRandomPool::GenerateByte()
|
|
|
|
{
|
2017-08-02 00:42:55 +00:00
|
|
|
if (getPos == pool.size())
|
|
|
|
Stir();
|
2017-08-01 22:53:31 +00:00
|
|
|
|
2017-08-02 00:42:55 +00:00
|
|
|
return pool[getPos++];
|
2017-08-01 22:53:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OldRandomPool::GenerateBlock(byte *outString, size_t size)
|
|
|
|
{
|
2017-08-02 00:42:55 +00:00
|
|
|
ArraySink sink(outString, size);
|
2017-08-02 23:43:56 +00:00
|
|
|
GenerateIntoBufferedTransformation(sink, DEFAULT_CHANNEL, size);
|
2017-08-01 22:53:31 +00:00
|
|
|
}
|
|
|
|
|
2015-11-05 06:59:46 +00:00
|
|
|
NAMESPACE_END
|
|
|
|
|
|
|
|
#endif
|