/src/xpdf-4.05/xpdf/Decrypt.cc
Line | Count | Source |
1 | | //======================================================================== |
2 | | // |
3 | | // Decrypt.cc |
4 | | // |
5 | | // Copyright 1996-2003 Glyph & Cog, LLC |
6 | | // |
7 | | //======================================================================== |
8 | | |
9 | | #include <aconf.h> |
10 | | |
11 | | #include <string.h> |
12 | | #include "gmem.h" |
13 | | #include "gmempp.h" |
14 | | #include "Decrypt.h" |
15 | | |
16 | | static void aes256KeyExpansion(DecryptAES256State *s, |
17 | | Guchar *objKey, int objKeyLen); |
18 | | static void aes256DecryptBlock(DecryptAES256State *s, Guchar *in, GBool last); |
19 | | static void sha256(Guchar *msg, int msgLen, Guchar *hash); |
20 | | static void sha384(Guchar *msg, int msgLen, Guchar *hash); |
21 | | static void sha512(Guchar *msg, int msgLen, Guchar *hash); |
22 | | |
23 | | static Guchar passwordPad[32] = { |
24 | | 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, |
25 | | 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, |
26 | | 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, |
27 | | 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a |
28 | | }; |
29 | | |
30 | | //------------------------------------------------------------------------ |
31 | | // Decrypt |
32 | | //------------------------------------------------------------------------ |
33 | | |
34 | | GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, |
35 | | GString *ownerKey, GString *userKey, |
36 | | GString *ownerEnc, GString *userEnc, |
37 | | int permissions, GString *fileID, |
38 | | GString *ownerPassword, GString *userPassword, |
39 | | Guchar *fileKey, GBool encryptMetadata, |
40 | 115 | GBool *ownerPasswordOk) { |
41 | 115 | DecryptAES256State state; |
42 | 115 | Guchar test[127 + 56], test2[32]; |
43 | 115 | GString *userPassword2; |
44 | 115 | const char *userPW; |
45 | 115 | Guchar fState[256]; |
46 | 115 | Guchar tmpKey[16]; |
47 | 115 | Guchar fx, fy; |
48 | 115 | int len, i, j; |
49 | | |
50 | 115 | *ownerPasswordOk = gFalse; |
51 | | |
52 | 115 | if (encRevision == 5 || encRevision == 6) { |
53 | | |
54 | | // check the owner password |
55 | 77 | if (ownerPassword) { |
56 | | //~ this is supposed to convert the password to UTF-8 using "SASLprep" |
57 | 0 | len = ownerPassword->getLength(); |
58 | 0 | if (len > 127) { |
59 | 0 | len = 127; |
60 | 0 | } |
61 | 0 | memcpy(test, ownerPassword->getCString(), len); |
62 | 0 | memcpy(test + len, ownerKey->getCString() + 32, 8); |
63 | 0 | memcpy(test + len + 8, userKey->getCString(), 48); |
64 | 0 | sha256(test, len + 56, test); |
65 | 0 | if (encRevision == 6) { |
66 | 0 | r6Hash(test, 32, ownerPassword->getCString(), len, |
67 | 0 | userKey->getCString()); |
68 | 0 | } |
69 | 0 | if (!memcmp(test, ownerKey->getCString(), 32)) { |
70 | | |
71 | | // compute the file key from the owner password |
72 | 0 | memcpy(test, ownerPassword->getCString(), len); |
73 | 0 | memcpy(test + len, ownerKey->getCString() + 40, 8); |
74 | 0 | memcpy(test + len + 8, userKey->getCString(), 48); |
75 | 0 | sha256(test, len + 56, test); |
76 | 0 | if (encRevision == 6) { |
77 | 0 | r6Hash(test, 32, ownerPassword->getCString(), len, |
78 | 0 | userKey->getCString()); |
79 | 0 | } |
80 | 0 | aes256KeyExpansion(&state, test, 32); |
81 | 0 | for (i = 0; i < 16; ++i) { |
82 | 0 | state.cbc[i] = 0; |
83 | 0 | } |
84 | 0 | aes256DecryptBlock(&state, (Guchar *)ownerEnc->getCString(), gFalse); |
85 | 0 | memcpy(fileKey, state.buf, 16); |
86 | 0 | aes256DecryptBlock(&state, (Guchar *)ownerEnc->getCString() + 16, |
87 | 0 | gFalse); |
88 | 0 | memcpy(fileKey + 16, state.buf, 16); |
89 | |
|
90 | 0 | *ownerPasswordOk = gTrue; |
91 | 0 | return gTrue; |
92 | 0 | } |
93 | 0 | } |
94 | | |
95 | | // check the user password |
96 | 77 | if (userPassword) { |
97 | | //~ this is supposed to convert the password to UTF-8 using "SASLprep" |
98 | 0 | userPW = userPassword->getCString(); |
99 | 0 | len = userPassword->getLength(); |
100 | 0 | if (len > 127) { |
101 | 0 | len = 127; |
102 | 0 | } |
103 | 77 | } else { |
104 | 77 | userPW = ""; |
105 | 77 | len = 0; |
106 | 77 | } |
107 | 77 | memcpy(test, userPW, len); |
108 | 77 | memcpy(test + len, userKey->getCString() + 32, 8); |
109 | 77 | sha256(test, len + 8, test); |
110 | 77 | if (encRevision == 6) { |
111 | 77 | r6Hash(test, 32, userPW, len, NULL); |
112 | 77 | } |
113 | 77 | if (!memcmp(test, userKey->getCString(), 32)) { |
114 | | |
115 | | // compute the file key from the user password |
116 | 76 | memcpy(test, userPW, len); |
117 | 76 | memcpy(test + len, userKey->getCString() + 40, 8); |
118 | 76 | sha256(test, len + 8, test); |
119 | 76 | if (encRevision == 6) { |
120 | 76 | r6Hash(test, 32, userPW, len, NULL); |
121 | 76 | } |
122 | 76 | aes256KeyExpansion(&state, test, 32); |
123 | 1.29k | for (i = 0; i < 16; ++i) { |
124 | 1.21k | state.cbc[i] = 0; |
125 | 1.21k | } |
126 | 76 | aes256DecryptBlock(&state, (Guchar *)userEnc->getCString(), gFalse); |
127 | 76 | memcpy(fileKey, state.buf, 16); |
128 | 76 | aes256DecryptBlock(&state, (Guchar *)userEnc->getCString() + 16, |
129 | 76 | gFalse); |
130 | 76 | memcpy(fileKey + 16, state.buf, 16); |
131 | | |
132 | 76 | return gTrue; |
133 | 76 | } |
134 | | |
135 | 1 | return gFalse; |
136 | | |
137 | 77 | } else { |
138 | | |
139 | | // try using the supplied owner password to generate the user password |
140 | 38 | if (ownerPassword) { |
141 | 0 | len = ownerPassword->getLength(); |
142 | 0 | if (len < 32) { |
143 | 0 | memcpy(test, ownerPassword->getCString(), len); |
144 | 0 | memcpy(test + len, passwordPad, 32 - len); |
145 | 0 | } else { |
146 | 0 | memcpy(test, ownerPassword->getCString(), 32); |
147 | 0 | } |
148 | 0 | md5(test, 32, test); |
149 | 0 | if (encRevision == 3) { |
150 | 0 | for (i = 0; i < 50; ++i) { |
151 | 0 | md5(test, keyLength, test); |
152 | 0 | } |
153 | 0 | } |
154 | 0 | if (encRevision == 2) { |
155 | 0 | rc4InitKey(test, keyLength, fState); |
156 | 0 | fx = fy = 0; |
157 | 0 | for (i = 0; i < 32; ++i) { |
158 | 0 | test2[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i)); |
159 | 0 | } |
160 | 0 | } else { |
161 | 0 | memcpy(test2, ownerKey->getCString(), 32); |
162 | 0 | for (i = 19; i >= 0; --i) { |
163 | 0 | for (j = 0; j < keyLength; ++j) { |
164 | 0 | tmpKey[j] = (Guchar)(test[j] ^ i); |
165 | 0 | } |
166 | 0 | rc4InitKey(tmpKey, keyLength, fState); |
167 | 0 | fx = fy = 0; |
168 | 0 | for (j = 0; j < 32; ++j) { |
169 | 0 | test2[j] = rc4DecryptByte(fState, &fx, &fy, test2[j]); |
170 | 0 | } |
171 | 0 | } |
172 | 0 | } |
173 | 0 | userPassword2 = new GString((char *)test2, 32); |
174 | 0 | if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey, |
175 | 0 | permissions, fileID, userPassword2, fileKey, |
176 | 0 | encryptMetadata)) { |
177 | 0 | *ownerPasswordOk = gTrue; |
178 | 0 | delete userPassword2; |
179 | 0 | return gTrue; |
180 | 0 | } |
181 | 0 | delete userPassword2; |
182 | 0 | } |
183 | | |
184 | | // try using the supplied user password |
185 | 38 | return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey, |
186 | 38 | permissions, fileID, userPassword, fileKey, |
187 | 38 | encryptMetadata); |
188 | 38 | } |
189 | 115 | } |
190 | | |
191 | | void Decrypt::r6Hash(Guchar *key, int keyLen, const char *pwd, int pwdLen, |
192 | 153 | char *userKey) { |
193 | 153 | Guchar key1[64*(127+64+48)]; |
194 | 153 | DecryptAESState state128; |
195 | 153 | int n, i, j, k; |
196 | | |
197 | 153 | i = 0; |
198 | 10.8k | while (1) { |
199 | 10.8k | memcpy(key1, pwd, pwdLen); |
200 | 10.8k | memcpy(key1 + pwdLen, key, keyLen); |
201 | 10.8k | n = pwdLen + keyLen; |
202 | 10.8k | if (userKey) { |
203 | 0 | memcpy(key1 + pwdLen + keyLen, userKey, 48); |
204 | 0 | n += 48; |
205 | 0 | } |
206 | 692k | for (j = 1; j < 64; ++j) { |
207 | 681k | memcpy(key1 + j * n, key1, n); |
208 | 681k | } |
209 | 10.8k | n *= 64; |
210 | 10.8k | aesKeyExpansion(&state128, key, 16, gFalse); |
211 | 183k | for (j = 0; j < 16; ++j) { |
212 | 173k | state128.cbc[j] = key[16+j]; |
213 | 173k | } |
214 | 2.06M | for (j = 0; j < n; j += 16) { |
215 | 2.05M | aesEncryptBlock(&state128, key1 + j); |
216 | 2.05M | memcpy(key1 + j, state128.buf, 16); |
217 | 2.05M | } |
218 | 10.8k | k = 0; |
219 | 183k | for (j = 0; j < 16; ++j) { |
220 | 173k | k += key1[j] % 3; |
221 | 173k | } |
222 | 10.8k | k %= 3; |
223 | 10.8k | switch (k) { |
224 | 3.46k | case 0: |
225 | 3.46k | sha256(key1, n, key); |
226 | 3.46k | keyLen = 32; |
227 | 3.46k | break; |
228 | 3.99k | case 1: |
229 | 3.99k | sha384(key1, n, key); |
230 | 3.99k | keyLen = 48; |
231 | 3.99k | break; |
232 | 3.35k | case 2: |
233 | 3.35k | sha512(key1, n, key); |
234 | 3.35k | keyLen = 64; |
235 | 3.35k | break; |
236 | 10.8k | } |
237 | | // from the spec, it appears that i should be incremented after |
238 | | // the test, but that doesn't match what Adobe does |
239 | 10.8k | ++i; |
240 | 10.8k | if (i >= 64 && key1[n - 1] <= i - 32) { |
241 | 153 | break; |
242 | 153 | } |
243 | 10.8k | } |
244 | 153 | } |
245 | | |
246 | | GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength, |
247 | | GString *ownerKey, GString *userKey, |
248 | | int permissions, GString *fileID, |
249 | | GString *userPassword, Guchar *fileKey, |
250 | 38 | GBool encryptMetadata) { |
251 | 38 | Guchar *buf; |
252 | 38 | Guchar test[32]; |
253 | 38 | Guchar fState[256]; |
254 | 38 | Guchar tmpKey[16]; |
255 | 38 | Guchar fx, fy; |
256 | 38 | int len, i, j; |
257 | 38 | GBool ok; |
258 | | |
259 | | // generate file key |
260 | 38 | buf = (Guchar *)gmalloc(72 + fileID->getLength()); |
261 | 38 | if (userPassword) { |
262 | 0 | len = userPassword->getLength(); |
263 | 0 | if (len < 32) { |
264 | 0 | memcpy(buf, userPassword->getCString(), len); |
265 | 0 | memcpy(buf + len, passwordPad, 32 - len); |
266 | 0 | } else { |
267 | 0 | memcpy(buf, userPassword->getCString(), 32); |
268 | 0 | } |
269 | 38 | } else { |
270 | 38 | memcpy(buf, passwordPad, 32); |
271 | 38 | } |
272 | 38 | memcpy(buf + 32, ownerKey->getCString(), 32); |
273 | 38 | buf[64] = (Guchar)(permissions & 0xff); |
274 | 38 | buf[65] = (Guchar)((permissions >> 8) & 0xff); |
275 | 38 | buf[66] = (Guchar)((permissions >> 16) & 0xff); |
276 | 38 | buf[67] = (Guchar)((permissions >> 24) & 0xff); |
277 | 38 | memcpy(buf + 68, fileID->getCString(), fileID->getLength()); |
278 | 38 | len = 68 + fileID->getLength(); |
279 | 38 | if (!encryptMetadata) { |
280 | 0 | buf[len++] = 0xff; |
281 | 0 | buf[len++] = 0xff; |
282 | 0 | buf[len++] = 0xff; |
283 | 0 | buf[len++] = 0xff; |
284 | 0 | } |
285 | 38 | md5(buf, len, fileKey); |
286 | 38 | if (encRevision == 3) { |
287 | 1.93k | for (i = 0; i < 50; ++i) { |
288 | 1.90k | md5(fileKey, keyLength, fileKey); |
289 | 1.90k | } |
290 | 38 | } |
291 | | |
292 | | // test user password |
293 | 38 | if (encRevision == 2) { |
294 | 0 | rc4InitKey(fileKey, keyLength, fState); |
295 | 0 | fx = fy = 0; |
296 | 0 | for (i = 0; i < 32; ++i) { |
297 | 0 | test[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i)); |
298 | 0 | } |
299 | 0 | ok = memcmp(test, passwordPad, 32) == 0; |
300 | 38 | } else if (encRevision == 3) { |
301 | 38 | memcpy(test, userKey->getCString(), 32); |
302 | 798 | for (i = 19; i >= 0; --i) { |
303 | 11.7k | for (j = 0; j < keyLength; ++j) { |
304 | 10.9k | tmpKey[j] = (Guchar)(fileKey[j] ^ i); |
305 | 10.9k | } |
306 | 760 | rc4InitKey(tmpKey, keyLength, fState); |
307 | 760 | fx = fy = 0; |
308 | 25.0k | for (j = 0; j < 32; ++j) { |
309 | 24.3k | test[j] = rc4DecryptByte(fState, &fx, &fy, test[j]); |
310 | 24.3k | } |
311 | 760 | } |
312 | 38 | memcpy(buf, passwordPad, 32); |
313 | 38 | memcpy(buf + 32, fileID->getCString(), fileID->getLength()); |
314 | 38 | md5(buf, 32 + fileID->getLength(), buf); |
315 | 38 | ok = memcmp(test, buf, 16) == 0; |
316 | 38 | } else { |
317 | 0 | ok = gFalse; |
318 | 0 | } |
319 | | |
320 | 38 | gfree(buf); |
321 | 38 | return ok; |
322 | 38 | } |
323 | | |
324 | | //------------------------------------------------------------------------ |
325 | | // DecryptStream |
326 | | //------------------------------------------------------------------------ |
327 | | |
328 | | DecryptStream::DecryptStream(Stream *strA, Guchar *fileKeyA, |
329 | | CryptAlgorithm algoA, int keyLengthA, |
330 | | int objNumA, int objGenA): |
331 | 59.3k | FilterStream(strA) |
332 | 59.3k | { |
333 | 59.3k | int i; |
334 | | |
335 | 59.3k | memcpy(fileKey, fileKeyA, keyLengthA); |
336 | 59.3k | algo = algoA; |
337 | 59.3k | keyLength = keyLengthA; |
338 | 59.3k | objNum = objNumA; |
339 | 59.3k | objGen = objGenA; |
340 | | |
341 | | // construct object key |
342 | 1.77M | for (i = 0; i < keyLength; ++i) { |
343 | 1.71M | objKey[i] = fileKey[i]; |
344 | 1.71M | } |
345 | 59.3k | switch (algo) { |
346 | 5.69k | case cryptRC4: |
347 | 5.69k | objKey[keyLength] = (Guchar)(objNum & 0xff); |
348 | 5.69k | objKey[keyLength + 1] = (Guchar)((objNum >> 8) & 0xff); |
349 | 5.69k | objKey[keyLength + 2] = (Guchar)((objNum >> 16) & 0xff); |
350 | 5.69k | objKey[keyLength + 3] = (Guchar)(objGen & 0xff); |
351 | 5.69k | objKey[keyLength + 4] = (Guchar)((objGen >> 8) & 0xff); |
352 | 5.69k | md5(objKey, keyLength + 5, objKey); |
353 | 5.69k | if ((objKeyLength = keyLength + 5) > 16) { |
354 | 4.00k | objKeyLength = 16; |
355 | 4.00k | } |
356 | 5.69k | break; |
357 | 8.26k | case cryptAES: |
358 | 8.26k | objKey[keyLength] = (Guchar)(objNum & 0xff); |
359 | 8.26k | objKey[keyLength + 1] = (Guchar)((objNum >> 8) & 0xff); |
360 | 8.26k | objKey[keyLength + 2] = (Guchar)((objNum >> 16) & 0xff); |
361 | 8.26k | objKey[keyLength + 3] = (Guchar)(objGen & 0xff); |
362 | 8.26k | objKey[keyLength + 4] = (Guchar)((objGen >> 8) & 0xff); |
363 | 8.26k | objKey[keyLength + 5] = 0x73; // 's' |
364 | 8.26k | objKey[keyLength + 6] = 0x41; // 'A' |
365 | 8.26k | objKey[keyLength + 7] = 0x6c; // 'l' |
366 | 8.26k | objKey[keyLength + 8] = 0x54; // 'T' |
367 | 8.26k | md5(objKey, keyLength + 9, objKey); |
368 | 8.26k | if ((objKeyLength = keyLength + 5) > 16) { |
369 | 8.26k | objKeyLength = 16; |
370 | 8.26k | } |
371 | 8.26k | break; |
372 | 45.3k | case cryptAES256: |
373 | 45.3k | objKeyLength = keyLength; |
374 | 45.3k | break; |
375 | 59.3k | } |
376 | 59.3k | } |
377 | | |
378 | 57.7k | DecryptStream::~DecryptStream() { |
379 | 57.7k | delete str; |
380 | 57.7k | } |
381 | | |
382 | 874 | Stream *DecryptStream::copy() { |
383 | 874 | return new DecryptStream(str->copy(), fileKey, algo, keyLength, |
384 | 874 | objNum, objGen); |
385 | 874 | } |
386 | | |
387 | 36.3k | void DecryptStream::reset() { |
388 | 36.3k | str->reset(); |
389 | 36.3k | switch (algo) { |
390 | 4.88k | case cryptRC4: |
391 | 4.88k | state.rc4.x = state.rc4.y = 0; |
392 | 4.88k | rc4InitKey(objKey, objKeyLength, state.rc4.state); |
393 | 4.88k | state.rc4.buf = EOF; |
394 | 4.88k | break; |
395 | 6.99k | case cryptAES: |
396 | 6.99k | aesKeyExpansion(&state.aes, objKey, objKeyLength, gTrue); |
397 | 6.99k | str->getBlock((char *)state.aes.cbc, 16); |
398 | 6.99k | state.aes.bufIdx = 16; |
399 | 6.99k | break; |
400 | 24.4k | case cryptAES256: |
401 | 24.4k | aes256KeyExpansion(&state.aes256, objKey, objKeyLength); |
402 | 24.4k | str->getBlock((char *)state.aes256.cbc, 16); |
403 | 24.4k | state.aes256.bufIdx = 16; |
404 | 24.4k | break; |
405 | 36.3k | } |
406 | 36.3k | } |
407 | | |
408 | 2.86M | int DecryptStream::getChar() { |
409 | 2.86M | Guchar in[16]; |
410 | 2.86M | int c; |
411 | | |
412 | 2.86M | c = EOF; // make gcc happy |
413 | 2.86M | switch (algo) { |
414 | 198k | case cryptRC4: |
415 | 198k | if (state.rc4.buf == EOF) { |
416 | 196k | c = str->getChar(); |
417 | 196k | if (c != EOF) { |
418 | 192k | state.rc4.buf = rc4DecryptByte(state.rc4.state, &state.rc4.x, |
419 | 192k | &state.rc4.y, (Guchar)c); |
420 | 192k | } |
421 | 196k | } |
422 | 198k | c = state.rc4.buf; |
423 | 198k | state.rc4.buf = EOF; |
424 | 198k | break; |
425 | 1.08M | case cryptAES: |
426 | 1.08M | if (state.aes.bufIdx == 16) { |
427 | 74.3k | if (str->getBlock((char *)in, 16) != 16) { |
428 | 4.54k | return EOF; |
429 | 4.54k | } |
430 | 69.8k | aesDecryptBlock(&state.aes, in, str->lookChar() == EOF); |
431 | 69.8k | } |
432 | 1.07M | if (state.aes.bufIdx == 16) { |
433 | 2.34k | c = EOF; |
434 | 1.07M | } else { |
435 | 1.07M | c = state.aes.buf[state.aes.bufIdx++]; |
436 | 1.07M | } |
437 | 1.07M | break; |
438 | 1.58M | case cryptAES256: |
439 | 1.58M | if (state.aes256.bufIdx == 16) { |
440 | 121k | if (str->getBlock((char *)in, 16) != 16) { |
441 | 21.3k | return EOF; |
442 | 21.3k | } |
443 | 100k | aes256DecryptBlock(&state.aes256, in, str->lookChar() == EOF); |
444 | 100k | } |
445 | 1.55M | if (state.aes256.bufIdx == 16) { |
446 | 2.96k | c = EOF; |
447 | 1.55M | } else { |
448 | 1.55M | c = state.aes256.buf[state.aes256.bufIdx++]; |
449 | 1.55M | } |
450 | 1.55M | break; |
451 | 2.86M | } |
452 | 2.83M | return c; |
453 | 2.86M | } |
454 | | |
455 | 1.52k | int DecryptStream::lookChar() { |
456 | 1.52k | Guchar in[16]; |
457 | 1.52k | int c; |
458 | | |
459 | 1.52k | c = EOF; // make gcc happy |
460 | 1.52k | switch (algo) { |
461 | 1.42k | case cryptRC4: |
462 | 1.42k | if (state.rc4.buf == EOF) { |
463 | 1.38k | c = str->getChar(); |
464 | 1.38k | if (c != EOF) { |
465 | 1.38k | state.rc4.buf = rc4DecryptByte(state.rc4.state, &state.rc4.x, |
466 | 1.38k | &state.rc4.y, (Guchar)c); |
467 | 1.38k | } |
468 | 1.38k | } |
469 | 1.42k | c = state.rc4.buf; |
470 | 1.42k | break; |
471 | 0 | case cryptAES: |
472 | 0 | if (state.aes.bufIdx == 16) { |
473 | 0 | if (str->getBlock((char *)in, 16) != 16) { |
474 | 0 | return EOF; |
475 | 0 | } |
476 | 0 | aesDecryptBlock(&state.aes, in, str->lookChar() == EOF); |
477 | 0 | } |
478 | 0 | if (state.aes.bufIdx == 16) { |
479 | 0 | c = EOF; |
480 | 0 | } else { |
481 | 0 | c = state.aes.buf[state.aes.bufIdx]; |
482 | 0 | } |
483 | 0 | break; |
484 | 103 | case cryptAES256: |
485 | 103 | if (state.aes256.bufIdx == 16) { |
486 | 6 | if (str->getBlock((char *)in, 16) != 16) { |
487 | 0 | return EOF; |
488 | 0 | } |
489 | 6 | aes256DecryptBlock(&state.aes256, in, str->lookChar() == EOF); |
490 | 6 | } |
491 | 103 | if (state.aes256.bufIdx == 16) { |
492 | 0 | c = EOF; |
493 | 103 | } else { |
494 | 103 | c = state.aes256.buf[state.aes256.bufIdx]; |
495 | 103 | } |
496 | 103 | break; |
497 | 1.52k | } |
498 | 1.52k | return c; |
499 | 1.52k | } |
500 | | |
501 | 0 | GBool DecryptStream::isBinary(GBool last) { |
502 | 0 | return str->isBinary(last); |
503 | 0 | } |
504 | | |
505 | | //------------------------------------------------------------------------ |
506 | | // RC4-compatible decryption |
507 | | //------------------------------------------------------------------------ |
508 | | |
509 | 5.64k | void rc4InitKey(Guchar *key, int keyLen, Guchar *state) { |
510 | 5.64k | Guchar index1, index2; |
511 | 5.64k | Guchar t; |
512 | 5.64k | int i; |
513 | | |
514 | 1.45M | for (i = 0; i < 256; ++i) |
515 | 1.44M | state[i] = (Guchar)i; |
516 | 5.64k | index1 = index2 = 0; |
517 | 1.45M | for (i = 0; i < 256; ++i) { |
518 | 1.44M | index2 = (Guchar)(key[index1] + state[i] + index2); |
519 | 1.44M | t = state[i]; |
520 | 1.44M | state[i] = state[index2]; |
521 | 1.44M | state[index2] = t; |
522 | 1.44M | index1 = (Guchar)((index1 + 1) % keyLen); |
523 | 1.44M | } |
524 | 5.64k | } |
525 | | |
526 | 217k | Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) { |
527 | 217k | Guchar x1, y1, tx, ty; |
528 | | |
529 | 217k | x1 = *x = (Guchar)(*x + 1); |
530 | 217k | y1 = *y = (Guchar)(state[*x] + *y); |
531 | 217k | tx = state[x1]; |
532 | 217k | ty = state[y1]; |
533 | 217k | state[x1] = ty; |
534 | 217k | state[y1] = tx; |
535 | 217k | return c ^ state[(tx + ty) % 256]; |
536 | 217k | } |
537 | | |
538 | | //------------------------------------------------------------------------ |
539 | | // AES decryption |
540 | | //------------------------------------------------------------------------ |
541 | | |
542 | | static Guchar sbox[256] = { |
543 | | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, |
544 | | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, |
545 | | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, |
546 | | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, |
547 | | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, |
548 | | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, |
549 | | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, |
550 | | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, |
551 | | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, |
552 | | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, |
553 | | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, |
554 | | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, |
555 | | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, |
556 | | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, |
557 | | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, |
558 | | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 |
559 | | }; |
560 | | |
561 | | static Guchar invSbox[256] = { |
562 | | 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, |
563 | | 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, |
564 | | 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, |
565 | | 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, |
566 | | 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, |
567 | | 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, |
568 | | 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, |
569 | | 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, |
570 | | 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, |
571 | | 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, |
572 | | 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, |
573 | | 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, |
574 | | 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, |
575 | | 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, |
576 | | 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, |
577 | | 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d |
578 | | }; |
579 | | |
580 | | static Guint rcon[11] = { |
581 | | 0x00000000, // unused |
582 | | 0x01000000, |
583 | | 0x02000000, |
584 | | 0x04000000, |
585 | | 0x08000000, |
586 | | 0x10000000, |
587 | | 0x20000000, |
588 | | 0x40000000, |
589 | | 0x80000000, |
590 | | 0x1b000000, |
591 | | 0x36000000 |
592 | | }; |
593 | | |
594 | 497k | static inline Guint subWord(Guint x) { |
595 | 497k | return (sbox[x >> 24] << 24) |
596 | 497k | | (sbox[(x >> 16) & 0xff] << 16) |
597 | 497k | | (sbox[(x >> 8) & 0xff] << 8) |
598 | 497k | | sbox[x & 0xff]; |
599 | 497k | } |
600 | | |
601 | 349k | static inline Guint rotWord(Guint x) { |
602 | 349k | return ((x << 8) & 0xffffffff) | (x >> 24); |
603 | 349k | } |
604 | | |
605 | 20.5M | static inline void subBytes(Guchar *state) { |
606 | 20.5M | int i; |
607 | | |
608 | 349M | for (i = 0; i < 16; ++i) { |
609 | 329M | state[i] = sbox[state[i]]; |
610 | 329M | } |
611 | 20.5M | } |
612 | | |
613 | 2.10M | static inline void invSubBytes(Guchar *state) { |
614 | 2.10M | int i; |
615 | | |
616 | 35.8M | for (i = 0; i < 16; ++i) { |
617 | 33.7M | state[i] = invSbox[state[i]]; |
618 | 33.7M | } |
619 | 2.10M | } |
620 | | |
621 | 20.5M | static inline void shiftRows(Guchar *state) { |
622 | 20.5M | Guchar t; |
623 | | |
624 | 20.5M | t = state[4]; |
625 | 20.5M | state[4] = state[5]; |
626 | 20.5M | state[5] = state[6]; |
627 | 20.5M | state[6] = state[7]; |
628 | 20.5M | state[7] = t; |
629 | | |
630 | 20.5M | t = state[8]; |
631 | 20.5M | state[8] = state[10]; |
632 | 20.5M | state[10] = t; |
633 | 20.5M | t = state[9]; |
634 | 20.5M | state[9] = state[11]; |
635 | 20.5M | state[11] = t; |
636 | | |
637 | 20.5M | t = state[15]; |
638 | 20.5M | state[15] = state[14]; |
639 | 20.5M | state[14] = state[13]; |
640 | 20.5M | state[13] = state[12]; |
641 | 20.5M | state[12] = t; |
642 | 20.5M | } |
643 | | |
644 | 2.10M | static inline void invShiftRows(Guchar *state) { |
645 | 2.10M | Guchar t; |
646 | | |
647 | 2.10M | t = state[7]; |
648 | 2.10M | state[7] = state[6]; |
649 | 2.10M | state[6] = state[5]; |
650 | 2.10M | state[5] = state[4]; |
651 | 2.10M | state[4] = t; |
652 | | |
653 | 2.10M | t = state[8]; |
654 | 2.10M | state[8] = state[10]; |
655 | 2.10M | state[10] = t; |
656 | 2.10M | t = state[9]; |
657 | 2.10M | state[9] = state[11]; |
658 | 2.10M | state[11] = t; |
659 | | |
660 | 2.10M | t = state[12]; |
661 | 2.10M | state[12] = state[13]; |
662 | 2.10M | state[13] = state[14]; |
663 | 2.10M | state[14] = state[15]; |
664 | 2.10M | state[15] = t; |
665 | 2.10M | } |
666 | | |
667 | | // {02} \cdot s |
668 | 296M | static inline Guchar mul02(Guchar s) { |
669 | 296M | Guchar s2; |
670 | | |
671 | 296M | s2 = (Guchar)((s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1)); |
672 | 296M | return s2; |
673 | 296M | } |
674 | | |
675 | | // {03} \cdot s |
676 | 296M | static inline Guchar mul03(Guchar s) { |
677 | 296M | Guchar s2; |
678 | | |
679 | 296M | s2 = (Guchar)((s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1)); |
680 | 296M | return s ^ s2; |
681 | 296M | } |
682 | | |
683 | | // {09} \cdot s |
684 | 37.1M | static inline Guchar mul09(Guchar s) { |
685 | 37.1M | Guchar s2, s4, s8; |
686 | | |
687 | 37.1M | s2 = (Guchar)((s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1)); |
688 | 37.1M | s4 = (Guchar)((s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1)); |
689 | 37.1M | s8 = (Guchar)((s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1)); |
690 | 37.1M | return s ^ s8; |
691 | 37.1M | } |
692 | | |
693 | | // {0b} \cdot s |
694 | 37.1M | static inline Guchar mul0b(Guchar s) { |
695 | 37.1M | Guchar s2, s4, s8; |
696 | | |
697 | 37.1M | s2 = (Guchar)((s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1)); |
698 | 37.1M | s4 = (Guchar)((s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1)); |
699 | 37.1M | s8 = (Guchar)((s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1)); |
700 | 37.1M | return s ^ s2 ^ s8; |
701 | 37.1M | } |
702 | | |
703 | | // {0d} \cdot s |
704 | 37.1M | static inline Guchar mul0d(Guchar s) { |
705 | 37.1M | Guchar s2, s4, s8; |
706 | | |
707 | 37.1M | s2 = (Guchar)((s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1)); |
708 | 37.1M | s4 = (Guchar)((s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1)); |
709 | 37.1M | s8 = (Guchar)((s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1)); |
710 | 37.1M | return s ^ s4 ^ s8; |
711 | 37.1M | } |
712 | | |
713 | | // {0e} \cdot s |
714 | 37.1M | static inline Guchar mul0e(Guchar s) { |
715 | 37.1M | Guchar s2, s4, s8; |
716 | | |
717 | 37.1M | s2 = (Guchar)((s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1)); |
718 | 37.1M | s4 = (Guchar)((s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1)); |
719 | 37.1M | s8 = (Guchar)((s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1)); |
720 | 37.1M | return s2 ^ s4 ^ s8; |
721 | 37.1M | } |
722 | | |
723 | 18.5M | static inline void mixColumns(Guchar *state) { |
724 | 18.5M | int c; |
725 | 18.5M | Guchar s0, s1, s2, s3; |
726 | | |
727 | 92.5M | for (c = 0; c < 4; ++c) { |
728 | 74.0M | s0 = state[c]; |
729 | 74.0M | s1 = state[4+c]; |
730 | 74.0M | s2 = state[8+c]; |
731 | 74.0M | s3 = state[12+c]; |
732 | 74.0M | state[c] = mul02(s0) ^ mul03(s1) ^ s2 ^ s3; |
733 | 74.0M | state[4+c] = s0 ^ mul02(s1) ^ mul03(s2) ^ s3; |
734 | 74.0M | state[8+c] = s0 ^ s1 ^ mul02(s2) ^ mul03(s3); |
735 | 74.0M | state[12+c] = mul03(s0) ^ s1 ^ s2 ^ mul02(s3); |
736 | 74.0M | } |
737 | 18.5M | } |
738 | | |
739 | 1.93M | static inline void invMixColumns(Guchar *state) { |
740 | 1.93M | int c; |
741 | 1.93M | Guchar s0, s1, s2, s3; |
742 | | |
743 | 9.69M | for (c = 0; c < 4; ++c) { |
744 | 7.75M | s0 = state[c]; |
745 | 7.75M | s1 = state[4+c]; |
746 | 7.75M | s2 = state[8+c]; |
747 | 7.75M | s3 = state[12+c]; |
748 | 7.75M | state[c] = mul0e(s0) ^ mul0b(s1) ^ mul0d(s2) ^ mul09(s3); |
749 | 7.75M | state[4+c] = mul09(s0) ^ mul0e(s1) ^ mul0b(s2) ^ mul0d(s3); |
750 | 7.75M | state[8+c] = mul0d(s0) ^ mul09(s1) ^ mul0e(s2) ^ mul0b(s3); |
751 | 7.75M | state[12+c] = mul0b(s0) ^ mul0d(s1) ^ mul09(s2) ^ mul0e(s3); |
752 | 7.75M | } |
753 | 1.93M | } |
754 | | |
755 | 382k | static inline void invMixColumnsW(Guint *w) { |
756 | 382k | int c; |
757 | 382k | Guchar s0, s1, s2, s3; |
758 | | |
759 | 1.91M | for (c = 0; c < 4; ++c) { |
760 | 1.52M | s0 = (Guchar)(w[c] >> 24); |
761 | 1.52M | s1 = (Guchar)(w[c] >> 16); |
762 | 1.52M | s2 = (Guchar)(w[c] >> 8); |
763 | 1.52M | s3 = (Guchar)w[c]; |
764 | 1.52M | w[c] = ((mul0e(s0) ^ mul0b(s1) ^ mul0d(s2) ^ mul09(s3)) << 24) |
765 | 1.52M | | ((mul09(s0) ^ mul0e(s1) ^ mul0b(s2) ^ mul0d(s3)) << 16) |
766 | 1.52M | | ((mul0d(s0) ^ mul09(s1) ^ mul0e(s2) ^ mul0b(s3)) << 8) |
767 | 1.52M | | (mul0b(s0) ^ mul0d(s1) ^ mul09(s2) ^ mul0e(s3)); |
768 | 1.52M | } |
769 | 382k | } |
770 | | |
771 | 24.9M | static inline void addRoundKey(Guchar *state, Guint *w) { |
772 | 24.9M | int c; |
773 | | |
774 | 124M | for (c = 0; c < 4; ++c) { |
775 | 99.6M | state[c] ^= (Guchar)(w[c] >> 24); |
776 | 99.6M | state[4+c] ^= (Guchar)(w[c] >> 16); |
777 | 99.6M | state[8+c] ^= (Guchar)(w[c] >> 8); |
778 | 99.6M | state[12+c] ^= (Guchar)w[c]; |
779 | 99.6M | } |
780 | 24.9M | } |
781 | | |
782 | | void aesKeyExpansion(DecryptAESState *s, |
783 | | Guchar *objKey, int objKeyLen, |
784 | 17.8k | GBool decrypt) { |
785 | 17.8k | Guint temp; |
786 | 17.8k | int i, round; |
787 | | |
788 | | //~ this assumes objKeyLen == 16 |
789 | | |
790 | 89.0k | for (i = 0; i < 4; ++i) { |
791 | 71.2k | s->w[i] = (objKey[4*i] << 24) + (objKey[4*i+1] << 16) + |
792 | 71.2k | (objKey[4*i+2] << 8) + objKey[4*i+3]; |
793 | 71.2k | } |
794 | 730k | for (i = 4; i < 44; ++i) { |
795 | 712k | temp = s->w[i-1]; |
796 | 712k | if (!(i & 3)) { |
797 | 178k | temp = subWord(rotWord(temp)) ^ rcon[i/4]; |
798 | 178k | } |
799 | 712k | s->w[i] = s->w[i-4] ^ temp; |
800 | 712k | } |
801 | 17.8k | if (decrypt) { |
802 | 69.9k | for (round = 1; round <= 9; ++round) { |
803 | 62.9k | invMixColumnsW(&s->w[round * 4]); |
804 | 62.9k | } |
805 | 6.99k | } |
806 | 17.8k | } |
807 | | |
808 | 2.05M | void aesEncryptBlock(DecryptAESState *s, Guchar *in) { |
809 | 2.05M | int c, round; |
810 | | |
811 | | // initial state + CBC |
812 | 10.2M | for (c = 0; c < 4; ++c) { |
813 | 8.22M | s->state[c] = in[4*c] ^ s->cbc[4*c]; |
814 | 8.22M | s->state[4+c] = in[4*c+1] ^ s->cbc[4*c+1]; |
815 | 8.22M | s->state[8+c] = in[4*c+2] ^ s->cbc[4*c+2]; |
816 | 8.22M | s->state[12+c] = in[4*c+3] ^ s->cbc[4*c+3]; |
817 | 8.22M | } |
818 | | |
819 | | // round 0 |
820 | 2.05M | addRoundKey(s->state, &s->w[0]); |
821 | | |
822 | | // rounds 1 .. 9 |
823 | 20.5M | for (round = 1; round <= 9; ++round) { |
824 | 18.5M | subBytes(s->state); |
825 | 18.5M | shiftRows(s->state); |
826 | 18.5M | mixColumns(s->state); |
827 | 18.5M | addRoundKey(s->state, &s->w[round * 4]); |
828 | 18.5M | } |
829 | | |
830 | | // round 10 |
831 | 2.05M | subBytes(s->state); |
832 | 2.05M | shiftRows(s->state); |
833 | 2.05M | addRoundKey(s->state, &s->w[10 * 4]); |
834 | | |
835 | | // output + save for next CBC |
836 | 10.2M | for (c = 0; c < 4; ++c) { |
837 | 8.22M | s->buf[4*c] = s->cbc[4*c] = s->state[c]; |
838 | 8.22M | s->buf[4*c+1] = s->cbc[4*c+1] = s->state[4+c]; |
839 | 8.22M | s->buf[4*c+2] = s->cbc[4*c+2] = s->state[8+c]; |
840 | 8.22M | s->buf[4*c+3] = s->cbc[4*c+3] = s->state[12+c]; |
841 | 8.22M | } |
842 | 2.05M | } |
843 | | |
844 | 69.8k | void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last) { |
845 | 69.8k | int c, round, n, i; |
846 | | |
847 | | // initial state |
848 | 349k | for (c = 0; c < 4; ++c) { |
849 | 279k | s->state[c] = in[4*c]; |
850 | 279k | s->state[4+c] = in[4*c+1]; |
851 | 279k | s->state[8+c] = in[4*c+2]; |
852 | 279k | s->state[12+c] = in[4*c+3]; |
853 | 279k | } |
854 | | |
855 | | // round 0 |
856 | 69.8k | addRoundKey(s->state, &s->w[10 * 4]); |
857 | | |
858 | | // rounds 1-9 |
859 | 698k | for (round = 9; round >= 1; --round) { |
860 | 628k | invSubBytes(s->state); |
861 | 628k | invShiftRows(s->state); |
862 | 628k | invMixColumns(s->state); |
863 | 628k | addRoundKey(s->state, &s->w[round * 4]); |
864 | 628k | } |
865 | | |
866 | | // round 10 |
867 | 69.8k | invSubBytes(s->state); |
868 | 69.8k | invShiftRows(s->state); |
869 | 69.8k | addRoundKey(s->state, &s->w[0]); |
870 | | |
871 | | // CBC |
872 | 349k | for (c = 0; c < 4; ++c) { |
873 | 279k | s->buf[4*c] = s->state[c] ^ s->cbc[4*c]; |
874 | 279k | s->buf[4*c+1] = s->state[4+c] ^ s->cbc[4*c+1]; |
875 | 279k | s->buf[4*c+2] = s->state[8+c] ^ s->cbc[4*c+2]; |
876 | 279k | s->buf[4*c+3] = s->state[12+c] ^ s->cbc[4*c+3]; |
877 | 279k | } |
878 | | |
879 | | // save the input block for the next CBC |
880 | 1.18M | for (i = 0; i < 16; ++i) { |
881 | 1.11M | s->cbc[i] = in[i]; |
882 | 1.11M | } |
883 | | |
884 | | // remove padding |
885 | 69.8k | s->bufIdx = 0; |
886 | 69.8k | if (last) { |
887 | 2.69k | n = s->buf[15]; |
888 | 2.69k | if (n < 1 || n > 16) { // this should never happen |
889 | 2.34k | n = 16; |
890 | 2.34k | } |
891 | 6.06k | for (i = 15; i >= n; --i) { |
892 | 3.37k | s->buf[i] = s->buf[i-n]; |
893 | 3.37k | } |
894 | 2.69k | s->bufIdx = n; |
895 | 2.69k | } |
896 | 69.8k | } |
897 | | |
898 | | //------------------------------------------------------------------------ |
899 | | // AES-256 decryption |
900 | | //------------------------------------------------------------------------ |
901 | | |
902 | | static void aes256KeyExpansion(DecryptAES256State *s, |
903 | 24.5k | Guchar *objKey, int objKeyLen) { |
904 | 24.5k | Guint temp; |
905 | 24.5k | int i, round; |
906 | | |
907 | | //~ this assumes objKeyLen == 32 |
908 | | |
909 | 220k | for (i = 0; i < 8; ++i) { |
910 | 196k | s->w[i] = (objKey[4*i] << 24) + (objKey[4*i+1] << 16) + |
911 | 196k | (objKey[4*i+2] << 8) + objKey[4*i+3]; |
912 | 196k | } |
913 | 1.30M | for (i = 8; i < 60; ++i) { |
914 | 1.27M | temp = s->w[i-1]; |
915 | 1.27M | if ((i & 7) == 0) { |
916 | 171k | temp = subWord(rotWord(temp)) ^ rcon[i/8]; |
917 | 1.10M | } else if ((i & 7) == 4) { |
918 | 147k | temp = subWord(temp); |
919 | 147k | } |
920 | 1.27M | s->w[i] = s->w[i-8] ^ temp; |
921 | 1.27M | } |
922 | 343k | for (round = 1; round <= 13; ++round) { |
923 | 319k | invMixColumnsW(&s->w[round * 4]); |
924 | 319k | } |
925 | 24.5k | } |
926 | | |
927 | 100k | static void aes256DecryptBlock(DecryptAES256State *s, Guchar *in, GBool last) { |
928 | 100k | int c, round, n, i; |
929 | | |
930 | | // initial state |
931 | 503k | for (c = 0; c < 4; ++c) { |
932 | 403k | s->state[c] = in[4*c]; |
933 | 403k | s->state[4+c] = in[4*c+1]; |
934 | 403k | s->state[8+c] = in[4*c+2]; |
935 | 403k | s->state[12+c] = in[4*c+3]; |
936 | 403k | } |
937 | | |
938 | | // round 0 |
939 | 100k | addRoundKey(s->state, &s->w[14 * 4]); |
940 | | |
941 | | // rounds 13-1 |
942 | 1.41M | for (round = 13; round >= 1; --round) { |
943 | 1.31M | invSubBytes(s->state); |
944 | 1.31M | invShiftRows(s->state); |
945 | 1.31M | invMixColumns(s->state); |
946 | 1.31M | addRoundKey(s->state, &s->w[round * 4]); |
947 | 1.31M | } |
948 | | |
949 | | // round 14 |
950 | 100k | invSubBytes(s->state); |
951 | 100k | invShiftRows(s->state); |
952 | 100k | addRoundKey(s->state, &s->w[0]); |
953 | | |
954 | | // CBC |
955 | 503k | for (c = 0; c < 4; ++c) { |
956 | 403k | s->buf[4*c] = s->state[c] ^ s->cbc[4*c]; |
957 | 403k | s->buf[4*c+1] = s->state[4+c] ^ s->cbc[4*c+1]; |
958 | 403k | s->buf[4*c+2] = s->state[8+c] ^ s->cbc[4*c+2]; |
959 | 403k | s->buf[4*c+3] = s->state[12+c] ^ s->cbc[4*c+3]; |
960 | 403k | } |
961 | | |
962 | | // save the input block for the next CBC |
963 | 1.71M | for (i = 0; i < 16; ++i) { |
964 | 1.61M | s->cbc[i] = in[i]; |
965 | 1.61M | } |
966 | | |
967 | | // remove padding |
968 | 100k | s->bufIdx = 0; |
969 | 100k | if (last) { |
970 | 3.75k | n = s->buf[15]; |
971 | 3.75k | if (n < 1 || n > 16) { // this should never happen |
972 | 2.79k | n = 16; |
973 | 2.79k | } |
974 | 11.8k | for (i = 15; i >= n; --i) { |
975 | 8.13k | s->buf[i] = s->buf[i-n]; |
976 | 8.13k | } |
977 | 3.75k | s->bufIdx = n; |
978 | 3.75k | } |
979 | 100k | } |
980 | | |
981 | | //------------------------------------------------------------------------ |
982 | | // MD5 message digest |
983 | | //------------------------------------------------------------------------ |
984 | | |
985 | | // this works around a bug in older Sun compilers |
986 | 1.07M | static inline Gulong rotateLeft(Gulong x, int r) { |
987 | 1.07M | x &= 0xffffffff; |
988 | 1.07M | return ((x << r) | (x >> (32 - r))) & 0xffffffff; |
989 | 1.07M | } |
990 | | |
991 | | static inline Gulong md5Round1(Gulong a, Gulong b, Gulong c, Gulong d, |
992 | 269k | Gulong Xk, int s, Gulong Ti) { |
993 | 269k | return b + rotateLeft((a + ((b & c) | (~b & d)) + Xk + Ti), s); |
994 | 269k | } |
995 | | |
996 | | static inline Gulong md5Round2(Gulong a, Gulong b, Gulong c, Gulong d, |
997 | 269k | Gulong Xk, int s, Gulong Ti) { |
998 | 269k | return b + rotateLeft((a + ((b & d) | (c & ~d)) + Xk + Ti), s); |
999 | 269k | } |
1000 | | |
1001 | | static inline Gulong md5Round3(Gulong a, Gulong b, Gulong c, Gulong d, |
1002 | 269k | Gulong Xk, int s, Gulong Ti) { |
1003 | 269k | return b + rotateLeft((a + (b ^ c ^ d) + Xk + Ti), s); |
1004 | 269k | } |
1005 | | |
1006 | | static inline Gulong md5Round4(Gulong a, Gulong b, Gulong c, Gulong d, |
1007 | 269k | Gulong Xk, int s, Gulong Ti) { |
1008 | 269k | return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s); |
1009 | 269k | } |
1010 | | |
1011 | 15.9k | void md5Start(MD5State *state) { |
1012 | 15.9k | state->a = 0x67452301; |
1013 | 15.9k | state->b = 0xefcdab89; |
1014 | 15.9k | state->c = 0x98badcfe; |
1015 | 15.9k | state->d = 0x10325476; |
1016 | 15.9k | state->bufLen = 0; |
1017 | 15.9k | state->msgLen = 0; |
1018 | 15.9k | } |
1019 | | |
1020 | 16.8k | static void md5ProcessBlock(MD5State *state) { |
1021 | 16.8k | Gulong x[16]; |
1022 | 16.8k | Gulong a, b, c, d; |
1023 | 16.8k | int i; |
1024 | | |
1025 | 286k | for (i = 0; i < 16; ++i) { |
1026 | 269k | x[i] = state->buf[4*i] | (state->buf[4*i+1] << 8) | |
1027 | 269k | (state->buf[4*i+2] << 16) | (state->buf[4*i+3] << 24); |
1028 | 269k | } |
1029 | | |
1030 | 16.8k | a = state->a; |
1031 | 16.8k | b = state->b; |
1032 | 16.8k | c = state->c; |
1033 | 16.8k | d = state->d; |
1034 | | |
1035 | | // round 1 |
1036 | 16.8k | a = md5Round1(a, b, c, d, x[0], 7, 0xd76aa478); |
1037 | 16.8k | d = md5Round1(d, a, b, c, x[1], 12, 0xe8c7b756); |
1038 | 16.8k | c = md5Round1(c, d, a, b, x[2], 17, 0x242070db); |
1039 | 16.8k | b = md5Round1(b, c, d, a, x[3], 22, 0xc1bdceee); |
1040 | 16.8k | a = md5Round1(a, b, c, d, x[4], 7, 0xf57c0faf); |
1041 | 16.8k | d = md5Round1(d, a, b, c, x[5], 12, 0x4787c62a); |
1042 | 16.8k | c = md5Round1(c, d, a, b, x[6], 17, 0xa8304613); |
1043 | 16.8k | b = md5Round1(b, c, d, a, x[7], 22, 0xfd469501); |
1044 | 16.8k | a = md5Round1(a, b, c, d, x[8], 7, 0x698098d8); |
1045 | 16.8k | d = md5Round1(d, a, b, c, x[9], 12, 0x8b44f7af); |
1046 | 16.8k | c = md5Round1(c, d, a, b, x[10], 17, 0xffff5bb1); |
1047 | 16.8k | b = md5Round1(b, c, d, a, x[11], 22, 0x895cd7be); |
1048 | 16.8k | a = md5Round1(a, b, c, d, x[12], 7, 0x6b901122); |
1049 | 16.8k | d = md5Round1(d, a, b, c, x[13], 12, 0xfd987193); |
1050 | 16.8k | c = md5Round1(c, d, a, b, x[14], 17, 0xa679438e); |
1051 | 16.8k | b = md5Round1(b, c, d, a, x[15], 22, 0x49b40821); |
1052 | | |
1053 | | // round 2 |
1054 | 16.8k | a = md5Round2(a, b, c, d, x[1], 5, 0xf61e2562); |
1055 | 16.8k | d = md5Round2(d, a, b, c, x[6], 9, 0xc040b340); |
1056 | 16.8k | c = md5Round2(c, d, a, b, x[11], 14, 0x265e5a51); |
1057 | 16.8k | b = md5Round2(b, c, d, a, x[0], 20, 0xe9b6c7aa); |
1058 | 16.8k | a = md5Round2(a, b, c, d, x[5], 5, 0xd62f105d); |
1059 | 16.8k | d = md5Round2(d, a, b, c, x[10], 9, 0x02441453); |
1060 | 16.8k | c = md5Round2(c, d, a, b, x[15], 14, 0xd8a1e681); |
1061 | 16.8k | b = md5Round2(b, c, d, a, x[4], 20, 0xe7d3fbc8); |
1062 | 16.8k | a = md5Round2(a, b, c, d, x[9], 5, 0x21e1cde6); |
1063 | 16.8k | d = md5Round2(d, a, b, c, x[14], 9, 0xc33707d6); |
1064 | 16.8k | c = md5Round2(c, d, a, b, x[3], 14, 0xf4d50d87); |
1065 | 16.8k | b = md5Round2(b, c, d, a, x[8], 20, 0x455a14ed); |
1066 | 16.8k | a = md5Round2(a, b, c, d, x[13], 5, 0xa9e3e905); |
1067 | 16.8k | d = md5Round2(d, a, b, c, x[2], 9, 0xfcefa3f8); |
1068 | 16.8k | c = md5Round2(c, d, a, b, x[7], 14, 0x676f02d9); |
1069 | 16.8k | b = md5Round2(b, c, d, a, x[12], 20, 0x8d2a4c8a); |
1070 | | |
1071 | | // round 3 |
1072 | 16.8k | a = md5Round3(a, b, c, d, x[5], 4, 0xfffa3942); |
1073 | 16.8k | d = md5Round3(d, a, b, c, x[8], 11, 0x8771f681); |
1074 | 16.8k | c = md5Round3(c, d, a, b, x[11], 16, 0x6d9d6122); |
1075 | 16.8k | b = md5Round3(b, c, d, a, x[14], 23, 0xfde5380c); |
1076 | 16.8k | a = md5Round3(a, b, c, d, x[1], 4, 0xa4beea44); |
1077 | 16.8k | d = md5Round3(d, a, b, c, x[4], 11, 0x4bdecfa9); |
1078 | 16.8k | c = md5Round3(c, d, a, b, x[7], 16, 0xf6bb4b60); |
1079 | 16.8k | b = md5Round3(b, c, d, a, x[10], 23, 0xbebfbc70); |
1080 | 16.8k | a = md5Round3(a, b, c, d, x[13], 4, 0x289b7ec6); |
1081 | 16.8k | d = md5Round3(d, a, b, c, x[0], 11, 0xeaa127fa); |
1082 | 16.8k | c = md5Round3(c, d, a, b, x[3], 16, 0xd4ef3085); |
1083 | 16.8k | b = md5Round3(b, c, d, a, x[6], 23, 0x04881d05); |
1084 | 16.8k | a = md5Round3(a, b, c, d, x[9], 4, 0xd9d4d039); |
1085 | 16.8k | d = md5Round3(d, a, b, c, x[12], 11, 0xe6db99e5); |
1086 | 16.8k | c = md5Round3(c, d, a, b, x[15], 16, 0x1fa27cf8); |
1087 | 16.8k | b = md5Round3(b, c, d, a, x[2], 23, 0xc4ac5665); |
1088 | | |
1089 | | // round 4 |
1090 | 16.8k | a = md5Round4(a, b, c, d, x[0], 6, 0xf4292244); |
1091 | 16.8k | d = md5Round4(d, a, b, c, x[7], 10, 0x432aff97); |
1092 | 16.8k | c = md5Round4(c, d, a, b, x[14], 15, 0xab9423a7); |
1093 | 16.8k | b = md5Round4(b, c, d, a, x[5], 21, 0xfc93a039); |
1094 | 16.8k | a = md5Round4(a, b, c, d, x[12], 6, 0x655b59c3); |
1095 | 16.8k | d = md5Round4(d, a, b, c, x[3], 10, 0x8f0ccc92); |
1096 | 16.8k | c = md5Round4(c, d, a, b, x[10], 15, 0xffeff47d); |
1097 | 16.8k | b = md5Round4(b, c, d, a, x[1], 21, 0x85845dd1); |
1098 | 16.8k | a = md5Round4(a, b, c, d, x[8], 6, 0x6fa87e4f); |
1099 | 16.8k | d = md5Round4(d, a, b, c, x[15], 10, 0xfe2ce6e0); |
1100 | 16.8k | c = md5Round4(c, d, a, b, x[6], 15, 0xa3014314); |
1101 | 16.8k | b = md5Round4(b, c, d, a, x[13], 21, 0x4e0811a1); |
1102 | 16.8k | a = md5Round4(a, b, c, d, x[4], 6, 0xf7537e82); |
1103 | 16.8k | d = md5Round4(d, a, b, c, x[11], 10, 0xbd3af235); |
1104 | 16.8k | c = md5Round4(c, d, a, b, x[2], 15, 0x2ad7d2bb); |
1105 | 16.8k | b = md5Round4(b, c, d, a, x[9], 21, 0xeb86d391); |
1106 | | |
1107 | | // increment a, b, c, d |
1108 | 16.8k | state->a += a; |
1109 | 16.8k | state->b += b; |
1110 | 16.8k | state->c += c; |
1111 | 16.8k | state->d += d; |
1112 | | |
1113 | 16.8k | state->bufLen = 0; |
1114 | 16.8k | } |
1115 | | |
1116 | 15.9k | void md5Append(MD5State *state, Guchar *data, int dataLen) { |
1117 | 15.9k | Guchar *p; |
1118 | 15.9k | int remain, k; |
1119 | | |
1120 | 15.9k | p = data; |
1121 | 15.9k | remain = dataLen; |
1122 | 16.8k | while (state->bufLen + remain >= 64) { |
1123 | 903 | k = 64 - state->bufLen; |
1124 | 903 | memcpy(state->buf + state->bufLen, p, k); |
1125 | 903 | state->bufLen = 64; |
1126 | 903 | md5ProcessBlock(state); |
1127 | 903 | p += k; |
1128 | 903 | remain -= k; |
1129 | 903 | } |
1130 | 15.9k | if (remain > 0) { |
1131 | 15.9k | memcpy(state->buf + state->bufLen, p, remain); |
1132 | 15.9k | state->bufLen += remain; |
1133 | 15.9k | } |
1134 | 15.9k | state->msgLen += dataLen; |
1135 | 15.9k | } |
1136 | | |
1137 | 15.9k | void md5Finish(MD5State *state) { |
1138 | | // padding and length |
1139 | 15.9k | state->buf[state->bufLen++] = 0x80; |
1140 | 15.9k | if (state->bufLen > 56) { |
1141 | 3 | while (state->bufLen < 64) { |
1142 | 1 | state->buf[state->bufLen++] = 0x00; |
1143 | 1 | } |
1144 | 2 | md5ProcessBlock(state); |
1145 | 2 | } |
1146 | 493k | while (state->bufLen < 56) { |
1147 | 477k | state->buf[state->bufLen++] = 0x00; |
1148 | 477k | } |
1149 | 15.9k | state->buf[56] = (Guchar)(state->msgLen << 3); |
1150 | 15.9k | state->buf[57] = (Guchar)(state->msgLen >> 5); |
1151 | 15.9k | state->buf[58] = (Guchar)(state->msgLen >> 13); |
1152 | 15.9k | state->buf[59] = (Guchar)(state->msgLen >> 21); |
1153 | 15.9k | state->buf[60] = (Guchar)(state->msgLen >> 29); |
1154 | 15.9k | state->buf[61] = (Guchar)0; |
1155 | 15.9k | state->buf[62] = (Guchar)0; |
1156 | 15.9k | state->buf[63] = (Guchar)0; |
1157 | 15.9k | state->bufLen = 64; |
1158 | 15.9k | md5ProcessBlock(state); |
1159 | | |
1160 | | // break digest into bytes |
1161 | 15.9k | state->digest[0] = (Guchar)state->a; |
1162 | 15.9k | state->digest[1] = (Guchar)(state->a >> 8); |
1163 | 15.9k | state->digest[2] = (Guchar)(state->a >> 16); |
1164 | 15.9k | state->digest[3] = (Guchar)(state->a >> 24); |
1165 | 15.9k | state->digest[4] = (Guchar)state->b; |
1166 | 15.9k | state->digest[5] = (Guchar)(state->b >> 8); |
1167 | 15.9k | state->digest[6] = (Guchar)(state->b >> 16); |
1168 | 15.9k | state->digest[7] = (Guchar)(state->b >> 24); |
1169 | 15.9k | state->digest[8] = (Guchar)state->c; |
1170 | 15.9k | state->digest[9] = (Guchar)(state->c >> 8); |
1171 | 15.9k | state->digest[10] = (Guchar)(state->c >> 16); |
1172 | 15.9k | state->digest[11] = (Guchar)(state->c >> 24); |
1173 | 15.9k | state->digest[12] = (Guchar)state->d; |
1174 | 15.9k | state->digest[13] = (Guchar)(state->d >> 8); |
1175 | 15.9k | state->digest[14] = (Guchar)(state->d >> 16); |
1176 | 15.9k | state->digest[15] = (Guchar)(state->d >> 24); |
1177 | 15.9k | } |
1178 | | |
1179 | 15.9k | void md5(Guchar *msg, int msgLen, Guchar *digest) { |
1180 | 15.9k | MD5State state; |
1181 | 15.9k | int i; |
1182 | | |
1183 | 15.9k | if (msgLen < 0) { |
1184 | 0 | return; |
1185 | 0 | } |
1186 | 15.9k | md5Start(&state); |
1187 | 15.9k | md5Append(&state, msg, msgLen); |
1188 | 15.9k | md5Finish(&state); |
1189 | 270k | for (i = 0; i < 16; ++i) { |
1190 | 254k | digest[i] = state.digest[i]; |
1191 | 254k | } |
1192 | 15.9k | } |
1193 | | |
1194 | | //------------------------------------------------------------------------ |
1195 | | // SHA-256 hash |
1196 | | //------------------------------------------------------------------------ |
1197 | | |
1198 | | static Guint sha256K[64] = { |
1199 | | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, |
1200 | | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, |
1201 | | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, |
1202 | | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, |
1203 | | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, |
1204 | | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, |
1205 | | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, |
1206 | | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, |
1207 | | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, |
1208 | | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, |
1209 | | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, |
1210 | | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, |
1211 | | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, |
1212 | | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, |
1213 | | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, |
1214 | | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 |
1215 | | }; |
1216 | | |
1217 | 94.3M | static inline Guint rotr(Guint x, Guint n) { |
1218 | 94.3M | return (x >> n) | (x << (32 - n)); |
1219 | 94.3M | } |
1220 | | |
1221 | 10.4M | static inline Guint sha256Ch(Guint x, Guint y, Guint z) { |
1222 | 10.4M | return (x & y) ^ (~x & z); |
1223 | 10.4M | } |
1224 | | |
1225 | 10.4M | static inline Guint sha256Maj(Guint x, Guint y, Guint z) { |
1226 | 10.4M | return (x & y) ^ (x & z) ^ (y & z); |
1227 | 10.4M | } |
1228 | | |
1229 | 10.4M | static inline Guint sha256Sigma0(Guint x) { |
1230 | 10.4M | return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); |
1231 | 10.4M | } |
1232 | | |
1233 | 10.4M | static inline Guint sha256Sigma1(Guint x) { |
1234 | 10.4M | return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); |
1235 | 10.4M | } |
1236 | | |
1237 | 7.86M | static inline Guint sha256sigma0(Guint x) { |
1238 | 7.86M | return rotr(x, 7) ^ rotr(x, 18) ^ (x >> 3); |
1239 | 7.86M | } |
1240 | | |
1241 | 7.86M | static inline Guint sha256sigma1(Guint x) { |
1242 | 7.86M | return rotr(x, 17) ^ rotr(x, 19) ^ (x >> 10); |
1243 | 7.86M | } |
1244 | | |
1245 | 163k | static void sha256HashBlock(Guchar *blk, Guint *H) { |
1246 | 163k | Guint W[64]; |
1247 | 163k | Guint a, b, c, d, e, f, g, h; |
1248 | 163k | Guint T1, T2; |
1249 | 163k | Guint t; |
1250 | | |
1251 | | // 1. prepare the message schedule |
1252 | 2.78M | for (t = 0; t < 16; ++t) { |
1253 | 2.62M | W[t] = (blk[t*4] << 24) | |
1254 | 2.62M | (blk[t*4 + 1] << 16) | |
1255 | 2.62M | (blk[t*4 + 2] << 8) | |
1256 | 2.62M | blk[t*4 + 3]; |
1257 | 2.62M | } |
1258 | 8.02M | for (t = 16; t < 64; ++t) { |
1259 | 7.86M | W[t] = sha256sigma1(W[t-2]) + W[t-7] + sha256sigma0(W[t-15]) + W[t-16]; |
1260 | 7.86M | } |
1261 | | |
1262 | | // 2. initialize the eight working variables |
1263 | 163k | a = H[0]; |
1264 | 163k | b = H[1]; |
1265 | 163k | c = H[2]; |
1266 | 163k | d = H[3]; |
1267 | 163k | e = H[4]; |
1268 | 163k | f = H[5]; |
1269 | 163k | g = H[6]; |
1270 | 163k | h = H[7]; |
1271 | | |
1272 | | // 3. |
1273 | 10.6M | for (t = 0; t < 64; ++t) { |
1274 | 10.4M | T1 = h + sha256Sigma1(e) + sha256Ch(e,f,g) + sha256K[t] + W[t]; |
1275 | 10.4M | T2 = sha256Sigma0(a) + sha256Maj(a,b,c); |
1276 | 10.4M | h = g; |
1277 | 10.4M | g = f; |
1278 | 10.4M | f = e; |
1279 | 10.4M | e = d + T1; |
1280 | 10.4M | d = c; |
1281 | 10.4M | c = b; |
1282 | 10.4M | b = a; |
1283 | 10.4M | a = T1 + T2; |
1284 | 10.4M | } |
1285 | | |
1286 | | // 4. compute the intermediate hash value |
1287 | 163k | H[0] += a; |
1288 | 163k | H[1] += b; |
1289 | 163k | H[2] += c; |
1290 | 163k | H[3] += d; |
1291 | 163k | H[4] += e; |
1292 | 163k | H[5] += f; |
1293 | 163k | H[6] += g; |
1294 | 163k | H[7] += h; |
1295 | 163k | } |
1296 | | |
1297 | 3.62k | static void sha256(Guchar *msg, int msgLen, Guchar *hash) { |
1298 | 3.62k | Guchar blk[64]; |
1299 | 3.62k | Guint H[8]; |
1300 | 3.62k | int blkLen, i; |
1301 | | |
1302 | 3.62k | H[0] = 0x6a09e667; |
1303 | 3.62k | H[1] = 0xbb67ae85; |
1304 | 3.62k | H[2] = 0x3c6ef372; |
1305 | 3.62k | H[3] = 0xa54ff53a; |
1306 | 3.62k | H[4] = 0x510e527f; |
1307 | 3.62k | H[5] = 0x9b05688c; |
1308 | 3.62k | H[6] = 0x1f83d9ab; |
1309 | 3.62k | H[7] = 0x5be0cd19; |
1310 | | |
1311 | 3.62k | blkLen = 0; |
1312 | 163k | for (i = 0; i + 64 <= msgLen; i += 64) { |
1313 | 160k | sha256HashBlock(msg + i, H); |
1314 | 160k | } |
1315 | 3.62k | blkLen = msgLen - i; |
1316 | 3.62k | if (blkLen > 0) { |
1317 | 153 | memcpy(blk, msg + i, blkLen); |
1318 | 153 | } |
1319 | | |
1320 | | // pad the message |
1321 | 3.62k | blk[blkLen++] = 0x80; |
1322 | 3.62k | if (blkLen > 56) { |
1323 | 0 | while (blkLen < 64) { |
1324 | 0 | blk[blkLen++] = 0; |
1325 | 0 | } |
1326 | 0 | sha256HashBlock(blk, H); |
1327 | 0 | blkLen = 0; |
1328 | 0 | } |
1329 | 201k | while (blkLen < 56) { |
1330 | 197k | blk[blkLen++] = 0; |
1331 | 197k | } |
1332 | 3.62k | blk[56] = 0; |
1333 | 3.62k | blk[57] = 0; |
1334 | 3.62k | blk[58] = 0; |
1335 | 3.62k | blk[59] = 0; |
1336 | 3.62k | blk[60] = (Guchar)(msgLen >> 21); |
1337 | 3.62k | blk[61] = (Guchar)(msgLen >> 13); |
1338 | 3.62k | blk[62] = (Guchar)(msgLen >> 5); |
1339 | 3.62k | blk[63] = (Guchar)(msgLen << 3); |
1340 | 3.62k | sha256HashBlock(blk, H); |
1341 | | |
1342 | | // copy the output into the buffer (convert words to bytes) |
1343 | 32.5k | for (i = 0; i < 8; ++i) { |
1344 | 28.9k | hash[i*4] = (Guchar)(H[i] >> 24); |
1345 | 28.9k | hash[i*4 + 1] = (Guchar)(H[i] >> 16); |
1346 | 28.9k | hash[i*4 + 2] = (Guchar)(H[i] >> 8); |
1347 | 28.9k | hash[i*4 + 3] = (Guchar)H[i]; |
1348 | 28.9k | } |
1349 | 3.62k | } |
1350 | | |
1351 | | //------------------------------------------------------------------------ |
1352 | | // SHA-384 and SHA-512 hashes |
1353 | | //------------------------------------------------------------------------ |
1354 | | |
1355 | | typedef unsigned long long SHA512Uint64; |
1356 | | |
1357 | | static SHA512Uint64 sha512K[80] = { |
1358 | | 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, |
1359 | | 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, |
1360 | | 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, |
1361 | | 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, |
1362 | | 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, |
1363 | | 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, |
1364 | | 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, |
1365 | | 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, |
1366 | | 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, |
1367 | | 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, |
1368 | | 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, |
1369 | | 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, |
1370 | | 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, |
1371 | | 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, |
1372 | | 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, |
1373 | | 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, |
1374 | | 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, |
1375 | | 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, |
1376 | | 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, |
1377 | | 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, |
1378 | | 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, |
1379 | | 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, |
1380 | | 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, |
1381 | | 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, |
1382 | | 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, |
1383 | | 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, |
1384 | | 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, |
1385 | | 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, |
1386 | | 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, |
1387 | | 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, |
1388 | | 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, |
1389 | | 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, |
1390 | | 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, |
1391 | | 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, |
1392 | | 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, |
1393 | | 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, |
1394 | | 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, |
1395 | | 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, |
1396 | | 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, |
1397 | | 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL |
1398 | | }; |
1399 | | |
1400 | 135M | static inline SHA512Uint64 rotr64(SHA512Uint64 x, Guint n) { |
1401 | 135M | return (x >> n) | (x << (64 - n)); |
1402 | 135M | } |
1403 | | |
1404 | | static inline SHA512Uint64 sha512Ch(SHA512Uint64 x, SHA512Uint64 y, |
1405 | 14.7M | SHA512Uint64 z) { |
1406 | 14.7M | return (x & y) ^ (~x & z); |
1407 | 14.7M | } |
1408 | | |
1409 | | static inline SHA512Uint64 sha512Maj(SHA512Uint64 x, SHA512Uint64 y, |
1410 | 14.7M | SHA512Uint64 z) { |
1411 | 14.7M | return (x & y) ^ (x & z) ^ (y & z); |
1412 | 14.7M | } |
1413 | | |
1414 | 14.7M | static inline SHA512Uint64 sha512Sigma0(SHA512Uint64 x) { |
1415 | 14.7M | return rotr64(x, 28) ^ rotr64(x, 34) ^ rotr64(x, 39); |
1416 | 14.7M | } |
1417 | | |
1418 | 14.7M | static inline SHA512Uint64 sha512Sigma1(SHA512Uint64 x) { |
1419 | 14.7M | return rotr64(x, 14) ^ rotr64(x, 18) ^ rotr64(x, 41); |
1420 | 14.7M | } |
1421 | | |
1422 | 11.7M | static inline SHA512Uint64 sha512sigma0(SHA512Uint64 x) { |
1423 | 11.7M | return rotr64(x, 1) ^ rotr64(x, 8) ^ (x >> 7); |
1424 | 11.7M | } |
1425 | | |
1426 | 11.7M | static inline SHA512Uint64 sha512sigma1(SHA512Uint64 x) { |
1427 | 11.7M | return rotr64(x, 19) ^ rotr64(x, 61) ^ (x >> 6); |
1428 | 11.7M | } |
1429 | | |
1430 | 184k | static void sha512HashBlock(Guchar *blk, SHA512Uint64 *H) { |
1431 | 184k | SHA512Uint64 W[80]; |
1432 | 184k | SHA512Uint64 a, b, c, d, e, f, g, h; |
1433 | 184k | SHA512Uint64 T1, T2; |
1434 | 184k | Guint t; |
1435 | | |
1436 | | // 1. prepare the message schedule |
1437 | 3.13M | for (t = 0; t < 16; ++t) { |
1438 | 2.94M | W[t] = ((SHA512Uint64)blk[t*8] << 56) | |
1439 | 2.94M | ((SHA512Uint64)blk[t*8 + 1] << 48) | |
1440 | 2.94M | ((SHA512Uint64)blk[t*8 + 2] << 40) | |
1441 | 2.94M | ((SHA512Uint64)blk[t*8 + 3] << 32) | |
1442 | 2.94M | ((SHA512Uint64)blk[t*8 + 4] << 24) | |
1443 | 2.94M | ((SHA512Uint64)blk[t*8 + 5] << 16) | |
1444 | 2.94M | ((SHA512Uint64)blk[t*8 + 6] << 8) | |
1445 | 2.94M | (SHA512Uint64)blk[t*8 + 7]; |
1446 | 2.94M | } |
1447 | 11.9M | for (t = 16; t < 80; ++t) { |
1448 | 11.7M | W[t] = sha512sigma1(W[t-2]) + W[t-7] + sha512sigma0(W[t-15]) + W[t-16]; |
1449 | 11.7M | } |
1450 | | |
1451 | | // 2. initialize the eight working variables |
1452 | 184k | a = H[0]; |
1453 | 184k | b = H[1]; |
1454 | 184k | c = H[2]; |
1455 | 184k | d = H[3]; |
1456 | 184k | e = H[4]; |
1457 | 184k | f = H[5]; |
1458 | 184k | g = H[6]; |
1459 | 184k | h = H[7]; |
1460 | | |
1461 | | // 3. |
1462 | 14.9M | for (t = 0; t < 80; ++t) { |
1463 | 14.7M | T1 = h + sha512Sigma1(e) + sha512Ch(e,f,g) + sha512K[t] + W[t]; |
1464 | 14.7M | T2 = sha512Sigma0(a) + sha512Maj(a,b,c); |
1465 | 14.7M | h = g; |
1466 | 14.7M | g = f; |
1467 | 14.7M | f = e; |
1468 | 14.7M | e = d + T1; |
1469 | 14.7M | d = c; |
1470 | 14.7M | c = b; |
1471 | 14.7M | b = a; |
1472 | 14.7M | a = T1 + T2; |
1473 | 14.7M | } |
1474 | | |
1475 | | // 4. compute the intermediate hash value |
1476 | 184k | H[0] += a; |
1477 | 184k | H[1] += b; |
1478 | 184k | H[2] += c; |
1479 | 184k | H[3] += d; |
1480 | 184k | H[4] += e; |
1481 | 184k | H[5] += f; |
1482 | 184k | H[6] += g; |
1483 | 184k | H[7] += h; |
1484 | 184k | } |
1485 | | |
1486 | 3.35k | static void sha512(Guchar *msg, int msgLen, Guchar *hash) { |
1487 | 3.35k | Guchar blk[128]; |
1488 | 3.35k | SHA512Uint64 H[8]; |
1489 | 3.35k | int blkLen, i; |
1490 | | |
1491 | 3.35k | H[0] = 0x6a09e667f3bcc908ULL; |
1492 | 3.35k | H[1] = 0xbb67ae8584caa73bULL; |
1493 | 3.35k | H[2] = 0x3c6ef372fe94f82bULL; |
1494 | 3.35k | H[3] = 0xa54ff53a5f1d36f1ULL; |
1495 | 3.35k | H[4] = 0x510e527fade682d1ULL; |
1496 | 3.35k | H[5] = 0x9b05688c2b3e6c1fULL; |
1497 | 3.35k | H[6] = 0x1f83d9abfb41bd6bULL; |
1498 | 3.35k | H[7] = 0x5be0cd19137e2179ULL; |
1499 | | |
1500 | 3.35k | blkLen = 0; |
1501 | 82.5k | for (i = 0; i + 128 <= msgLen; i += 128) { |
1502 | 79.1k | sha512HashBlock(msg + i, H); |
1503 | 79.1k | } |
1504 | 3.35k | blkLen = msgLen - i; |
1505 | 3.35k | if (blkLen > 0) { |
1506 | 0 | memcpy(blk, msg + i, blkLen); |
1507 | 0 | } |
1508 | | |
1509 | | // pad the message |
1510 | 3.35k | blk[blkLen++] = 0x80; |
1511 | 3.35k | if (blkLen > 112) { |
1512 | 0 | while (blkLen < 128) { |
1513 | 0 | blk[blkLen++] = 0; |
1514 | 0 | } |
1515 | 0 | sha512HashBlock(blk, H); |
1516 | 0 | blkLen = 0; |
1517 | 0 | } |
1518 | 376k | while (blkLen < 112) { |
1519 | 372k | blk[blkLen++] = 0; |
1520 | 372k | } |
1521 | 3.35k | blk[112] = 0; |
1522 | 3.35k | blk[113] = 0; |
1523 | 3.35k | blk[114] = 0; |
1524 | 3.35k | blk[115] = 0; |
1525 | 3.35k | blk[116] = 0; |
1526 | 3.35k | blk[117] = 0; |
1527 | 3.35k | blk[118] = 0; |
1528 | 3.35k | blk[119] = 0; |
1529 | 3.35k | blk[120] = 0; |
1530 | 3.35k | blk[121] = 0; |
1531 | 3.35k | blk[122] = 0; |
1532 | 3.35k | blk[123] = 0; |
1533 | 3.35k | blk[124] = (Guchar)(msgLen >> 21); |
1534 | 3.35k | blk[125] = (Guchar)(msgLen >> 13); |
1535 | 3.35k | blk[126] = (Guchar)(msgLen >> 5); |
1536 | 3.35k | blk[127] = (Guchar)(msgLen << 3); |
1537 | 3.35k | sha512HashBlock(blk, H); |
1538 | | |
1539 | | // copy the output into the buffer (convert words to bytes) |
1540 | 30.2k | for (i = 0; i < 8; ++i) { |
1541 | 26.8k | hash[i*8] = (Guchar)(H[i] >> 56); |
1542 | 26.8k | hash[i*8 + 1] = (Guchar)(H[i] >> 48); |
1543 | 26.8k | hash[i*8 + 2] = (Guchar)(H[i] >> 40); |
1544 | 26.8k | hash[i*8 + 3] = (Guchar)(H[i] >> 32); |
1545 | 26.8k | hash[i*8 + 4] = (Guchar)(H[i] >> 24); |
1546 | 26.8k | hash[i*8 + 5] = (Guchar)(H[i] >> 16); |
1547 | 26.8k | hash[i*8 + 6] = (Guchar)(H[i] >> 8); |
1548 | 26.8k | hash[i*8 + 7] = (Guchar)H[i]; |
1549 | 26.8k | } |
1550 | 3.35k | } |
1551 | | |
1552 | 3.99k | static void sha384(Guchar *msg, int msgLen, Guchar *hash) { |
1553 | 3.99k | Guchar blk[128]; |
1554 | 3.99k | SHA512Uint64 H[8]; |
1555 | 3.99k | int blkLen, i; |
1556 | | |
1557 | 3.99k | H[0] = 0xcbbb9d5dc1059ed8ULL; |
1558 | 3.99k | H[1] = 0x629a292a367cd507ULL; |
1559 | 3.99k | H[2] = 0x9159015a3070dd17ULL; |
1560 | 3.99k | H[3] = 0x152fecd8f70e5939ULL; |
1561 | 3.99k | H[4] = 0x67332667ffc00b31ULL; |
1562 | 3.99k | H[5] = 0x8eb44a8768581511ULL; |
1563 | 3.99k | H[6] = 0xdb0c2e0d64f98fa7ULL; |
1564 | 3.99k | H[7] = 0x47b5481dbefa4fa4ULL; |
1565 | | |
1566 | 3.99k | blkLen = 0; |
1567 | 101k | for (i = 0; i + 128 <= msgLen; i += 128) { |
1568 | 97.7k | sha512HashBlock(msg + i, H); |
1569 | 97.7k | } |
1570 | 3.99k | blkLen = msgLen - i; |
1571 | 3.99k | if (blkLen > 0) { |
1572 | 0 | memcpy(blk, msg + i, blkLen); |
1573 | 0 | } |
1574 | | |
1575 | | // pad the message |
1576 | 3.99k | blk[blkLen++] = 0x80; |
1577 | 3.99k | if (blkLen > 112) { |
1578 | 0 | while (blkLen < 128) { |
1579 | 0 | blk[blkLen++] = 0; |
1580 | 0 | } |
1581 | 0 | sha512HashBlock(blk, H); |
1582 | 0 | blkLen = 0; |
1583 | 0 | } |
1584 | 446k | while (blkLen < 112) { |
1585 | 442k | blk[blkLen++] = 0; |
1586 | 442k | } |
1587 | 3.99k | blk[112] = 0; |
1588 | 3.99k | blk[113] = 0; |
1589 | 3.99k | blk[114] = 0; |
1590 | 3.99k | blk[115] = 0; |
1591 | 3.99k | blk[116] = 0; |
1592 | 3.99k | blk[117] = 0; |
1593 | 3.99k | blk[118] = 0; |
1594 | 3.99k | blk[119] = 0; |
1595 | 3.99k | blk[120] = 0; |
1596 | 3.99k | blk[121] = 0; |
1597 | 3.99k | blk[122] = 0; |
1598 | 3.99k | blk[123] = 0; |
1599 | 3.99k | blk[124] = (Guchar)(msgLen >> 21); |
1600 | 3.99k | blk[125] = (Guchar)(msgLen >> 13); |
1601 | 3.99k | blk[126] = (Guchar)(msgLen >> 5); |
1602 | 3.99k | blk[127] = (Guchar)(msgLen << 3); |
1603 | 3.99k | sha512HashBlock(blk, H); |
1604 | | |
1605 | | // copy the output into the buffer (convert words to bytes) |
1606 | 27.9k | for (i = 0; i < 6; ++i) { |
1607 | 23.9k | hash[i*8] = (Guchar)(H[i] >> 56); |
1608 | 23.9k | hash[i*8 + 1] = (Guchar)(H[i] >> 48); |
1609 | 23.9k | hash[i*8 + 2] = (Guchar)(H[i] >> 40); |
1610 | 23.9k | hash[i*8 + 3] = (Guchar)(H[i] >> 32); |
1611 | 23.9k | hash[i*8 + 4] = (Guchar)(H[i] >> 24); |
1612 | 23.9k | hash[i*8 + 5] = (Guchar)(H[i] >> 16); |
1613 | 23.9k | hash[i*8 + 6] = (Guchar)(H[i] >> 8); |
1614 | 23.9k | hash[i*8 + 7] = (Guchar)H[i]; |
1615 | 23.9k | } |
1616 | 3.99k | } |