~zooko/cryptopp/trunk

« back to all changes in this revision

Viewing changes to randpool.cpp

  • Committer: noloader
  • Date: 2015-06-29 13:37:03 UTC
  • Revision ID: svn-v4:57ff6487-cd31-0410-9ec3-f628ee90f5f0:trunk/c5:558
Cleared warning on operator precedence

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
// randpool.cpp - written and placed in the public domain by Wei Dai
2
 
// The algorithm in this module comes from PGP's randpool.c
 
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).
3
6
 
4
7
#include "pch.h"
5
8
 
6
9
#ifndef CRYPTOPP_IMPORTS
7
10
 
8
11
#include "randpool.h"
9
 
#include "mdc.h"
 
12
#include "aes.h"
10
13
#include "sha.h"
11
 
#include "modes.h"
 
14
#include "hrtimer.h"
 
15
#include <time.h>
 
16
 
 
17
#if GCC_DIAGNOSTIC_AWARE
 
18
# pragma GCC diagnostic ignored "-Wunused-value"
 
19
# pragma GCC diagnostic ignored "-Wunused-variable"
 
20
#endif
12
21
 
13
22
NAMESPACE_BEGIN(CryptoPP)
14
23
 
15
 
typedef MDC<SHA> RandomPoolCipher;
16
 
 
17
 
RandomPool::RandomPool(unsigned int poolSize)
18
 
        : pool(poolSize), key(RandomPoolCipher::DEFAULT_KEYLENGTH)
19
 
{
20
 
        assert(poolSize > key.size());
21
 
 
22
 
        addPos=0;
23
 
        getPos=poolSize;
24
 
        memset(pool, 0, poolSize);
25
 
        memset(key, 0, key.size());
26
 
}
27
 
 
28
 
void RandomPool::Stir()
29
 
{
30
 
        CFB_Mode<RandomPoolCipher>::Encryption cipher;
31
 
 
32
 
        for (int i=0; i<2; i++)
33
 
        {
34
 
                cipher.SetKeyWithIV(key, key.size(), pool.end()-cipher.IVSize());
35
 
                cipher.ProcessString(pool, pool.size());
36
 
                memcpy(key, pool, key.size());
37
 
        }
38
 
 
39
 
        addPos = 0;
40
 
        getPos = key.size();
41
 
}
42
 
 
43
 
size_t RandomPool::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
44
 
{
45
 
        size_t t;
46
 
 
47
 
        while (length > (t = pool.size() - addPos))
48
 
        {
49
 
                xorbuf(pool+addPos, inString, t);
50
 
                inString += t;
51
 
                length -= t;
52
 
                Stir();
53
 
        }
54
 
 
55
 
        if (length)
56
 
        {
57
 
                xorbuf(pool+addPos, inString, length);
58
 
                addPos += length;
59
 
                getPos = pool.size(); // Force stir on get
60
 
        }
61
 
 
62
 
        return 0;
63
 
}
64
 
 
65
 
size_t RandomPool::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
66
 
{
67
 
        if (!blocking)
68
 
                throw NotImplemented("RandomPool: nonblocking transfer is not implemented by this object");
69
 
 
70
 
        lword size = transferBytes;
71
 
 
72
 
        while (size > 0)
73
 
        {
74
 
                if (getPos == pool.size())
75
 
                        Stir();
76
 
                size_t t = UnsignedMin(pool.size() - getPos, size);
77
 
                target.ChannelPut(channel, pool+getPos, t);
78
 
                size -= t;
79
 
                getPos += t;
80
 
        }
81
 
 
82
 
        return 0;
83
 
}
84
 
 
85
 
byte RandomPool::GenerateByte()
86
 
{
87
 
        if (getPos == pool.size())
88
 
                Stir();
89
 
 
90
 
        return pool[getPos++];
91
 
}
92
 
 
93
 
void RandomPool::GenerateBlock(byte *outString, size_t size)
94
 
{
95
 
        ArraySink sink(outString, size);
96
 
        TransferTo(sink, size);
 
24
RandomPool::RandomPool()
 
25
        : m_pCipher(new AES::Encryption), m_keySet(false)
 
26
{
 
27
        memset(m_key, 0, m_key.SizeInBytes());
 
28
        memset(m_seed, 0, m_seed.SizeInBytes());
 
29
}
 
30
 
 
31
void RandomPool::IncorporateEntropy(const byte *input, size_t length)
 
32
{
 
33
        SHA256 hash;
 
34
        hash.Update(m_key, 32);
 
35
        hash.Update(input, length);
 
36
        hash.Final(m_key);
 
37
        m_keySet = false;
 
38
}
 
39
 
 
40
void RandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
 
41
{
 
42
        if (size > 0)
 
43
        {
 
44
                if (!m_keySet)
 
45
                        m_pCipher->SetKey(m_key, 32);
 
46
 
 
47
                Timer timer;
 
48
                TimerWord tw = timer.GetCurrentTimerValue();
 
49
                CRYPTOPP_COMPILE_ASSERT(sizeof(tw) <= 16);
 
50
                *(TimerWord *)m_seed.data() += tw;
 
51
 
 
52
                time_t t = time(NULL);
 
53
                CRYPTOPP_COMPILE_ASSERT(sizeof(t) <= 8);
 
54
                *(time_t *)(m_seed.data()+8) += t;
 
55
 
 
56
                do
 
57
                {
 
58
                        m_pCipher->ProcessBlock(m_seed);
 
59
                        size_t len = UnsignedMin(16, size);
 
60
                        target.ChannelPut(channel, m_seed, len);
 
61
                        size -= len;
 
62
                } while (size > 0);
 
63
        }
97
64
}
98
65
 
99
66
NAMESPACE_END