1370b324cSopenharmony_ci// RandGen.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "RandGen.h"
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#ifndef USE_STATIC_SYSTEM_RAND
8370b324cSopenharmony_ci
9370b324cSopenharmony_ci#ifndef Z7_ST
10370b324cSopenharmony_ci#include "../../Windows/Synchronization.h"
11370b324cSopenharmony_ci#endif
12370b324cSopenharmony_ci
13370b324cSopenharmony_ci
14370b324cSopenharmony_ci#ifdef _WIN32
15370b324cSopenharmony_ci
16370b324cSopenharmony_ci#ifdef _WIN64
17370b324cSopenharmony_ci#define USE_STATIC_RtlGenRandom
18370b324cSopenharmony_ci#endif
19370b324cSopenharmony_ci
20370b324cSopenharmony_ci#ifdef USE_STATIC_RtlGenRandom
21370b324cSopenharmony_ci
22370b324cSopenharmony_ci// #include <NTSecAPI.h>
23370b324cSopenharmony_ci
24370b324cSopenharmony_ciEXTERN_C_BEGIN
25370b324cSopenharmony_ci#ifndef RtlGenRandom
26370b324cSopenharmony_ci  #define RtlGenRandom SystemFunction036
27370b324cSopenharmony_ci  BOOLEAN WINAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
28370b324cSopenharmony_ci#endif
29370b324cSopenharmony_ciEXTERN_C_END
30370b324cSopenharmony_ci
31370b324cSopenharmony_ci#else
32370b324cSopenharmony_ciEXTERN_C_BEGIN
33370b324cSopenharmony_citypedef BOOLEAN (WINAPI * Func_RtlGenRandom)(PVOID RandomBuffer, ULONG RandomBufferLength);
34370b324cSopenharmony_ciEXTERN_C_END
35370b324cSopenharmony_ci#endif
36370b324cSopenharmony_ci
37370b324cSopenharmony_ci
38370b324cSopenharmony_ci#else
39370b324cSopenharmony_ci#include <unistd.h>
40370b324cSopenharmony_ci#include <sys/types.h>
41370b324cSopenharmony_ci#include <sys/stat.h>
42370b324cSopenharmony_ci#include <fcntl.h>
43370b324cSopenharmony_ci#define USE_POSIX_TIME
44370b324cSopenharmony_ci#define USE_POSIX_TIME2
45370b324cSopenharmony_ci#endif
46370b324cSopenharmony_ci
47370b324cSopenharmony_ci#ifdef USE_POSIX_TIME
48370b324cSopenharmony_ci#include <time.h>
49370b324cSopenharmony_ci#ifdef USE_POSIX_TIME2
50370b324cSopenharmony_ci#include <sys/time.h>
51370b324cSopenharmony_ci#endif
52370b324cSopenharmony_ci#endif
53370b324cSopenharmony_ci
54370b324cSopenharmony_ci// The seed and first generated data block depend from processID,
55370b324cSopenharmony_ci// theadID, timer and system random generator, if available.
56370b324cSopenharmony_ci// Other generated data blocks depend from previous state
57370b324cSopenharmony_ci
58370b324cSopenharmony_ci#define HASH_UPD(x) Sha256_Update(&hash, (const Byte *)&x, sizeof(x));
59370b324cSopenharmony_ci
60370b324cSopenharmony_civoid CRandomGenerator::Init()
61370b324cSopenharmony_ci{
62370b324cSopenharmony_ci  MY_ALIGN (16)
63370b324cSopenharmony_ci  CSha256 hash;
64370b324cSopenharmony_ci  Sha256_Init(&hash);
65370b324cSopenharmony_ci
66370b324cSopenharmony_ci  unsigned numIterations = 1000;
67370b324cSopenharmony_ci
68370b324cSopenharmony_ci  {
69370b324cSopenharmony_ci  #ifndef UNDER_CE
70370b324cSopenharmony_ci  const unsigned kNumIterations_Small = 100;
71370b324cSopenharmony_ci  const unsigned kBufSize = 32;
72370b324cSopenharmony_ci  MY_ALIGN (16)
73370b324cSopenharmony_ci  Byte buf[kBufSize];
74370b324cSopenharmony_ci  #endif
75370b324cSopenharmony_ci
76370b324cSopenharmony_ci  #ifdef _WIN32
77370b324cSopenharmony_ci
78370b324cSopenharmony_ci  DWORD w = ::GetCurrentProcessId();
79370b324cSopenharmony_ci  HASH_UPD(w)
80370b324cSopenharmony_ci  w = ::GetCurrentThreadId();
81370b324cSopenharmony_ci  HASH_UPD(w)
82370b324cSopenharmony_ci
83370b324cSopenharmony_ci  #ifdef UNDER_CE
84370b324cSopenharmony_ci  /*
85370b324cSopenharmony_ci  if (CeGenRandom(kBufSize, buf))
86370b324cSopenharmony_ci  {
87370b324cSopenharmony_ci    numIterations = kNumIterations_Small;
88370b324cSopenharmony_ci    Sha256_Update(&hash, buf, kBufSize);
89370b324cSopenharmony_ci  }
90370b324cSopenharmony_ci  */
91370b324cSopenharmony_ci  #elif defined(USE_STATIC_RtlGenRandom)
92370b324cSopenharmony_ci  if (RtlGenRandom(buf, kBufSize))
93370b324cSopenharmony_ci  {
94370b324cSopenharmony_ci    numIterations = kNumIterations_Small;
95370b324cSopenharmony_ci    Sha256_Update(&hash, buf, kBufSize);
96370b324cSopenharmony_ci  }
97370b324cSopenharmony_ci  #else
98370b324cSopenharmony_ci  {
99370b324cSopenharmony_ci    const HMODULE hModule = ::LoadLibrary(TEXT("advapi32.dll"));
100370b324cSopenharmony_ci    if (hModule)
101370b324cSopenharmony_ci    {
102370b324cSopenharmony_ci      // SystemFunction036() is real name of RtlGenRandom() function
103370b324cSopenharmony_ci      const
104370b324cSopenharmony_ci      Func_RtlGenRandom
105370b324cSopenharmony_ci        my_RtlGenRandom = Z7_GET_PROC_ADDRESS(
106370b324cSopenharmony_ci      Func_RtlGenRandom, hModule, "SystemFunction036");
107370b324cSopenharmony_ci      if (my_RtlGenRandom)
108370b324cSopenharmony_ci      {
109370b324cSopenharmony_ci        if (my_RtlGenRandom(buf, kBufSize))
110370b324cSopenharmony_ci        {
111370b324cSopenharmony_ci          numIterations = kNumIterations_Small;
112370b324cSopenharmony_ci          Sha256_Update(&hash, buf, kBufSize);
113370b324cSopenharmony_ci        }
114370b324cSopenharmony_ci      }
115370b324cSopenharmony_ci      ::FreeLibrary(hModule);
116370b324cSopenharmony_ci    }
117370b324cSopenharmony_ci  }
118370b324cSopenharmony_ci  #endif
119370b324cSopenharmony_ci
120370b324cSopenharmony_ci  #else
121370b324cSopenharmony_ci
122370b324cSopenharmony_ci  pid_t pid = getpid();
123370b324cSopenharmony_ci  HASH_UPD(pid)
124370b324cSopenharmony_ci  pid = getppid();
125370b324cSopenharmony_ci  HASH_UPD(pid)
126370b324cSopenharmony_ci
127370b324cSopenharmony_ci  {
128370b324cSopenharmony_ci    int f = open("/dev/urandom", O_RDONLY);
129370b324cSopenharmony_ci    unsigned numBytes = kBufSize;
130370b324cSopenharmony_ci    if (f >= 0)
131370b324cSopenharmony_ci    {
132370b324cSopenharmony_ci      do
133370b324cSopenharmony_ci      {
134370b324cSopenharmony_ci        ssize_t n = read(f, buf, numBytes);
135370b324cSopenharmony_ci        if (n <= 0)
136370b324cSopenharmony_ci          break;
137370b324cSopenharmony_ci        Sha256_Update(&hash, buf, (size_t)n);
138370b324cSopenharmony_ci        numBytes -= (unsigned)n;
139370b324cSopenharmony_ci      }
140370b324cSopenharmony_ci      while (numBytes);
141370b324cSopenharmony_ci      close(f);
142370b324cSopenharmony_ci      if (numBytes == 0)
143370b324cSopenharmony_ci        numIterations = kNumIterations_Small;
144370b324cSopenharmony_ci    }
145370b324cSopenharmony_ci  }
146370b324cSopenharmony_ci  /*
147370b324cSopenharmony_ci  {
148370b324cSopenharmony_ci    int n = getrandom(buf, kBufSize, 0);
149370b324cSopenharmony_ci    if (n > 0)
150370b324cSopenharmony_ci    {
151370b324cSopenharmony_ci      Sha256_Update(&hash, buf, n);
152370b324cSopenharmony_ci      if (n == kBufSize)
153370b324cSopenharmony_ci        numIterations = kNumIterations_Small;
154370b324cSopenharmony_ci    }
155370b324cSopenharmony_ci  }
156370b324cSopenharmony_ci  */
157370b324cSopenharmony_ci
158370b324cSopenharmony_ci  #endif
159370b324cSopenharmony_ci  }
160370b324cSopenharmony_ci
161370b324cSopenharmony_ci  #ifdef _DEBUG
162370b324cSopenharmony_ci  numIterations = 2;
163370b324cSopenharmony_ci  #endif
164370b324cSopenharmony_ci
165370b324cSopenharmony_ci  do
166370b324cSopenharmony_ci  {
167370b324cSopenharmony_ci    #ifdef _WIN32
168370b324cSopenharmony_ci    LARGE_INTEGER v;
169370b324cSopenharmony_ci    if (::QueryPerformanceCounter(&v))
170370b324cSopenharmony_ci      HASH_UPD(v.QuadPart)
171370b324cSopenharmony_ci    #endif
172370b324cSopenharmony_ci
173370b324cSopenharmony_ci    #ifdef USE_POSIX_TIME
174370b324cSopenharmony_ci    #ifdef USE_POSIX_TIME2
175370b324cSopenharmony_ci    timeval v;
176370b324cSopenharmony_ci    if (gettimeofday(&v, NULL) == 0)
177370b324cSopenharmony_ci    {
178370b324cSopenharmony_ci      HASH_UPD(v.tv_sec)
179370b324cSopenharmony_ci      HASH_UPD(v.tv_usec)
180370b324cSopenharmony_ci    }
181370b324cSopenharmony_ci    #endif
182370b324cSopenharmony_ci    const time_t v2 = time(NULL);
183370b324cSopenharmony_ci    HASH_UPD(v2)
184370b324cSopenharmony_ci    #endif
185370b324cSopenharmony_ci
186370b324cSopenharmony_ci    #ifdef _WIN32
187370b324cSopenharmony_ci    const DWORD tickCount = ::GetTickCount();
188370b324cSopenharmony_ci    HASH_UPD(tickCount)
189370b324cSopenharmony_ci    #endif
190370b324cSopenharmony_ci
191370b324cSopenharmony_ci    for (unsigned j = 0; j < 100; j++)
192370b324cSopenharmony_ci    {
193370b324cSopenharmony_ci      Sha256_Final(&hash, _buff);
194370b324cSopenharmony_ci      Sha256_Init(&hash);
195370b324cSopenharmony_ci      Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
196370b324cSopenharmony_ci    }
197370b324cSopenharmony_ci  }
198370b324cSopenharmony_ci  while (--numIterations);
199370b324cSopenharmony_ci
200370b324cSopenharmony_ci  Sha256_Final(&hash, _buff);
201370b324cSopenharmony_ci  _needInit = false;
202370b324cSopenharmony_ci}
203370b324cSopenharmony_ci
204370b324cSopenharmony_ci#ifndef Z7_ST
205370b324cSopenharmony_ci  static NWindows::NSynchronization::CCriticalSection g_CriticalSection;
206370b324cSopenharmony_ci  #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
207370b324cSopenharmony_ci#else
208370b324cSopenharmony_ci  #define MT_LOCK
209370b324cSopenharmony_ci#endif
210370b324cSopenharmony_ci
211370b324cSopenharmony_civoid CRandomGenerator::Generate(Byte *data, unsigned size)
212370b324cSopenharmony_ci{
213370b324cSopenharmony_ci  MT_LOCK
214370b324cSopenharmony_ci
215370b324cSopenharmony_ci  if (_needInit)
216370b324cSopenharmony_ci    Init();
217370b324cSopenharmony_ci  while (size != 0)
218370b324cSopenharmony_ci  {
219370b324cSopenharmony_ci    MY_ALIGN (16)
220370b324cSopenharmony_ci    CSha256 hash;
221370b324cSopenharmony_ci
222370b324cSopenharmony_ci    Sha256_Init(&hash);
223370b324cSopenharmony_ci    Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
224370b324cSopenharmony_ci    Sha256_Final(&hash, _buff);
225370b324cSopenharmony_ci
226370b324cSopenharmony_ci    Sha256_Init(&hash);
227370b324cSopenharmony_ci    UInt32 salt = 0xF672ABD1;
228370b324cSopenharmony_ci    HASH_UPD(salt)
229370b324cSopenharmony_ci    Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
230370b324cSopenharmony_ci    MY_ALIGN (16)
231370b324cSopenharmony_ci    Byte buff[SHA256_DIGEST_SIZE];
232370b324cSopenharmony_ci    Sha256_Final(&hash, buff);
233370b324cSopenharmony_ci    for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size != 0; i++, size--)
234370b324cSopenharmony_ci      *data++ = buff[i];
235370b324cSopenharmony_ci  }
236370b324cSopenharmony_ci}
237370b324cSopenharmony_ci
238370b324cSopenharmony_ciMY_ALIGN (16)
239370b324cSopenharmony_ciCRandomGenerator g_RandomGenerator;
240370b324cSopenharmony_ci
241370b324cSopenharmony_ci#endif
242