1 // RandGen.cpp
2 
3 #include "StdAfx.h"
4 
5 #ifndef _7ZIP_ST
6 #include "../../Windows/Synchronization.h"
7 #endif
8 
9 #include "RandGen.h"
10 
11 #ifndef _WIN32
12 #include <unistd.h>
13 #define USE_POSIX_TIME
14 #define USE_POSIX_TIME2
15 #endif
16 
17 #ifdef USE_POSIX_TIME
18 #include <time.h>
19 #ifdef USE_POSIX_TIME2
20 #include <sys/time.h>
21 #endif
22 #endif
23 
24 // This is not very good random number generator.
25 // Please use it only for salt.
26 // First generated data block depends from timer and processID.
27 // Other generated data blocks depend from previous state
28 // Maybe it's possible to restore original timer value from generated value.
29 
30 #define HASH_UPD(x) Sha256_Update(&hash, (const Byte *)&x, sizeof(x));
31 
Init()32 void CRandomGenerator::Init()
33 {
34   CSha256 hash;
35   Sha256_Init(&hash);
36 
37   #ifdef _WIN32
38   DWORD w = ::GetCurrentProcessId();
39   HASH_UPD(w);
40   w = ::GetCurrentThreadId();
41   HASH_UPD(w);
42   #else
43   pid_t pid = getpid();
44   HASH_UPD(pid);
45   pid = getppid();
46   HASH_UPD(pid);
47   #endif
48 
49   for (unsigned i = 0; i <
50     #ifdef _DEBUG
51     2;
52     #else
53     1000;
54     #endif
55     i++)
56   {
57     #ifdef _WIN32
58     LARGE_INTEGER v;
59     if (::QueryPerformanceCounter(&v))
60       HASH_UPD(v.QuadPart);
61     #endif
62 
63     #ifdef USE_POSIX_TIME
64     #ifdef USE_POSIX_TIME2
65     timeval v;
66     if (gettimeofday(&v, 0) == 0)
67     {
68       HASH_UPD(v.tv_sec);
69       HASH_UPD(v.tv_usec);
70     }
71     #endif
72     time_t v2 = time(NULL);
73     HASH_UPD(v2);
74     #endif
75 
76     #ifdef _WIN32
77     DWORD tickCount = ::GetTickCount();
78     HASH_UPD(tickCount);
79     #endif
80 
81     for (unsigned j = 0; j < 100; j++)
82     {
83       Sha256_Final(&hash, _buff);
84       Sha256_Init(&hash);
85       Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
86     }
87   }
88   Sha256_Final(&hash, _buff);
89   _needInit = false;
90 }
91 
92 #ifndef _7ZIP_ST
93   static NWindows::NSynchronization::CCriticalSection g_CriticalSection;
94   #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
95 #else
96   #define MT_LOCK
97 #endif
98 
Generate(Byte * data,unsigned size)99 void CRandomGenerator::Generate(Byte *data, unsigned size)
100 {
101   MT_LOCK
102 
103   if (_needInit)
104     Init();
105   while (size != 0)
106   {
107     CSha256 hash;
108 
109     Sha256_Init(&hash);
110     Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
111     Sha256_Final(&hash, _buff);
112 
113     Sha256_Init(&hash);
114     UInt32 salt = 0xF672ABD1;
115     HASH_UPD(salt);
116     Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
117     Byte buff[SHA256_DIGEST_SIZE];
118     Sha256_Final(&hash, buff);
119     for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size != 0; i++, size--)
120       *data++ = buff[i];
121   }
122 }
123 
124 CRandomGenerator g_RandomGenerator;
125