Mercurial > vba-linux
comparison src/win32/7zip/7z/CPP/7zip/Crypto/7zAes.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // 7zAes.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 extern "C" | |
6 { | |
7 #include "../../../C/Sha256.h" | |
8 } | |
9 | |
10 #include "Windows/Synchronization.h" | |
11 #include "../Common/StreamObjects.h" | |
12 #include "../Common/StreamUtils.h" | |
13 #include "7zAes.h" | |
14 #include "MyAes.h" | |
15 | |
16 #ifndef EXTRACT_ONLY | |
17 #include "RandGen.h" | |
18 #endif | |
19 | |
20 using namespace NWindows; | |
21 | |
22 namespace NCrypto { | |
23 namespace NSevenZ { | |
24 | |
25 bool CKeyInfo::IsEqualTo(const CKeyInfo &a) const | |
26 { | |
27 if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower) | |
28 return false; | |
29 for (UInt32 i = 0; i < SaltSize; i++) | |
30 if (Salt[i] != a.Salt[i]) | |
31 return false; | |
32 return (Password == a.Password); | |
33 } | |
34 | |
35 void CKeyInfo::CalculateDigest() | |
36 { | |
37 if (NumCyclesPower == 0x3F) | |
38 { | |
39 UInt32 pos; | |
40 for (pos = 0; pos < SaltSize; pos++) | |
41 Key[pos] = Salt[pos]; | |
42 for (UInt32 i = 0; i < Password.GetCapacity() && pos < kKeySize; i++) | |
43 Key[pos++] = Password[i]; | |
44 for (; pos < kKeySize; pos++) | |
45 Key[pos] = 0; | |
46 } | |
47 else | |
48 { | |
49 CSha256 sha; | |
50 Sha256_Init(&sha); | |
51 const UInt64 numRounds = UInt64(1) << (NumCyclesPower); | |
52 Byte temp[8] = { 0,0,0,0,0,0,0,0 }; | |
53 for (UInt64 round = 0; round < numRounds; round++) | |
54 { | |
55 Sha256_Update(&sha, Salt, (size_t)SaltSize); | |
56 Sha256_Update(&sha, Password, Password.GetCapacity()); | |
57 Sha256_Update(&sha, temp, 8); | |
58 for (int i = 0; i < 8; i++) | |
59 if (++(temp[i]) != 0) | |
60 break; | |
61 } | |
62 Sha256_Final(&sha, Key); | |
63 } | |
64 } | |
65 | |
66 bool CKeyInfoCache::Find(CKeyInfo &key) | |
67 { | |
68 for (int i = 0; i < Keys.Size(); i++) | |
69 { | |
70 const CKeyInfo &cached = Keys[i]; | |
71 if (key.IsEqualTo(cached)) | |
72 { | |
73 for (int j = 0; j < kKeySize; j++) | |
74 key.Key[j] = cached.Key[j]; | |
75 if (i != 0) | |
76 { | |
77 Keys.Insert(0, cached); | |
78 Keys.Delete(i+1); | |
79 } | |
80 return true; | |
81 } | |
82 } | |
83 return false; | |
84 } | |
85 | |
86 void CKeyInfoCache::Add(CKeyInfo &key) | |
87 { | |
88 if (Find(key)) | |
89 return; | |
90 if (Keys.Size() >= Size) | |
91 Keys.DeleteBack(); | |
92 Keys.Insert(0, key); | |
93 } | |
94 | |
95 static CKeyInfoCache g_GlobalKeyCache(32); | |
96 static NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection; | |
97 | |
98 CBase::CBase(): | |
99 _cachedKeys(16), | |
100 _ivSize(0) | |
101 { | |
102 for (int i = 0; i < sizeof(_iv); i++) | |
103 _iv[i] = 0; | |
104 } | |
105 | |
106 void CBase::CalculateDigest() | |
107 { | |
108 NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection); | |
109 if (_cachedKeys.Find(_key)) | |
110 g_GlobalKeyCache.Add(_key); | |
111 else | |
112 { | |
113 if (!g_GlobalKeyCache.Find(_key)) | |
114 { | |
115 _key.CalculateDigest(); | |
116 g_GlobalKeyCache.Add(_key); | |
117 } | |
118 _cachedKeys.Add(_key); | |
119 } | |
120 } | |
121 | |
122 #ifndef EXTRACT_ONLY | |
123 | |
124 /* | |
125 STDMETHODIMP CEncoder::ResetSalt() | |
126 { | |
127 _key.SaltSize = 4; | |
128 g_RandomGenerator.Generate(_key.Salt, _key.SaltSize); | |
129 return S_OK; | |
130 } | |
131 */ | |
132 | |
133 STDMETHODIMP CEncoder::ResetInitVector() | |
134 { | |
135 _ivSize = 8; | |
136 g_RandomGenerator.Generate(_iv, (unsigned)_ivSize); | |
137 return S_OK; | |
138 } | |
139 | |
140 STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) | |
141 { | |
142 // _key.Init(); | |
143 for (UInt32 i = _ivSize; i < sizeof(_iv); i++) | |
144 _iv[i] = 0; | |
145 | |
146 UInt32 ivSize = _ivSize; | |
147 | |
148 // _key.NumCyclesPower = 0x3F; | |
149 _key.NumCyclesPower = 19; | |
150 | |
151 Byte firstByte = (Byte)(_key.NumCyclesPower | | |
152 (((_key.SaltSize == 0) ? 0 : 1) << 7) | | |
153 (((ivSize == 0) ? 0 : 1) << 6)); | |
154 RINOK(outStream->Write(&firstByte, 1, NULL)); | |
155 if (_key.SaltSize == 0 && ivSize == 0) | |
156 return S_OK; | |
157 Byte saltSizeSpec = (Byte)((_key.SaltSize == 0) ? 0 : (_key.SaltSize - 1)); | |
158 Byte ivSizeSpec = (Byte)((ivSize == 0) ? 0 : (ivSize - 1)); | |
159 Byte secondByte = (Byte)(((saltSizeSpec) << 4) | ivSizeSpec); | |
160 RINOK(outStream->Write(&secondByte, 1, NULL)); | |
161 if (_key.SaltSize > 0) | |
162 { | |
163 RINOK(WriteStream(outStream, _key.Salt, _key.SaltSize)); | |
164 } | |
165 if (ivSize > 0) | |
166 { | |
167 RINOK(WriteStream(outStream, _iv, ivSize)); | |
168 } | |
169 return S_OK; | |
170 } | |
171 | |
172 HRESULT CEncoder::CreateFilter() | |
173 { | |
174 _aesFilter = new CAesCbcEncoder; | |
175 return S_OK; | |
176 } | |
177 | |
178 #endif | |
179 | |
180 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) | |
181 { | |
182 _key.Init(); | |
183 UInt32 i; | |
184 for (i = 0; i < sizeof(_iv); i++) | |
185 _iv[i] = 0; | |
186 if (size == 0) | |
187 return S_OK; | |
188 UInt32 pos = 0; | |
189 Byte firstByte = data[pos++]; | |
190 | |
191 _key.NumCyclesPower = firstByte & 0x3F; | |
192 if ((firstByte & 0xC0) == 0) | |
193 return S_OK; | |
194 _key.SaltSize = (firstByte >> 7) & 1; | |
195 UInt32 ivSize = (firstByte >> 6) & 1; | |
196 | |
197 if (pos >= size) | |
198 return E_INVALIDARG; | |
199 Byte secondByte = data[pos++]; | |
200 | |
201 _key.SaltSize += (secondByte >> 4); | |
202 ivSize += (secondByte & 0x0F); | |
203 | |
204 if (pos + _key.SaltSize + ivSize > size) | |
205 return E_INVALIDARG; | |
206 for (i = 0; i < _key.SaltSize; i++) | |
207 _key.Salt[i] = data[pos++]; | |
208 for (i = 0; i < ivSize; i++) | |
209 _iv[i] = data[pos++]; | |
210 return S_OK; | |
211 } | |
212 | |
213 STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size) | |
214 { | |
215 _key.Password.SetCapacity((size_t)size); | |
216 memcpy(_key.Password, data, (size_t)size); | |
217 return S_OK; | |
218 } | |
219 | |
220 STDMETHODIMP CBaseCoder::Init() | |
221 { | |
222 CalculateDigest(); | |
223 if (_aesFilter == 0) | |
224 { | |
225 RINOK(CreateFilter()); | |
226 } | |
227 CMyComPtr<ICryptoProperties> cp; | |
228 RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp)); | |
229 RINOK(cp->SetKey(_key.Key, sizeof(_key.Key))); | |
230 RINOK(cp->SetInitVector(_iv, sizeof(_iv))); | |
231 return S_OK; | |
232 } | |
233 | |
234 STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size) | |
235 { | |
236 return _aesFilter->Filter(data, size); | |
237 } | |
238 | |
239 HRESULT CDecoder::CreateFilter() | |
240 { | |
241 _aesFilter = new CAesCbcDecoder; | |
242 return S_OK; | |
243 } | |
244 | |
245 }} |