Crypto++ 8.7
Free C++ class library of cryptographic schemes
randpool.cpp
1// randpool.cpp - originally written and placed in the public domain by Wei Dai
2// RandomPool used to follow the design of randpool in PGP 2.6.x,
3// but as of version 5.5 it has been redesigned to reduce the risk
4// of reusing random numbers after state rollback (which may occur
5// when running in a virtual machine like VMware).
6
7#include "pch.h"
8
9#ifndef CRYPTOPP_IMPORTS
10
11#include "randpool.h"
12#include "aes.h"
13#include "sha.h"
14#include "hrtimer.h"
15#include "trap.h"
16
17// OldRandomPool
18#include "mdc.h"
19#include "modes.h"
20
21#include <time.h>
22
23NAMESPACE_BEGIN(CryptoPP)
24
26 : m_pCipher(new AES::Encryption), m_keySet(false)
27{
28 std::memset(m_key, 0, m_key.SizeInBytes());
29 std::memset(m_seed, 0, m_seed.SizeInBytes());
30}
31
32void RandomPool::IncorporateEntropy(const byte *input, size_t length)
33{
34 SHA256 hash;
35 hash.Update(m_key, 32);
36 hash.Update(input, length);
37 hash.Final(m_key);
38 m_keySet = false;
39}
40
41void RandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
42{
43 if (size > 0)
44 {
45 if (!m_keySet)
46 m_pCipher->SetKey(m_key, 32);
47
49 CRYPTOPP_COMPILE_ASSERT(sizeof(time_t) <= 8);
50
51 Timer timer;
53
54 *(TimerWord *)(void*)m_seed.data() += tw;
55 time_t t = time(NULLPTR);
56
57 // UBsan finding: signed integer overflow: 1876017710 + 1446085457 cannot be represented in type 'long int'
58 // *(time_t *)(m_seed.data()+8) += t;
59 word64 tt1 = 0, tt2 = (word64)t;
60 std::memcpy(&tt1, m_seed.data()+8, 8);
61 std::memcpy(m_seed.data()+8, &(tt2 += tt1), 8);
62
63 // Wipe the intermediates
64 *((volatile TimerWord*)&tw) = 0;
65 *((volatile word64*)&tt1) = 0;
66 *((volatile word64*)&tt2) = 0;
67
68 do
69 {
70 m_pCipher->ProcessBlock(m_seed);
71 size_t len = UnsignedMin(16, size);
72 target.ChannelPut(channel, m_seed, len);
73 size -= len;
74 } while (size > 0);
75 }
76}
77
78// OldRandomPool is provided for backwards compatibility for a migration path
79typedef MDC<SHA1> OldRandomPoolCipher;
80
81OldRandomPool::OldRandomPool(unsigned int poolSize)
82 : pool(poolSize), key(OldRandomPoolCipher::DEFAULT_KEYLENGTH), addPos(0), getPos(poolSize)
83{
84 CRYPTOPP_ASSERT(poolSize > key.size());
85 std::memset(pool, 0, poolSize);
86 std::memset(key, 0, key.size());
87}
88
89void OldRandomPool::IncorporateEntropy(const byte *input, size_t length)
90{
91 size_t t;
92 while (length > (t = pool.size() - addPos))
93 {
94 xorbuf(pool+addPos, input, t);
95 input += t;
96 length -= t;
97 Stir();
98 }
99
100 if (length)
101 {
102 xorbuf(pool+addPos, input, length);
103 addPos += length;
104 getPos = pool.size(); // Force stir on get
105 }
106}
107
108// GenerateWord32 is overridden and provides Crypto++ 5.4 behavior.
109// Taken from RandomNumberGenerator::GenerateWord32 in cryptlib.cpp.
111{
112 const word32 range = max-min;
113 const unsigned int maxBytes = BytePrecision(range);
114 const unsigned int maxBits = BitPrecision(range);
115
116 word32 value;
117
118 do
119 {
120 value = 0;
121 for (unsigned int i=0; i<maxBytes; i++)
122 value = (value << 8) | GenerateByte();
123
124 value = Crop(value, maxBits);
125 } while (value > range);
126
127 return value+min;
128}
129
130void OldRandomPool::Stir()
131{
133
134 for (int i=0; i<2; i++)
135 {
136 cipher.SetKeyWithIV(key, key.size(), pool.end()-cipher.IVSize());
137 cipher.ProcessString(pool, pool.size());
138 std::memcpy(key, pool, key.size());
139 }
140
141 addPos = 0;
142 getPos = key.size();
143}
144
145void OldRandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
146{
147 while (size > 0)
148 {
149 if (getPos == pool.size())
150 Stir();
151 size_t t = UnsignedMin(pool.size() - getPos, size);
152 target.ChannelPut(channel, pool+getPos, t);
153 size -= t;
154 getPos += t;
155 }
156}
157
159{
160 if (getPos == pool.size())
161 Stir();
162
163 return pool[getPos++];
164}
165
166void OldRandomPool::GenerateBlock(byte *outString, size_t size)
167{
168 ArraySink sink(outString, size);
170}
171
172NAMESPACE_END
173
174#endif
Class file for the AES cipher (Rijndael)
AES block cipher (Rijndael)
Definition: aes.h:23
Copy input to a memory buffer.
Definition: filters.h:1200
void ProcessBlock(const byte *inBlock, byte *outBlock) const
Encrypt or decrypt a block.
Definition: cryptlib.h:879
Interface for buffered transformations.
Definition: cryptlib.h:1652
size_t ChannelPut(const std::string &channel, byte inByte, bool blocking=true)
Input a byte for processing on a channel.
Definition: cryptlib.h:2194
Block cipher mode of operation aggregate.
Definition: modes.h:347
virtual void Final(byte *digest)
Computes the hash of the current message.
Definition: cryptlib.h:1142
void Update(const byte *input, size_t length)
Updates a hash with additional input.
Definition: iterhash.cpp:13
MDC cipher.
Definition: mdc.h:33
void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
Generate random bytes into a BufferedTransformation.
word32 GenerateWord32(word32 min=0, word32 max=0xffffffffUL)
Generate a random 32 bit word in the range min to max, inclusive.
byte GenerateByte()
Generate new random byte and return it.
void IncorporateEntropy(const byte *input, size_t length)
Update RNG state with additional unpredictable values.
void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
OldRandomPool(unsigned int poolSize=384)
Construct an OldRandomPool.
RandomPool()
Construct a RandomPool.
void IncorporateEntropy(const byte *input, size_t length)
Update RNG state with additional unpredictable values.
void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
Generate random bytes into a BufferedTransformation.
SHA-256 message digest.
Definition: sha.h:65
iterator end()
Provides an iterator pointing beyond the last element in the memory block.
Definition: secblock.h:846
A::pointer data()
Provides a pointer to the first element in the memory block.
Definition: secblock.h:857
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:867
virtual void SetKey(const byte *key, size_t length, const NameValuePairs &params=g_nullNameValuePairs)
Sets or reset the key of this object.
High resolution timer.
Definition: hrtimer.h:122
TimerWord GetCurrentTimerValue()
Retrieve the current timer value.
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:62
unsigned long long word64
64-bit unsigned datatype
Definition: config_int.h:91
word64 lword
Large word type.
Definition: config_int.h:158
const std::string DEFAULT_CHANNEL
Default channel for BufferedTransformation.
Definition: cryptlib.h:511
Classes for timers.
word64 TimerWord
TimerWord is a 64-bit word.
Definition: hrtimer.h:19
Classes for the MDC message digest.
unsigned int BitPrecision(const T &value)
Returns the number of bits required for a value.
Definition: misc.h:842
unsigned int BytePrecision(const T &value)
Returns the number of 8-bit bytes or octets required for a value.
Definition: misc.h:819
T Crop(T value, size_t bits)
Truncates the value to the specified number of bits.
Definition: misc.h:926
#define CRYPTOPP_COMPILE_ASSERT(expr)
Compile time assertion.
Definition: misc.h:151
const T1 UnsignedMin(const T1 &a, const T2 &b)
Safe comparison of values that could be negative and incorrectly promoted.
Definition: misc.h:694
CRYPTOPP_DLL void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Classes for block cipher modes of operation.
Crypto++ library namespace.
Precompiled header file.
Class file for Randomness Pool.
Classes for SHA-1 and SHA-2 family of message digests.
Debugging and diagnostic assertions.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68