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