view 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
line wrap: on
line source
1 // 7zAes.cpp
3 #include "StdAfx.h"
5 extern "C"
6 {
7 #include "../../../C/Sha256.h"
8 }
10 #include "Windows/Synchronization.h"
11 #include "../Common/StreamObjects.h"
12 #include "../Common/StreamUtils.h"
13 #include "7zAes.h"
14 #include "MyAes.h"
16 #ifndef EXTRACT_ONLY
17 #include "RandGen.h"
18 #endif
20 using namespace NWindows;
22 namespace NCrypto {
23 namespace NSevenZ {
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 }
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 }
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 }
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 }
95 static CKeyInfoCache g_GlobalKeyCache(32);
96 static NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;
98 CBase::CBase():
99 _cachedKeys(16),
100 _ivSize(0)
101 {
102 for (int i = 0; i < sizeof(_iv); i++)
103 _iv[i] = 0;
104 }
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 }
122 #ifndef EXTRACT_ONLY
124 /*
125 STDMETHODIMP CEncoder::ResetSalt()
126 {
127 _key.SaltSize = 4;
128 g_RandomGenerator.Generate(_key.Salt, _key.SaltSize);
129 return S_OK;
130 }
131 */
133 STDMETHODIMP CEncoder::ResetInitVector()
134 {
135 _ivSize = 8;
136 g_RandomGenerator.Generate(_iv, (unsigned)_ivSize);
137 return S_OK;
138 }
140 STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
141 {
142 // _key.Init();
143 for (UInt32 i = _ivSize; i < sizeof(_iv); i++)
144 _iv[i] = 0;
146 UInt32 ivSize = _ivSize;
148 // _key.NumCyclesPower = 0x3F;
149 _key.NumCyclesPower = 19;
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 }
172 HRESULT CEncoder::CreateFilter()
173 {
174 _aesFilter = new CAesCbcEncoder;
175 return S_OK;
176 }
178 #endif
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++];
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;
197 if (pos >= size)
198 return E_INVALIDARG;
199 Byte secondByte = data[pos++];
201 _key.SaltSize += (secondByte >> 4);
202 ivSize += (secondByte & 0x0F);
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 }
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 }
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 }
234 STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size)
235 {
236 return _aesFilter->Filter(data, size);
237 }
239 HRESULT CDecoder::CreateFilter()
240 {
241 _aesFilter = new CAesCbcDecoder;
242 return S_OK;
243 }
245 }}