source: trunk/src-cryptopp/rng.cpp

Last change on this file was e230cb0, checked in by David Stainton <dstainton415@…>, at 2016-10-12T13:27:29Z

Add cryptopp from tag CRYPTOPP_5_6_5

  • Property mode set to 100644
File size: 4.3 KB
Line 
1// rng.cpp - written and placed in the public domain by Wei Dai
2
3#include "pch.h"
4
5#include "rng.h"
6#include "fips140.h"
7
8#include <time.h>
9#include <math.h>
10
11NAMESPACE_BEGIN(CryptoPP)
12
13// linear congruential generator
14// originally by William S. England
15
16// do not use for cryptographic purposes
17
18/*
19** Original_numbers are the original published m and q in the
20** ACM article above.  John Burton has furnished numbers for
21** a reportedly better generator.  The new numbers are now
22** used in this program by default.
23*/
24
25#ifndef LCRNG_ORIGINAL_NUMBERS
26const word32 LC_RNG::m=2147483647L;
27const word32 LC_RNG::q=44488L;
28
29const word16 LC_RNG::a=(unsigned int)48271L;
30const word16 LC_RNG::r=3399;
31#else
32const word32 LC_RNG::m=2147483647L;
33const word32 LC_RNG::q=127773L;
34
35const word16 LC_RNG::a=16807;
36const word16 LC_RNG::r=2836;
37#endif
38
39void LC_RNG::GenerateBlock(byte *output, size_t size)
40{
41        while (size--)
42        {
43                word32 hi = seed/q;
44                word32 lo = seed%q;
45
46                long test = a*lo - r*hi;
47
48                if (test > 0)
49                        seed = test;
50                else
51                        seed = test+ m;
52
53                *output++ = byte((GETBYTE(seed, 0) ^ GETBYTE(seed, 1) ^ GETBYTE(seed, 2) ^ GETBYTE(seed, 3)));
54        }
55}
56
57// ********************************************************
58
59#ifndef CRYPTOPP_IMPORTS
60
61X917RNG::X917RNG(BlockTransformation *c, const byte *seed, const byte *deterministicTimeVector)
62        : m_cipher(c),
63          m_size(m_cipher->BlockSize()),
64          m_datetime(m_size),
65          m_randseed(seed, m_size),
66          m_lastBlock(m_size),
67          m_deterministicTimeVector(deterministicTimeVector, deterministicTimeVector ? m_size : 0)
68{
69        // Valgrind finding, http://github.com/weidai11/cryptopp/issues/105
70        // Garbage in the tail creates a non-conforming X9.17 or X9.31 generator.
71        if (m_size > 8)
72        {
73                memset(m_datetime, 0x00, m_size);
74                memset(m_lastBlock, 0x00, m_size);
75        }
76
77        if (!deterministicTimeVector)
78        {
79                time_t tstamp1 = time(0);
80                xorbuf(m_datetime, (byte *)&tstamp1, UnsignedMin(sizeof(tstamp1), m_size));
81                m_cipher->ProcessBlock(m_datetime);
82                clock_t tstamp2 = clock();
83                xorbuf(m_datetime, (byte *)&tstamp2, UnsignedMin(sizeof(tstamp2), m_size));
84                m_cipher->ProcessBlock(m_datetime);
85        }
86
87        // for FIPS 140-2
88        GenerateBlock(m_lastBlock, m_size);
89}
90
91void X917RNG::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
92{
93        while (size > 0)
94        {
95                // calculate new enciphered timestamp
96                if (m_deterministicTimeVector.size())
97                {
98                        m_cipher->ProcessBlock(m_deterministicTimeVector, m_datetime);
99                        IncrementCounterByOne(m_deterministicTimeVector, m_size);
100                }
101                else
102                {
103                        clock_t c = clock();
104                        xorbuf(m_datetime, (byte *)&c, UnsignedMin(sizeof(c), m_size));
105                        time_t t = time(NULL);
106                        xorbuf(m_datetime+m_size-UnsignedMin(sizeof(t), m_size), (byte *)&t, UnsignedMin(sizeof(t), m_size));
107                        m_cipher->ProcessBlock(m_datetime);
108                }
109
110                // combine enciphered timestamp with seed
111                xorbuf(m_randseed, m_datetime, m_size);
112
113                // generate a new block of random bytes
114                m_cipher->ProcessBlock(m_randseed);
115                if (memcmp(m_lastBlock, m_randseed, m_size) == 0)
116                        throw SelfTestFailure("X917RNG: Continuous random number generator test failed.");
117
118                // output random bytes
119                size_t len = UnsignedMin(m_size, size);
120                target.ChannelPut(channel, m_randseed, len);
121                size -= len;
122
123                // compute new seed vector
124                memcpy(m_lastBlock, m_randseed, m_size);
125                xorbuf(m_randseed, m_datetime, m_size);
126                m_cipher->ProcessBlock(m_randseed);
127        }
128}
129
130#endif
131
132MaurerRandomnessTest::MaurerRandomnessTest()
133        : sum(0.0), n(0)
134{
135        for (unsigned i=0; i<V; i++)
136                tab[i] = 0;
137}
138
139size_t MaurerRandomnessTest::Put2(const byte *inString, size_t length, int /*messageEnd*/, bool /*blocking*/)
140{
141        while (length--)
142        {
143                byte inByte = *inString++;
144                if (n >= Q)
145                        sum += log(double(n - tab[inByte]));
146                tab[inByte] = n;
147                n++;
148        }
149        return 0;
150}
151
152double MaurerRandomnessTest::GetTestValue() const
153{
154        if (BytesNeeded() > 0)
155                throw Exception(Exception::OTHER_ERROR, "MaurerRandomnessTest: " + IntToString(BytesNeeded()) + " more bytes of input needed");
156
157        double fTu = (sum/(n-Q))/log(2.0);      // this is the test value defined by Maurer
158
159        double value = fTu * 0.1392;            // arbitrarily normalize it to
160        return value > 1.0 ? 1.0 : value;       // a number between 0 and 1
161}
162
163NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.