Mercurial > vba-linux
comparison src/win32/7zip/7z/CPP/7zip/Crypto/WzAes.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 // Crypto/WzAes.cpp | |
2 /* | |
3 This code implements Brian Gladman's scheme | |
4 specified in password Based File Encryption Utility. | |
5 | |
6 Note: you must include MyAes.cpp to project to initialize AES tables | |
7 */ | |
8 | |
9 #include "StdAfx.h" | |
10 | |
11 #include "../Common/StreamObjects.h" | |
12 #include "../Common/StreamUtils.h" | |
13 | |
14 #include "Pbkdf2HmacSha1.h" | |
15 #include "RandGen.h" | |
16 #include "WzAes.h" | |
17 | |
18 // define it if you don't want to use speed-optimized version of Pbkdf2HmacSha1 | |
19 // #define _NO_WZAES_OPTIMIZATIONS | |
20 | |
21 namespace NCrypto { | |
22 namespace NWzAes { | |
23 | |
24 const unsigned int kAesKeySizeMax = 32; | |
25 | |
26 static const UInt32 kNumKeyGenIterations = 1000; | |
27 | |
28 STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size) | |
29 { | |
30 if(size > kPasswordSizeMax) | |
31 return E_INVALIDARG; | |
32 _key.Password.SetCapacity(size); | |
33 memcpy(_key.Password, data, size); | |
34 return S_OK; | |
35 } | |
36 | |
37 #define SetUi32(p, d) { UInt32 x = (d); (p)[0] = (Byte)x; (p)[1] = (Byte)(x >> 8); \ | |
38 (p)[2] = (Byte)(x >> 16); (p)[3] = (Byte)(x >> 24); } | |
39 | |
40 void CBaseCoder::EncryptData(Byte *data, UInt32 size) | |
41 { | |
42 unsigned int pos = _blockPos; | |
43 for (; size > 0; size--) | |
44 { | |
45 if (pos == AES_BLOCK_SIZE) | |
46 { | |
47 if (++_counter[0] == 0) | |
48 _counter[1]++; | |
49 UInt32 temp[4]; | |
50 Aes_Encode32(&Aes, temp, _counter); | |
51 SetUi32(_buffer, temp[0]); | |
52 SetUi32(_buffer + 4, temp[1]); | |
53 SetUi32(_buffer + 8, temp[2]); | |
54 SetUi32(_buffer + 12, temp[3]); | |
55 pos = 0; | |
56 } | |
57 *data++ ^= _buffer[pos++]; | |
58 } | |
59 _blockPos = pos; | |
60 } | |
61 | |
62 #ifndef _NO_WZAES_OPTIMIZATIONS | |
63 | |
64 static void BytesToBeUInt32s(const Byte *src, UInt32 *dest, int destSize) | |
65 { | |
66 for (int i = 0 ; i < destSize; i++) | |
67 dest[i] = | |
68 ((UInt32)(src[i * 4 + 0]) << 24) | | |
69 ((UInt32)(src[i * 4 + 1]) << 16) | | |
70 ((UInt32)(src[i * 4 + 2]) << 8) | | |
71 ((UInt32)(src[i * 4 + 3])); | |
72 } | |
73 | |
74 #endif | |
75 | |
76 STDMETHODIMP CBaseCoder::Init() | |
77 { | |
78 UInt32 keySize = _key.GetKeySize(); | |
79 UInt32 keysTotalSize = 2 * keySize + kPwdVerifCodeSize; | |
80 Byte buf[2 * kAesKeySizeMax + kPwdVerifCodeSize]; | |
81 | |
82 // for (int ii = 0; ii < 1000; ii++) | |
83 { | |
84 #ifdef _NO_WZAES_OPTIMIZATIONS | |
85 | |
86 NSha1::Pbkdf2Hmac( | |
87 _key.Password, _key.Password.GetCapacity(), | |
88 _key.Salt, _key.GetSaltSize(), | |
89 kNumKeyGenIterations, | |
90 buf, keysTotalSize); | |
91 | |
92 #else | |
93 | |
94 UInt32 buf32[(2 * kAesKeySizeMax + kPwdVerifCodeSize + 3) / 4]; | |
95 UInt32 key32SizeTotal = (keysTotalSize + 3) / 4; | |
96 UInt32 salt[kSaltSizeMax * 4]; | |
97 UInt32 saltSizeInWords = _key.GetSaltSize() / 4; | |
98 BytesToBeUInt32s(_key.Salt, salt, saltSizeInWords); | |
99 NSha1::Pbkdf2Hmac32( | |
100 _key.Password, _key.Password.GetCapacity(), | |
101 salt, saltSizeInWords, | |
102 kNumKeyGenIterations, | |
103 buf32, key32SizeTotal); | |
104 for (UInt32 j = 0; j < keysTotalSize; j++) | |
105 buf[j] = (Byte)(buf32[j / 4] >> (24 - 8 * (j & 3))); | |
106 | |
107 #endif | |
108 } | |
109 | |
110 _hmac.SetKey(buf + keySize, keySize); | |
111 memcpy(_key.PwdVerifComputed, buf + 2 * keySize, kPwdVerifCodeSize); | |
112 | |
113 _blockPos = AES_BLOCK_SIZE; | |
114 for (int i = 0; i < 4; i++) | |
115 _counter[i] = 0; | |
116 | |
117 Aes_SetKeyEncode(&Aes, buf, keySize); | |
118 return S_OK; | |
119 } | |
120 | |
121 /* | |
122 STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) | |
123 { | |
124 Byte keySizeMode = 3; | |
125 return outStream->Write(&keySizeMode, 1, NULL); | |
126 } | |
127 */ | |
128 | |
129 HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream) | |
130 { | |
131 UInt32 saltSize = _key.GetSaltSize(); | |
132 g_RandomGenerator.Generate(_key.Salt, saltSize); | |
133 Init(); | |
134 RINOK(WriteStream(outStream, _key.Salt, saltSize)); | |
135 return WriteStream(outStream, _key.PwdVerifComputed, kPwdVerifCodeSize); | |
136 } | |
137 | |
138 HRESULT CEncoder::WriteFooter(ISequentialOutStream *outStream) | |
139 { | |
140 Byte mac[kMacSize]; | |
141 _hmac.Final(mac, kMacSize); | |
142 return WriteStream(outStream, mac, kMacSize); | |
143 } | |
144 | |
145 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) | |
146 { | |
147 if (size != 1) | |
148 return E_INVALIDARG; | |
149 _key.Init(); | |
150 Byte keySizeMode = data[0]; | |
151 if (keySizeMode < 1 || keySizeMode > 3) | |
152 return E_INVALIDARG; | |
153 _key.KeySizeMode = keySizeMode; | |
154 return S_OK; | |
155 } | |
156 | |
157 HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream) | |
158 { | |
159 UInt32 saltSize = _key.GetSaltSize(); | |
160 UInt32 extraSize = saltSize + kPwdVerifCodeSize; | |
161 Byte temp[kSaltSizeMax + kPwdVerifCodeSize]; | |
162 RINOK(ReadStream_FAIL(inStream, temp, extraSize)); | |
163 UInt32 i; | |
164 for (i = 0; i < saltSize; i++) | |
165 _key.Salt[i] = temp[i]; | |
166 for (i = 0; i < kPwdVerifCodeSize; i++) | |
167 _pwdVerifFromArchive[i] = temp[saltSize + i]; | |
168 return S_OK; | |
169 } | |
170 | |
171 static bool CompareArrays(const Byte *p1, const Byte *p2, UInt32 size) | |
172 { | |
173 for (UInt32 i = 0; i < size; i++) | |
174 if (p1[i] != p2[i]) | |
175 return false; | |
176 return true; | |
177 } | |
178 | |
179 bool CDecoder::CheckPasswordVerifyCode() | |
180 { | |
181 return CompareArrays(_key.PwdVerifComputed, _pwdVerifFromArchive, kPwdVerifCodeSize); | |
182 } | |
183 | |
184 HRESULT CDecoder::CheckMac(ISequentialInStream *inStream, bool &isOK) | |
185 { | |
186 isOK = false; | |
187 Byte mac1[kMacSize]; | |
188 RINOK(ReadStream_FAIL(inStream, mac1, kMacSize)); | |
189 Byte mac2[kMacSize]; | |
190 _hmac.Final(mac2, kMacSize); | |
191 isOK = CompareArrays(mac1, mac2, kMacSize); | |
192 return S_OK; | |
193 } | |
194 | |
195 STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size) | |
196 { | |
197 EncryptData(data, size); | |
198 _hmac.Update(data, size); | |
199 return size; | |
200 } | |
201 | |
202 STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size) | |
203 { | |
204 _hmac.Update(data, size); | |
205 EncryptData(data, size); | |
206 return size; | |
207 } | |
208 | |
209 }} |