xref: /aosp_15_r20/external/lzma/CPP/7zip/Crypto/RandGen.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // RandGen.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "RandGen.h"
6 
7 #ifndef USE_STATIC_SYSTEM_RAND
8 
9 #ifndef Z7_ST
10 #include "../../Windows/Synchronization.h"
11 #endif
12 
13 
14 #ifdef _WIN32
15 
16 #ifdef _WIN64
17 #define USE_STATIC_RtlGenRandom
18 #endif
19 
20 #ifdef USE_STATIC_RtlGenRandom
21 
22 // #include <NTSecAPI.h>
23 
24 EXTERN_C_BEGIN
25 #ifndef RtlGenRandom
26   #define RtlGenRandom SystemFunction036
27   BOOLEAN WINAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
28 #endif
29 EXTERN_C_END
30 
31 #else
32 EXTERN_C_BEGIN
33 typedef BOOLEAN (WINAPI * Func_RtlGenRandom)(PVOID RandomBuffer, ULONG RandomBufferLength);
34 EXTERN_C_END
35 #endif
36 
37 
38 #else
39 #include <unistd.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <fcntl.h>
43 #define USE_POSIX_TIME
44 #define USE_POSIX_TIME2
45 #endif
46 
47 #ifdef USE_POSIX_TIME
48 #include <time.h>
49 #ifdef USE_POSIX_TIME2
50 #include <sys/time.h>
51 #endif
52 #endif
53 
54 // The seed and first generated data block depend from processID,
55 // theadID, timer and system random generator, if available.
56 // Other generated data blocks depend from previous state
57 
58 #define HASH_UPD(x) Sha256_Update(&hash, (const Byte *)&x, sizeof(x));
59 
Init()60 void CRandomGenerator::Init()
61 {
62   MY_ALIGN (16)
63   CSha256 hash;
64   Sha256_Init(&hash);
65 
66   unsigned numIterations = 1000;
67 
68   {
69   #ifndef UNDER_CE
70   const unsigned kNumIterations_Small = 100;
71   const unsigned kBufSize = 32;
72   MY_ALIGN (16)
73   Byte buf[kBufSize];
74   #endif
75 
76   #ifdef _WIN32
77 
78   DWORD w = ::GetCurrentProcessId();
79   HASH_UPD(w)
80   w = ::GetCurrentThreadId();
81   HASH_UPD(w)
82 
83   #ifdef UNDER_CE
84   /*
85   if (CeGenRandom(kBufSize, buf))
86   {
87     numIterations = kNumIterations_Small;
88     Sha256_Update(&hash, buf, kBufSize);
89   }
90   */
91   #elif defined(USE_STATIC_RtlGenRandom)
92   if (RtlGenRandom(buf, kBufSize))
93   {
94     numIterations = kNumIterations_Small;
95     Sha256_Update(&hash, buf, kBufSize);
96   }
97   #else
98   {
99     const HMODULE hModule = ::LoadLibrary(TEXT("advapi32.dll"));
100     if (hModule)
101     {
102       // SystemFunction036() is real name of RtlGenRandom() function
103       const
104       Func_RtlGenRandom
105         my_RtlGenRandom = Z7_GET_PROC_ADDRESS(
106       Func_RtlGenRandom, hModule, "SystemFunction036");
107       if (my_RtlGenRandom)
108       {
109         if (my_RtlGenRandom(buf, kBufSize))
110         {
111           numIterations = kNumIterations_Small;
112           Sha256_Update(&hash, buf, kBufSize);
113         }
114       }
115       ::FreeLibrary(hModule);
116     }
117   }
118   #endif
119 
120   #else
121 
122   pid_t pid = getpid();
123   HASH_UPD(pid)
124   pid = getppid();
125   HASH_UPD(pid)
126 
127   {
128     int f = open("/dev/urandom", O_RDONLY);
129     unsigned numBytes = kBufSize;
130     if (f >= 0)
131     {
132       do
133       {
134         ssize_t n = read(f, buf, numBytes);
135         if (n <= 0)
136           break;
137         Sha256_Update(&hash, buf, (size_t)n);
138         numBytes -= (unsigned)n;
139       }
140       while (numBytes);
141       close(f);
142       if (numBytes == 0)
143         numIterations = kNumIterations_Small;
144     }
145   }
146   /*
147   {
148     int n = getrandom(buf, kBufSize, 0);
149     if (n > 0)
150     {
151       Sha256_Update(&hash, buf, n);
152       if (n == kBufSize)
153         numIterations = kNumIterations_Small;
154     }
155   }
156   */
157 
158   #endif
159   }
160 
161   #ifdef _DEBUG
162   numIterations = 2;
163   #endif
164 
165   do
166   {
167     #ifdef _WIN32
168     LARGE_INTEGER v;
169     if (::QueryPerformanceCounter(&v))
170       HASH_UPD(v.QuadPart)
171     #endif
172 
173     #ifdef USE_POSIX_TIME
174     #ifdef USE_POSIX_TIME2
175     timeval v;
176     if (gettimeofday(&v, NULL) == 0)
177     {
178       HASH_UPD(v.tv_sec)
179       HASH_UPD(v.tv_usec)
180     }
181     #endif
182     const time_t v2 = time(NULL);
183     HASH_UPD(v2)
184     #endif
185 
186     #ifdef _WIN32
187     const DWORD tickCount = ::GetTickCount();
188     HASH_UPD(tickCount)
189     #endif
190 
191     for (unsigned j = 0; j < 100; j++)
192     {
193       Sha256_Final(&hash, _buff);
194       Sha256_Init(&hash);
195       Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
196     }
197   }
198   while (--numIterations);
199 
200   Sha256_Final(&hash, _buff);
201   _needInit = false;
202 }
203 
204 #ifndef Z7_ST
205   static NWindows::NSynchronization::CCriticalSection g_CriticalSection;
206   #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
207 #else
208   #define MT_LOCK
209 #endif
210 
Generate(Byte * data,unsigned size)211 void CRandomGenerator::Generate(Byte *data, unsigned size)
212 {
213   MT_LOCK
214 
215   if (_needInit)
216     Init();
217   while (size != 0)
218   {
219     MY_ALIGN (16)
220     CSha256 hash;
221 
222     Sha256_Init(&hash);
223     Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
224     Sha256_Final(&hash, _buff);
225 
226     Sha256_Init(&hash);
227     UInt32 salt = 0xF672ABD1;
228     HASH_UPD(salt)
229     Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
230     MY_ALIGN (16)
231     Byte buff[SHA256_DIGEST_SIZE];
232     Sha256_Final(&hash, buff);
233     for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size != 0; i++, size--)
234       *data++ = buff[i];
235   }
236 }
237 
238 MY_ALIGN (16)
239 CRandomGenerator g_RandomGenerator;
240 
241 #endif
242