Home | History | Annotate | Download | only in Crypto
      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 
     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 
     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