xref: /aosp_15_r20/external/lzma/CPP/7zip/Crypto/RarAes.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // Crypto/RarAes.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/RotateDefs.h"
7*f6dc9357SAndroid Build Coastguard Worker 
8*f6dc9357SAndroid Build Coastguard Worker #include "RarAes.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "Sha1Cls.h"
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker namespace NCrypto {
12*f6dc9357SAndroid Build Coastguard Worker namespace NRar3 {
13*f6dc9357SAndroid Build Coastguard Worker 
CDecoder()14*f6dc9357SAndroid Build Coastguard Worker CDecoder::CDecoder():
15*f6dc9357SAndroid Build Coastguard Worker     CAesCbcDecoder(kAesKeySize),
16*f6dc9357SAndroid Build Coastguard Worker     _thereIsSalt(false),
17*f6dc9357SAndroid Build Coastguard Worker     _needCalc(true)
18*f6dc9357SAndroid Build Coastguard Worker     // _rar350Mode(false)
19*f6dc9357SAndroid Build Coastguard Worker {
20*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < sizeof(_salt); i++)
21*f6dc9357SAndroid Build Coastguard Worker     _salt[i] = 0;
22*f6dc9357SAndroid Build Coastguard Worker }
23*f6dc9357SAndroid Build Coastguard Worker 
SetDecoderProperties2(const Byte * data,UInt32 size)24*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
25*f6dc9357SAndroid Build Coastguard Worker {
26*f6dc9357SAndroid Build Coastguard Worker   bool prev = _thereIsSalt;
27*f6dc9357SAndroid Build Coastguard Worker   _thereIsSalt = false;
28*f6dc9357SAndroid Build Coastguard Worker   if (size == 0)
29*f6dc9357SAndroid Build Coastguard Worker   {
30*f6dc9357SAndroid Build Coastguard Worker     if (!_needCalc && prev)
31*f6dc9357SAndroid Build Coastguard Worker       _needCalc = true;
32*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
33*f6dc9357SAndroid Build Coastguard Worker   }
34*f6dc9357SAndroid Build Coastguard Worker   if (size < 8)
35*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
36*f6dc9357SAndroid Build Coastguard Worker   _thereIsSalt = true;
37*f6dc9357SAndroid Build Coastguard Worker   bool same = false;
38*f6dc9357SAndroid Build Coastguard Worker   if (_thereIsSalt == prev)
39*f6dc9357SAndroid Build Coastguard Worker   {
40*f6dc9357SAndroid Build Coastguard Worker     same = true;
41*f6dc9357SAndroid Build Coastguard Worker     if (_thereIsSalt)
42*f6dc9357SAndroid Build Coastguard Worker     {
43*f6dc9357SAndroid Build Coastguard Worker       for (unsigned i = 0; i < sizeof(_salt); i++)
44*f6dc9357SAndroid Build Coastguard Worker         if (_salt[i] != data[i])
45*f6dc9357SAndroid Build Coastguard Worker         {
46*f6dc9357SAndroid Build Coastguard Worker           same = false;
47*f6dc9357SAndroid Build Coastguard Worker           break;
48*f6dc9357SAndroid Build Coastguard Worker         }
49*f6dc9357SAndroid Build Coastguard Worker     }
50*f6dc9357SAndroid Build Coastguard Worker   }
51*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < sizeof(_salt); i++)
52*f6dc9357SAndroid Build Coastguard Worker     _salt[i] = data[i];
53*f6dc9357SAndroid Build Coastguard Worker   if (!_needCalc && !same)
54*f6dc9357SAndroid Build Coastguard Worker     _needCalc = true;
55*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
56*f6dc9357SAndroid Build Coastguard Worker }
57*f6dc9357SAndroid Build Coastguard Worker 
58*f6dc9357SAndroid Build Coastguard Worker static const unsigned kPasswordLen_Bytes_MAX = 127 * 2;
59*f6dc9357SAndroid Build Coastguard Worker 
SetPassword(const Byte * data,unsigned size)60*f6dc9357SAndroid Build Coastguard Worker void CDecoder::SetPassword(const Byte *data, unsigned size)
61*f6dc9357SAndroid Build Coastguard Worker {
62*f6dc9357SAndroid Build Coastguard Worker   if (size > kPasswordLen_Bytes_MAX)
63*f6dc9357SAndroid Build Coastguard Worker     size = kPasswordLen_Bytes_MAX;
64*f6dc9357SAndroid Build Coastguard Worker   bool same = false;
65*f6dc9357SAndroid Build Coastguard Worker   if (size == _password.Size())
66*f6dc9357SAndroid Build Coastguard Worker   {
67*f6dc9357SAndroid Build Coastguard Worker     same = true;
68*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 i = 0; i < size; i++)
69*f6dc9357SAndroid Build Coastguard Worker       if (data[i] != _password[i])
70*f6dc9357SAndroid Build Coastguard Worker       {
71*f6dc9357SAndroid Build Coastguard Worker         same = false;
72*f6dc9357SAndroid Build Coastguard Worker         break;
73*f6dc9357SAndroid Build Coastguard Worker       }
74*f6dc9357SAndroid Build Coastguard Worker   }
75*f6dc9357SAndroid Build Coastguard Worker   if (!_needCalc && !same)
76*f6dc9357SAndroid Build Coastguard Worker     _needCalc = true;
77*f6dc9357SAndroid Build Coastguard Worker   _password.Wipe();
78*f6dc9357SAndroid Build Coastguard Worker   _password.CopyFrom(data, (size_t)size);
79*f6dc9357SAndroid Build Coastguard Worker }
80*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CDecoder::Init ())81*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::Init())
82*f6dc9357SAndroid Build Coastguard Worker {
83*f6dc9357SAndroid Build Coastguard Worker   CalcKey();
84*f6dc9357SAndroid Build Coastguard Worker   RINOK(SetKey(_key, kAesKeySize))
85*f6dc9357SAndroid Build Coastguard Worker   RINOK(SetInitVector(_iv, AES_BLOCK_SIZE))
86*f6dc9357SAndroid Build Coastguard Worker   return CAesCoder::Init();
87*f6dc9357SAndroid Build Coastguard Worker }
88*f6dc9357SAndroid Build Coastguard Worker 
89*f6dc9357SAndroid Build Coastguard Worker 
90*f6dc9357SAndroid Build Coastguard Worker // if (password_size_in_bytes + SaltSize > 64),
91*f6dc9357SAndroid Build Coastguard Worker // the original rar code updates password_with_salt buffer
92*f6dc9357SAndroid Build Coastguard Worker // with some generated data from SHA1 code.
93*f6dc9357SAndroid Build Coastguard Worker 
94*f6dc9357SAndroid Build Coastguard Worker // #define RAR_SHA1_REDUCE
95*f6dc9357SAndroid Build Coastguard Worker 
96*f6dc9357SAndroid Build Coastguard Worker #ifdef RAR_SHA1_REDUCE
97*f6dc9357SAndroid Build Coastguard Worker   #define kNumW 16
98*f6dc9357SAndroid Build Coastguard Worker   #define WW(i) W[(i)&15]
99*f6dc9357SAndroid Build Coastguard Worker #else
100*f6dc9357SAndroid Build Coastguard Worker   #define kNumW 80
101*f6dc9357SAndroid Build Coastguard Worker   #define WW(i) W[i]
102*f6dc9357SAndroid Build Coastguard Worker #endif
103*f6dc9357SAndroid Build Coastguard Worker 
UpdatePswDataSha1(Byte * data)104*f6dc9357SAndroid Build Coastguard Worker static void UpdatePswDataSha1(Byte *data)
105*f6dc9357SAndroid Build Coastguard Worker {
106*f6dc9357SAndroid Build Coastguard Worker   UInt32 W[kNumW];
107*f6dc9357SAndroid Build Coastguard Worker   size_t i;
108*f6dc9357SAndroid Build Coastguard Worker 
109*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)
110*f6dc9357SAndroid Build Coastguard Worker     W[i] = GetBe32(data + i * 4);
111*f6dc9357SAndroid Build Coastguard Worker 
112*f6dc9357SAndroid Build Coastguard Worker   for (i = 16; i < 80; i++)
113*f6dc9357SAndroid Build Coastguard Worker   {
114*f6dc9357SAndroid Build Coastguard Worker     const UInt32 t = WW((i)-3) ^ WW((i)-8) ^ WW((i)-14) ^ WW((i)-16);
115*f6dc9357SAndroid Build Coastguard Worker     WW(i) = rotlFixed(t, 1);
116*f6dc9357SAndroid Build Coastguard Worker   }
117*f6dc9357SAndroid Build Coastguard Worker 
118*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)
119*f6dc9357SAndroid Build Coastguard Worker   {
120*f6dc9357SAndroid Build Coastguard Worker     SetUi32(data + i * 4, W[kNumW - SHA1_NUM_BLOCK_WORDS + i])
121*f6dc9357SAndroid Build Coastguard Worker   }
122*f6dc9357SAndroid Build Coastguard Worker }
123*f6dc9357SAndroid Build Coastguard Worker 
124*f6dc9357SAndroid Build Coastguard Worker 
CalcKey()125*f6dc9357SAndroid Build Coastguard Worker void CDecoder::CalcKey()
126*f6dc9357SAndroid Build Coastguard Worker {
127*f6dc9357SAndroid Build Coastguard Worker   if (!_needCalc)
128*f6dc9357SAndroid Build Coastguard Worker     return;
129*f6dc9357SAndroid Build Coastguard Worker 
130*f6dc9357SAndroid Build Coastguard Worker   const unsigned kSaltSize = 8;
131*f6dc9357SAndroid Build Coastguard Worker 
132*f6dc9357SAndroid Build Coastguard Worker   MY_ALIGN (16)
133*f6dc9357SAndroid Build Coastguard Worker   Byte buf[kPasswordLen_Bytes_MAX + kSaltSize];
134*f6dc9357SAndroid Build Coastguard Worker 
135*f6dc9357SAndroid Build Coastguard Worker   if (_password.Size() != 0)
136*f6dc9357SAndroid Build Coastguard Worker     memcpy(buf, _password, _password.Size());
137*f6dc9357SAndroid Build Coastguard Worker 
138*f6dc9357SAndroid Build Coastguard Worker   size_t rawSize = _password.Size();
139*f6dc9357SAndroid Build Coastguard Worker 
140*f6dc9357SAndroid Build Coastguard Worker   if (_thereIsSalt)
141*f6dc9357SAndroid Build Coastguard Worker   {
142*f6dc9357SAndroid Build Coastguard Worker     memcpy(buf + rawSize, _salt, kSaltSize);
143*f6dc9357SAndroid Build Coastguard Worker     rawSize += kSaltSize;
144*f6dc9357SAndroid Build Coastguard Worker   }
145*f6dc9357SAndroid Build Coastguard Worker 
146*f6dc9357SAndroid Build Coastguard Worker   MY_ALIGN (16)
147*f6dc9357SAndroid Build Coastguard Worker   NSha1::CContext sha;
148*f6dc9357SAndroid Build Coastguard Worker   sha.Init();
149*f6dc9357SAndroid Build Coastguard Worker 
150*f6dc9357SAndroid Build Coastguard Worker   MY_ALIGN (16)
151*f6dc9357SAndroid Build Coastguard Worker   Byte digest[NSha1::kDigestSize];
152*f6dc9357SAndroid Build Coastguard Worker   // rar reverts hash for sha.
153*f6dc9357SAndroid Build Coastguard Worker   const UInt32 kNumRounds = (UInt32)1 << 18;
154*f6dc9357SAndroid Build Coastguard Worker   UInt32 pos = 0;
155*f6dc9357SAndroid Build Coastguard Worker   UInt32 i;
156*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < kNumRounds; i++)
157*f6dc9357SAndroid Build Coastguard Worker   {
158*f6dc9357SAndroid Build Coastguard Worker     sha.Update(buf, rawSize);
159*f6dc9357SAndroid Build Coastguard Worker     // if (_rar350Mode)
160*f6dc9357SAndroid Build Coastguard Worker     {
161*f6dc9357SAndroid Build Coastguard Worker       const UInt32 kBlockSize = 64;
162*f6dc9357SAndroid Build Coastguard Worker       const UInt32 endPos = (pos + (UInt32)rawSize) & ~(kBlockSize - 1);
163*f6dc9357SAndroid Build Coastguard Worker       if (endPos > pos + kBlockSize)
164*f6dc9357SAndroid Build Coastguard Worker       {
165*f6dc9357SAndroid Build Coastguard Worker         UInt32 curPos = pos & ~(kBlockSize - 1);
166*f6dc9357SAndroid Build Coastguard Worker         curPos += kBlockSize;
167*f6dc9357SAndroid Build Coastguard Worker         do
168*f6dc9357SAndroid Build Coastguard Worker         {
169*f6dc9357SAndroid Build Coastguard Worker           UpdatePswDataSha1(buf + (curPos - pos));
170*f6dc9357SAndroid Build Coastguard Worker           curPos += kBlockSize;
171*f6dc9357SAndroid Build Coastguard Worker         }
172*f6dc9357SAndroid Build Coastguard Worker         while (curPos != endPos);
173*f6dc9357SAndroid Build Coastguard Worker       }
174*f6dc9357SAndroid Build Coastguard Worker     }
175*f6dc9357SAndroid Build Coastguard Worker     pos += (UInt32)rawSize;
176*f6dc9357SAndroid Build Coastguard Worker #if 1
177*f6dc9357SAndroid Build Coastguard Worker     UInt32 pswNum;
178*f6dc9357SAndroid Build Coastguard Worker     SetUi32a(&pswNum, i)
179*f6dc9357SAndroid Build Coastguard Worker     sha.Update((const Byte *)&pswNum, 3);
180*f6dc9357SAndroid Build Coastguard Worker #else
181*f6dc9357SAndroid Build Coastguard Worker     Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) };
182*f6dc9357SAndroid Build Coastguard Worker     sha.Update(pswNum, 3);
183*f6dc9357SAndroid Build Coastguard Worker #endif
184*f6dc9357SAndroid Build Coastguard Worker     pos += 3;
185*f6dc9357SAndroid Build Coastguard Worker     if (i % (kNumRounds / 16) == 0)
186*f6dc9357SAndroid Build Coastguard Worker     {
187*f6dc9357SAndroid Build Coastguard Worker       MY_ALIGN (16)
188*f6dc9357SAndroid Build Coastguard Worker       NSha1::CContext shaTemp = sha;
189*f6dc9357SAndroid Build Coastguard Worker       shaTemp.Final(digest);
190*f6dc9357SAndroid Build Coastguard Worker       _iv[i / (kNumRounds / 16)] = (Byte)digest[4 * 4 + 3];
191*f6dc9357SAndroid Build Coastguard Worker     }
192*f6dc9357SAndroid Build Coastguard Worker   }
193*f6dc9357SAndroid Build Coastguard Worker 
194*f6dc9357SAndroid Build Coastguard Worker   sha.Final(digest);
195*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < 4; i++)
196*f6dc9357SAndroid Build Coastguard Worker     for (unsigned j = 0; j < 4; j++)
197*f6dc9357SAndroid Build Coastguard Worker       _key[i * 4 + j] = (digest[i * 4 + 3 - j]);
198*f6dc9357SAndroid Build Coastguard Worker 
199*f6dc9357SAndroid Build Coastguard Worker   _needCalc = false;
200*f6dc9357SAndroid Build Coastguard Worker }
201*f6dc9357SAndroid Build Coastguard Worker 
202*f6dc9357SAndroid Build Coastguard Worker }}
203