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++ = (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	: cipher(c),
63	  S(cipher->BlockSize()),
64	  dtbuf(S),
65	  randseed(seed, S),
66	  m_lastBlock(S),
67	  m_deterministicTimeVector(deterministicTimeVector, deterministicTimeVector ? S : 0)
68{
69	if (!deterministicTimeVector)
70	{
71		time_t tstamp1 = time(0);
72		xorbuf(dtbuf, (byte *)&tstamp1, UnsignedMin(sizeof(tstamp1), S));
73		cipher->ProcessBlock(dtbuf);
74		clock_t tstamp2 = clock();
75		xorbuf(dtbuf, (byte *)&tstamp2, UnsignedMin(sizeof(tstamp2), S));
76		cipher->ProcessBlock(dtbuf);
77	}
78
79	// for FIPS 140-2
80	GenerateBlock(m_lastBlock, S);
81}
82
83void X917RNG::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
84{
85	while (size > 0)
86	{
87		// calculate new enciphered timestamp
88		if (m_deterministicTimeVector.size())
89		{
90			cipher->ProcessBlock(m_deterministicTimeVector, dtbuf);
91			IncrementCounterByOne(m_deterministicTimeVector, S);
92		}
93		else
94		{
95			clock_t c = clock();
96			xorbuf(dtbuf, (byte *)&c, UnsignedMin(sizeof(c), S));
97			time_t t = time(NULL);
98			xorbuf(dtbuf+S-UnsignedMin(sizeof(t), S), (byte *)&t, UnsignedMin(sizeof(t), S));
99			cipher->ProcessBlock(dtbuf);
100		}
101
102		// combine enciphered timestamp with seed
103		xorbuf(randseed, dtbuf, S);
104
105		// generate a new block of random bytes
106		cipher->ProcessBlock(randseed);
107		if (memcmp(m_lastBlock, randseed, S) == 0)
108			throw SelfTestFailure("X917RNG: Continuous random number generator test failed.");
109
110		// output random bytes
111		size_t len = UnsignedMin(S, size);
112		target.ChannelPut(channel, randseed, len);
113		size -= len;
114
115		// compute new seed vector
116		memcpy(m_lastBlock, randseed, S);
117		xorbuf(randseed, dtbuf, S);
118		cipher->ProcessBlock(randseed);
119	}
120}
121
122#endif
123
124MaurerRandomnessTest::MaurerRandomnessTest()
125	: sum(0.0), n(0)
126{
127	for (unsigned i=0; i<V; i++)
128		tab[i] = 0;
129}
130
131size_t MaurerRandomnessTest::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
132{
133	while (length--)
134	{
135		byte inByte = *inString++;
136		if (n >= Q)
137			sum += log(double(n - tab[inByte]));
138		tab[inByte] = n;
139		n++;
140	}
141	return 0;
142}
143
144double MaurerRandomnessTest::GetTestValue() const
145{
146	if (BytesNeeded() > 0)
147		throw Exception(Exception::OTHER_ERROR, "MaurerRandomnessTest: " + IntToString(BytesNeeded()) + " more bytes of input needed");
148
149	double fTu = (sum/(n-Q))/log(2.0);	// this is the test value defined by Maurer
150
151	double value = fTu * 0.1392;		// arbitrarily normalize it to
152	return value > 1.0 ? 1.0 : value;	// a number between 0 and 1
153}
154
155NAMESPACE_END
156