Crypto++ 8.7
Free C++ class library of cryptographic schemes
rng.cpp
1// rng.cpp - originally 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 const word32 hi = seed/q;
44 const word32 lo = seed%q;
45 const sword64 test = a*lo - r*hi;
46
47 if (test > 0)
48 seed = static_cast<word32>(test);
49 else
50 seed = static_cast<word32>(test + m);
51
52 *output++ = byte((GETBYTE(seed, 0) ^ GETBYTE(seed, 1) ^ GETBYTE(seed, 2) ^ GETBYTE(seed, 3)));
53 }
54}
55
56// ********************************************************
57
58#ifndef CRYPTOPP_IMPORTS
59
60X917RNG::X917RNG(BlockTransformation *c, const byte *seed, const byte *deterministicTimeVector)
61 : m_cipher(c),
62 m_size(m_cipher->BlockSize()),
63 m_datetime(m_size),
64 m_randseed(seed, m_size),
65 m_lastBlock(m_size),
66 m_deterministicTimeVector(deterministicTimeVector, deterministicTimeVector ? m_size : 0)
67{
68 // Valgrind finding, http://github.com/weidai11/cryptopp/issues/105
69 // Garbage in the tail creates a non-conforming X9.17 or X9.31 generator.
70 if (m_size > 8)
71 {
72 memset(m_datetime, 0x00, m_size);
73 memset(m_lastBlock, 0x00, m_size);
74 }
75
76 if (!deterministicTimeVector)
77 {
78 time_t tstamp1 = ::time(NULLPTR);
79 xorbuf(m_datetime, (byte *)&tstamp1, UnsignedMin(sizeof(tstamp1), m_size));
80 m_cipher->ProcessBlock(m_datetime);
81 clock_t tstamp2 = clock();
82 xorbuf(m_datetime, (byte *)&tstamp2, UnsignedMin(sizeof(tstamp2), m_size));
83 m_cipher->ProcessBlock(m_datetime);
84 }
85
86 // for FIPS 140-2
87 // GenerateBlock(m_lastBlock, m_size);
88
89 // Make explicit call to avoid virtual-dispatch findings in ctor
90 ArraySink target(m_lastBlock, m_size);
92}
93
94void X917RNG::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
95{
96 while (size > 0)
97 {
98 // calculate new enciphered timestamp
99 if (m_deterministicTimeVector.size())
100 {
101 m_cipher->ProcessBlock(m_deterministicTimeVector, m_datetime);
102 IncrementCounterByOne(m_deterministicTimeVector, m_size);
103 }
104 else
105 {
106 clock_t c = clock();
107 xorbuf(m_datetime, (byte *)&c, UnsignedMin(sizeof(c), m_size));
108 time_t t = ::time(NULLPTR);
109 xorbuf(m_datetime+m_size-UnsignedMin(sizeof(t), m_size), (byte *)&t, UnsignedMin(sizeof(t), m_size));
110 m_cipher->ProcessBlock(m_datetime);
111 }
112
113 // combine enciphered timestamp with seed
114 xorbuf(m_randseed, m_datetime, m_size);
115
116 // generate a new block of random bytes
117 m_cipher->ProcessBlock(m_randseed);
118 if (memcmp(m_lastBlock, m_randseed, m_size) == 0)
119 throw SelfTestFailure("X917RNG: Continuous random number generator test failed.");
120
121 // output random bytes
122 size_t len = UnsignedMin(m_size, size);
123 target.ChannelPut(channel, m_randseed, len);
124 size -= len;
125
126 // compute new seed vector
127 memcpy(m_lastBlock, m_randseed, m_size);
128 xorbuf(m_randseed, m_datetime, m_size);
129 m_cipher->ProcessBlock(m_randseed);
130 }
131}
132
133#endif
134
136 : sum(0.0), n(0)
137{
138 for (unsigned i=0; i<V; i++)
139 tab[i] = 0;
140}
141
142size_t MaurerRandomnessTest::Put2(const byte *inString, size_t length, int /*messageEnd*/, bool /*blocking*/)
143{
144 while (length--)
145 {
146 byte inByte = *inString++;
147 if (n >= Q)
148 sum += ::log(double(n - tab[inByte]));
149 tab[inByte] = n;
150 n++;
151 }
152 return 0;
153}
154
155double MaurerRandomnessTest::GetTestValue() const
156{
157 if (BytesNeeded() > 0)
158 throw Exception(Exception::OTHER_ERROR, "MaurerRandomnessTest: " + IntToString(BytesNeeded()) + " more bytes of input needed");
159
160 double fTu = (sum/(n-Q))/::log(2.0); // this is the test value defined by Maurer
161
162 double value = fTu * 0.1392; // arbitrarily normalize it to
163 return value > 1.0 ? 1.0 : value; // a number between 0 and 1
164}
165
166NAMESPACE_END
Copy input to a memory buffer.
Definition: filters.h:1200
Interface for the data processing part of block ciphers.
Definition: cryptlib.h:856
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
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:159
@ OTHER_ERROR
Some other error occurred not belonging to other categories.
Definition: cryptlib.h:177
void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
Definition: rng.cpp:39
MaurerRandomnessTest()
Construct a MaurerRandomnessTest.
Definition: rng.cpp:135
unsigned int BytesNeeded() const
Provides the number of bytes of input is needed by the test.
Definition: rng.h:96
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
Input multiple bytes for processing.
Definition: rng.cpp:142
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:867
Exception thrown when a crypto algorithm is used after a self test fails.
Definition: fips140.h:23
void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
Generate random bytes into a BufferedTransformation.
X917RNG(BlockTransformation *cipher, const byte *seed, const byte *deterministicTimeVector=NULL)
Construct a X917RNG.
signed long long sword64
64-bit signed datatype
Definition: config_int.h:99
unsigned char byte
8-bit unsigned datatype
Definition: config_int.h:56
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:62
unsigned short word16
16-bit unsigned datatype
Definition: config_int.h:59
word64 lword
Large word type.
Definition: config_int.h:158
const std::string DEFAULT_CHANNEL
Default channel for BufferedTransformation.
Definition: cryptlib.h:511
Classes and functions for the FIPS 140-2 validated library.
void IncrementCounterByOne(byte *inout, unsigned int size)
Performs an addition with carry on a block of bytes.
Definition: misc.h:1299
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:724
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.
Crypto++ library namespace.
const char * BlockSize()
int, in bytes
Definition: argnames.h:27
Precompiled header file.
Miscellaneous classes for RNGs.