1 | // randpool.cpp - 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 <time.h> |
---|
16 | |
---|
17 | NAMESPACE_BEGIN(CryptoPP) |
---|
18 | |
---|
19 | RandomPool::RandomPool() |
---|
20 | : m_pCipher(new AES::Encryption), m_keySet(false) |
---|
21 | { |
---|
22 | memset(m_key, 0, m_key.SizeInBytes()); |
---|
23 | memset(m_seed, 0, m_seed.SizeInBytes()); |
---|
24 | } |
---|
25 | |
---|
26 | void RandomPool::IncorporateEntropy(const byte *input, size_t length) |
---|
27 | { |
---|
28 | SHA256 hash; |
---|
29 | hash.Update(m_key, 32); |
---|
30 | hash.Update(input, length); |
---|
31 | hash.Final(m_key); |
---|
32 | m_keySet = false; |
---|
33 | } |
---|
34 | |
---|
35 | void RandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size) |
---|
36 | { |
---|
37 | if (size > 0) |
---|
38 | { |
---|
39 | if (!m_keySet) |
---|
40 | m_pCipher->SetKey(m_key, 32); |
---|
41 | |
---|
42 | CRYPTOPP_COMPILE_ASSERT(sizeof(TimerWord) <= 16); |
---|
43 | CRYPTOPP_COMPILE_ASSERT(sizeof(time_t) <= 8); |
---|
44 | |
---|
45 | Timer timer; |
---|
46 | TimerWord tw = timer.GetCurrentTimerValue(); |
---|
47 | |
---|
48 | *(TimerWord *)(void*)m_seed.data() += tw; |
---|
49 | time_t t = time(NULL); |
---|
50 | |
---|
51 | // UBsan finding: signed integer overflow: 1876017710 + 1446085457 cannot be represented in type 'long int' |
---|
52 | // *(time_t *)(m_seed.data()+8) += t; |
---|
53 | word64 tt1 = 0, tt2 = (word64)t; |
---|
54 | memcpy(&tt1, m_seed.data()+8, 8); |
---|
55 | memcpy(m_seed.data()+8, &(tt2 += tt1), 8); |
---|
56 | |
---|
57 | // Wipe the intermediates |
---|
58 | *((volatile TimerWord*)&tw) = 0; |
---|
59 | *((volatile word64*)&tt1) = 0; |
---|
60 | *((volatile word64*)&tt2) = 0; |
---|
61 | |
---|
62 | do |
---|
63 | { |
---|
64 | m_pCipher->ProcessBlock(m_seed); |
---|
65 | size_t len = UnsignedMin(16, size); |
---|
66 | target.ChannelPut(channel, m_seed, len); |
---|
67 | size -= len; |
---|
68 | } while (size > 0); |
---|
69 | } |
---|
70 | } |
---|
71 | |
---|
72 | NAMESPACE_END |
---|
73 | |
---|
74 | #endif |
---|