1 #include "rar.hpp"
2 
3 #ifndef SFX_MODULE
4 #include "crypt1.cpp"
5 #include "crypt2.cpp"
6 #endif
7 #include "crypt3.cpp"
8 #include "crypt5.cpp"
9 
10 
CryptData()11 CryptData::CryptData()
12 {
13   Method=CRYPT_NONE;
14   memset(KDF3Cache,0,sizeof(KDF3Cache));
15   memset(KDF5Cache,0,sizeof(KDF5Cache));
16   KDF3CachePos=0;
17   KDF5CachePos=0;
18   memset(CRCTab,0,sizeof(CRCTab));
19 }
20 
21 
~CryptData()22 CryptData::~CryptData()
23 {
24   cleandata(KDF3Cache,sizeof(KDF3Cache));
25   cleandata(KDF5Cache,sizeof(KDF5Cache));
26 }
27 
28 
29 
30 
DecryptBlock(byte * Buf,size_t Size)31 void CryptData::DecryptBlock(byte *Buf,size_t Size)
32 {
33   switch(Method)
34   {
35 #ifndef SFX_MODULE
36     case CRYPT_RAR13:
37       Decrypt13(Buf,Size);
38       break;
39     case CRYPT_RAR15:
40       Crypt15(Buf,Size);
41       break;
42     case CRYPT_RAR20:
43       for (size_t I=0;I<Size;I+=CRYPT_BLOCK_SIZE)
44         DecryptBlock20(Buf+I);
45       break;
46 #endif
47     case CRYPT_RAR30:
48     case CRYPT_RAR50:
49       rin.blockDecrypt(Buf,Size,Buf);
50       break;
51   }
52 }
53 
54 
SetCryptKeys(bool Encrypt,CRYPT_METHOD Method,SecPassword * Password,const byte * Salt,const byte * InitV,uint Lg2Cnt,byte * HashKey,byte * PswCheck)55 bool CryptData::SetCryptKeys(bool Encrypt,CRYPT_METHOD Method,
56      SecPassword *Password,const byte *Salt,
57      const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck)
58 {
59   if (!Password->IsSet() || Method==CRYPT_NONE)
60     return false;
61 
62   CryptData::Method=Method;
63 
64   wchar PwdW[MAXPASSWORD];
65   Password->Get(PwdW,ASIZE(PwdW));
66   char PwdA[MAXPASSWORD];
67   WideToChar(PwdW,PwdA,ASIZE(PwdA));
68 
69   switch(Method)
70   {
71 #ifndef SFX_MODULE
72     case CRYPT_RAR13:
73       SetKey13(PwdA);
74       break;
75     case CRYPT_RAR15:
76       SetKey15(PwdA);
77       break;
78     case CRYPT_RAR20:
79       SetKey20(PwdA);
80       break;
81 #endif
82     case CRYPT_RAR30:
83       SetKey30(Encrypt,Password,PwdW,Salt);
84       break;
85     case CRYPT_RAR50:
86       SetKey50(Encrypt,Password,PwdW,Salt,InitV,Lg2Cnt,HashKey,PswCheck);
87       break;
88   }
89   cleandata(PwdA,sizeof(PwdA));
90   cleandata(PwdW,sizeof(PwdW));
91   return true;
92 }
93 
94 
95 // Use the current system time to additionally randomize data.
TimeRandomize(byte * RndBuf,size_t BufSize)96 static void TimeRandomize(byte *RndBuf,size_t BufSize)
97 {
98   static uint Count=0;
99   RarTime CurTime;
100   CurTime.SetCurrentTime();
101   uint64 Random=CurTime.GetWin()+clock();
102   for (size_t I=0;I<BufSize;I++)
103   {
104     byte RndByte = byte (Random >> ( (I & 7) * 8 ));
105     RndBuf[I]=byte( (RndByte ^ I) + Count++);
106   }
107 }
108 
109 
110 
111 
112 // Fill buffer with random data.
GetRnd(byte * RndBuf,size_t BufSize)113 void GetRnd(byte *RndBuf,size_t BufSize)
114 {
115   bool Success=false;
116 #if defined(_WIN_ALL)
117   HCRYPTPROV hProvider = 0;
118   if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
119   {
120     Success=CryptGenRandom(hProvider, (DWORD)BufSize, RndBuf) == TRUE;
121     CryptReleaseContext(hProvider, 0);
122   }
123 #elif defined(_UNIX)
124   FILE *rndf = fopen("/dev/urandom", "r");
125   if (rndf!=NULL)
126   {
127     Success=fread(RndBuf, BufSize, 1, rndf) == BufSize;
128     fclose(rndf);
129   }
130 #endif
131   // We use this code only as the last resort if code above failed.
132   if (!Success)
133     TimeRandomize(RndBuf,BufSize);
134 }
135