00001
00002
00003 #include "pch.h"
00004
00005 #include "rng.h"
00006 #include "fips140.h"
00007
00008 #include <time.h>
00009 #include <math.h>
00010
00011 NAMESPACE_BEGIN(CryptoPP)
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef LCRNG_ORIGINAL_NUMBERS
00026 const word32 LC_RNG::m=2147483647L;
00027 const word32 LC_RNG::q=44488L;
00028
00029 const word16 LC_RNG::a=(unsigned int)48271L;
00030 const word16 LC_RNG::r=3399;
00031 #else
00032 const word32 LC_RNG::m=2147483647L;
00033 const word32 LC_RNG::q=127773L;
00034
00035 const word16 LC_RNG::a=16807;
00036 const word16 LC_RNG::r=2836;
00037 #endif
00038
00039 void LC_RNG::GenerateBlock(byte *output, size_t size)
00040 {
00041 while (size--)
00042 {
00043 word32 hi = seed/q;
00044 word32 lo = seed%q;
00045
00046 long test = a*lo - r*hi;
00047
00048 if (test > 0)
00049 seed = test;
00050 else
00051 seed = test+ m;
00052
00053 *output++ = (GETBYTE(seed, 0) ^ GETBYTE(seed, 1) ^ GETBYTE(seed, 2) ^ GETBYTE(seed, 3));
00054 }
00055 }
00056
00057
00058
00059 #ifndef CRYPTOPP_IMPORTS
00060
00061 X917RNG::X917RNG(BlockTransformation *c, const byte *seed, const byte *deterministicTimeVector)
00062 : cipher(c),
00063 S(cipher->BlockSize()),
00064 dtbuf(S),
00065 randseed(seed, S),
00066 m_lastBlock(S),
00067 m_deterministicTimeVector(deterministicTimeVector, deterministicTimeVector ? S : 0)
00068 {
00069 if (!deterministicTimeVector)
00070 {
00071 time_t tstamp1 = time(0);
00072 xorbuf(dtbuf, (byte *)&tstamp1, UnsignedMin(sizeof(tstamp1), S));
00073 cipher->ProcessBlock(dtbuf);
00074 clock_t tstamp2 = clock();
00075 xorbuf(dtbuf, (byte *)&tstamp2, UnsignedMin(sizeof(tstamp2), S));
00076 cipher->ProcessBlock(dtbuf);
00077 }
00078
00079
00080 GenerateBlock(m_lastBlock, S);
00081 }
00082
00083 void X917RNG::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
00084 {
00085 while (size > 0)
00086 {
00087
00088 if (m_deterministicTimeVector.size())
00089 {
00090 cipher->ProcessBlock(m_deterministicTimeVector, dtbuf);
00091 IncrementCounterByOne(m_deterministicTimeVector, S);
00092 }
00093 else
00094 {
00095 clock_t c = clock();
00096 xorbuf(dtbuf, (byte *)&c, UnsignedMin(sizeof(c), S));
00097 time_t t = time(NULL);
00098 xorbuf(dtbuf+S-UnsignedMin(sizeof(t), S), (byte *)&t, UnsignedMin(sizeof(t), S));
00099 cipher->ProcessBlock(dtbuf);
00100 }
00101
00102
00103 xorbuf(randseed, dtbuf, S);
00104
00105
00106 cipher->ProcessBlock(randseed);
00107 if (memcmp(m_lastBlock, randseed, S) == 0)
00108 throw SelfTestFailure("X917RNG: Continuous random number generator test failed.");
00109
00110
00111 size_t len = UnsignedMin(S, size);
00112 target.ChannelPut(channel, randseed, len);
00113 size -= len;
00114
00115
00116 memcpy(m_lastBlock, randseed, S);
00117 xorbuf(randseed, dtbuf, S);
00118 cipher->ProcessBlock(randseed);
00119 }
00120 }
00121
00122 #endif
00123
00124 MaurerRandomnessTest::MaurerRandomnessTest()
00125 : sum(0.0), n(0)
00126 {
00127 for (unsigned i=0; i<V; i++)
00128 tab[i] = 0;
00129 }
00130
00131 size_t MaurerRandomnessTest::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
00132 {
00133 while (length--)
00134 {
00135 byte inByte = *inString++;
00136 if (n >= Q)
00137 sum += log(double(n - tab[inByte]));
00138 tab[inByte] = n;
00139 n++;
00140 }
00141 return 0;
00142 }
00143
00144 double MaurerRandomnessTest::GetTestValue() const
00145 {
00146 if (BytesNeeded() > 0)
00147 throw Exception(Exception::OTHER_ERROR, "MaurerRandomnessTest: " + IntToString(BytesNeeded()) + " more bytes of input needed");
00148
00149 double fTu = (sum/(n-Q))/log(2.0);
00150
00151 double value = fTu * 0.1392;
00152 return value > 1.0 ? 1.0 : value;
00153 }
00154
00155 NAMESPACE_END