Crypto++  8.0
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 
23 NAMESPACE_BEGIN(CryptoPP)
24 
26  : m_pCipher(new AES::Encryption), m_keySet(false)
27 {
28  ::memset(m_key, 0, m_key.SizeInBytes());
29  ::memset(m_seed, 0, m_seed.SizeInBytes());
30 }
31 
32 void 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 
41 void 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 
48  CRYPTOPP_COMPILE_ASSERT(sizeof(TimerWord) <= 16);
49  CRYPTOPP_COMPILE_ASSERT(sizeof(time_t) <= 8);
50 
51  Timer timer;
52  TimerWord tw = timer.GetCurrentTimerValue();
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  ::memcpy(&tt1, m_seed.data()+8, 8);
61  ::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
80 
81 OldRandomPool::OldRandomPool(unsigned int poolSize)
82  : pool(poolSize), key(OldRandomPoolCipher::DEFAULT_KEYLENGTH), addPos(0), getPos(poolSize)
83 {
84  CRYPTOPP_ASSERT(poolSize > key.size());
85  ::memset(pool, 0, poolSize);
86  ::memset(key, 0, key.size());
87 }
88 
89 void 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 void OldRandomPool::Stir()
109 {
111 
112  for (int i=0; i<2; i++)
113  {
114  cipher.SetKeyWithIV(key, key.size(), pool.end()-cipher.IVSize());
115  cipher.ProcessString(pool, pool.size());
116  ::memcpy(key, pool, key.size());
117  }
118 
119  addPos = 0;
120  getPos = key.size();
121 }
122 
123 void OldRandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
124 {
125  while (size > 0)
126  {
127  if (getPos == pool.size())
128  Stir();
129  size_t t = UnsignedMin(pool.size() - getPos, size);
130  target.ChannelPut(channel, pool+getPos, t);
131  size -= t;
132  getPos += t;
133  }}
134 
136 {
137  if (getPos == pool.size())
138  Stir();
139 
140  return pool[getPos++];
141 }
142 
143 void OldRandomPool::GenerateBlock(byte *outString, size_t size)
144 {
145  ArraySink sink(outString, size);
147 }
148 
149 NAMESPACE_END
150 
151 #endif
void IncorporateEntropy(const byte *input, size_t length)
Update RNG state with additional unpredictable values.
Definition: randpool.cpp:32
iterator end()
Provides an iterator pointing beyond the last element in the memory block.
Definition: secblock.h:780
Randomness Pool based on AES-256.
Definition: randpool.h:41
high resolution timer
Definition: hrtimer.h:55
virtual void SetKey(const byte *key, size_t length, const NameValuePairs &params=g_nullNameValuePairs)
Sets or reset the key of this object.
Definition: cryptlib.cpp:58
SHA-256 message digest.
Definition: sha.h:64
Class file for Randomness Pool.
Classes for block cipher modes of operation.
size_t ChannelPut(const std::string &channel, byte inByte, bool blocking=true)
Input a byte for processing on a channel.
Definition: cryptlib.h:2106
MDC cipher.
Definition: mdc.h:32
void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
Generate random bytes into a BufferedTransformation.
Definition: randpool.cpp:123
void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
Generate random bytes into a BufferedTransformation.
Definition: randpool.cpp:41
void Update(const byte *input, size_t length)
Updates a hash with additional input.
Definition: iterhash.cpp:13
Interface for buffered transformations.
Definition: cryptlib.h:1598
Copy input to a memory buffer.
Definition: filters.h:1136
const std::string DEFAULT_CHANNEL
Default channel for BufferedTransformation.
Definition: cryptlib.h:482
Block cipher mode of operation aggregate.
Definition: modes.h:344
#define CRYPTOPP_COMPILE_ASSERT(expr)
Compile time assertion.
Definition: misc.h:116
A::pointer data()
Provides a pointer to the first element in the memory block.
Definition: secblock.h:789
Class file for the AES cipher (Rijndael)
Precompiled header file.
void ProcessBlock(const byte *inBlock, byte *outBlock) const
Encrypt or decrypt a block.
Definition: cryptlib.h:851
const T1 UnsignedMin(const T1 &a, const T2 &b)
Safe comparison of values that could be neagtive and incorrectly promoted.
Definition: misc.h:574
void IncorporateEntropy(const byte *input, size_t length)
Update RNG state with additional unpredictable values.
Definition: randpool.cpp:89
AES block cipher (Rijndael)
Definition: aes.h:23
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:69
OldRandomPool(unsigned int poolSize=384)
Construct an OldRandomPool.
Definition: randpool.cpp:81
Classes for SHA-1 and SHA-2 family of message digests.
byte GenerateByte()
Generate new random byte and return it.
Definition: randpool.cpp:135
Classes for the MDC message digest.
void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Definition: misc.cpp:32
Debugging and diagnostic assertions.
void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
Definition: randpool.cpp:143
Crypto++ library namespace.
virtual void Final(byte *digest)
Computes the hash of the current message.
Definition: cryptlib.h:1114
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:797