1 | //======================================================================== |
2 | // |
3 | // Decrypt.cc |
4 | // |
5 | // Copyright 1996-2003 Glyph & Cog, LLC |
6 | // |
7 | //======================================================================== |
8 | |
9 | //======================================================================== |
10 | // |
11 | // Modified under the Poppler project - http://poppler.freedesktop.org |
12 | // |
13 | // All changes made under the Poppler project to this file are licensed |
14 | // under GPL version 2 or later |
15 | // |
16 | // Copyright (C) 2008 Julien Rebetez <julien@fhtagn.net> |
17 | // Copyright (C) 2008, 2010, 2016-2021 Albert Astals Cid <aacid@kde.org> |
18 | // Copyright (C) 2009 Matthias Franz <matthias@ktug.or.kr> |
19 | // Copyright (C) 2009 David Benjamin <davidben@mit.edu> |
20 | // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it> |
21 | // Copyright (C) 2013, 2017 Adrian Johnson <ajohnson@redneon.com> |
22 | // Copyright (C) 2016 Alok Anand <alok4nand@gmail.com> |
23 | // Copyright (C) 2016 Thomas Freitag <Thomas.Freitag@alfa.de> |
24 | // Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de> |
25 | // |
26 | // To see a description of the changes please see the Changelog file that |
27 | // came with your tarball or type make ChangeLog if you are building from git |
28 | // |
29 | //======================================================================== |
30 | |
31 | #include <config.h> |
32 | |
33 | #include <cstdint> |
34 | #include <cstring> |
35 | #include "goo/gmem.h" |
36 | #include "goo/grandom.h" |
37 | #include "Decrypt.h" |
38 | #include "Error.h" |
39 | |
40 | static void rc4InitKey(const unsigned char *key, int keyLen, unsigned char *state); |
41 | static unsigned char rc4DecryptByte(unsigned char *state, unsigned char *x, unsigned char *y, unsigned char c); |
42 | |
43 | static bool aesReadBlock(Stream *str, unsigned char *in, bool addPadding); |
44 | |
45 | static void aesKeyExpansion(DecryptAESState *s, const unsigned char *objKey, int objKeyLen, bool decrypt); |
46 | static void aesEncryptBlock(DecryptAESState *s, const unsigned char *in); |
47 | static void aesDecryptBlock(DecryptAESState *s, const unsigned char *in, bool last); |
48 | |
49 | static void aes256KeyExpansion(DecryptAES256State *s, const unsigned char *objKey, int objKeyLen, bool decrypt); |
50 | static void aes256EncryptBlock(DecryptAES256State *s, const unsigned char *in); |
51 | static void aes256DecryptBlock(DecryptAES256State *s, const unsigned char *in, bool last); |
52 | |
53 | static void sha256(unsigned char *msg, int msgLen, unsigned char *hash); |
54 | static void sha384(unsigned char *msg, int msgLen, unsigned char *hash); |
55 | static void sha512(unsigned char *msg, int msgLen, unsigned char *hash); |
56 | |
57 | static void revision6Hash(const GooString *inputPassword, unsigned char *K, const char *userKey); |
58 | |
59 | static const unsigned char passwordPad[32] = { 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a }; |
60 | |
61 | //------------------------------------------------------------------------ |
62 | // Decrypt |
63 | //------------------------------------------------------------------------ |
64 | |
65 | bool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, const GooString *ownerKey, const GooString *userKey, const GooString *ownerEnc, const GooString *userEnc, int permissions, const GooString *fileID, |
66 | const GooString *ownerPassword, const GooString *userPassword, unsigned char *fileKey, bool encryptMetadata, bool *ownerPasswordOk) |
67 | { |
68 | DecryptAES256State state; |
69 | unsigned char test[127 + 56], test2[32]; |
70 | GooString *userPassword2; |
71 | unsigned char fState[256]; |
72 | unsigned char tmpKey[16]; |
73 | unsigned char fx, fy; |
74 | int len, i, j; |
75 | |
76 | *ownerPasswordOk = false; |
77 | |
78 | if (encRevision == 5 || encRevision == 6) { |
79 | |
80 | // check the owner password |
81 | if (ownerPassword) { |
82 | //~ this is supposed to convert the password to UTF-8 using "SASLprep" |
83 | len = ownerPassword->getLength(); |
84 | if (len > 127) { |
85 | len = 127; |
86 | } |
87 | memcpy(dest: test, src: ownerPassword->c_str(), n: len); |
88 | memcpy(dest: test + len, src: ownerKey->c_str() + 32, n: 8); |
89 | memcpy(dest: test + len + 8, src: userKey->c_str(), n: 48); |
90 | sha256(msg: test, msgLen: len + 56, hash: test); |
91 | if (encRevision == 6) { |
92 | // test contains the initial SHA-256 hash as input K. |
93 | revision6Hash(inputPassword: ownerPassword, K: test, userKey: userKey->c_str()); |
94 | } |
95 | if (!memcmp(s1: test, s2: ownerKey->c_str(), n: 32)) { |
96 | |
97 | // compute the file key from the owner password |
98 | memcpy(dest: test, src: ownerPassword->c_str(), n: len); |
99 | memcpy(dest: test + len, src: ownerKey->c_str() + 40, n: 8); |
100 | memcpy(dest: test + len + 8, src: userKey->c_str(), n: 48); |
101 | sha256(msg: test, msgLen: len + 56, hash: test); |
102 | if (encRevision == 6) { |
103 | // test contains the initial SHA-256 hash input K. |
104 | revision6Hash(inputPassword: ownerPassword, K: test, userKey: userKey->c_str()); |
105 | } |
106 | aes256KeyExpansion(s: &state, objKey: test, objKeyLen: 32, decrypt: true); |
107 | for (i = 0; i < 16; ++i) { |
108 | state.cbc[i] = 0; |
109 | } |
110 | aes256DecryptBlock(s: &state, in: (unsigned char *)ownerEnc->c_str(), last: false); |
111 | memcpy(dest: fileKey, src: state.buf, n: 16); |
112 | aes256DecryptBlock(s: &state, in: (unsigned char *)ownerEnc->c_str() + 16, last: false); |
113 | memcpy(dest: fileKey + 16, src: state.buf, n: 16); |
114 | |
115 | *ownerPasswordOk = true; |
116 | return true; |
117 | } |
118 | } |
119 | |
120 | // check the user password |
121 | if (userPassword) { |
122 | //~ this is supposed to convert the password to UTF-8 using "SASLprep" |
123 | len = userPassword->getLength(); |
124 | if (len > 127) { |
125 | len = 127; |
126 | } |
127 | memcpy(dest: test, src: userPassword->c_str(), n: len); |
128 | memcpy(dest: test + len, src: userKey->c_str() + 32, n: 8); |
129 | sha256(msg: test, msgLen: len + 8, hash: test); |
130 | if (encRevision == 6) { |
131 | // test contains the initial SHA-256 hash input K. |
132 | // user key is not used in checking user password. |
133 | revision6Hash(inputPassword: userPassword, K: test, userKey: nullptr); |
134 | } |
135 | if (!memcmp(s1: test, s2: userKey->c_str(), n: 32)) { |
136 | |
137 | // compute the file key from the user password |
138 | memcpy(dest: test, src: userPassword->c_str(), n: len); |
139 | memcpy(dest: test + len, src: userKey->c_str() + 40, n: 8); |
140 | sha256(msg: test, msgLen: len + 8, hash: test); |
141 | if (encRevision == 6) { |
142 | // test contains the initial SHA-256 hash input K. |
143 | // user key is not used in computing intermediate user key. |
144 | revision6Hash(inputPassword: userPassword, K: test, userKey: nullptr); |
145 | } |
146 | aes256KeyExpansion(s: &state, objKey: test, objKeyLen: 32, decrypt: true); |
147 | for (i = 0; i < 16; ++i) { |
148 | state.cbc[i] = 0; |
149 | } |
150 | aes256DecryptBlock(s: &state, in: (unsigned char *)userEnc->c_str(), last: false); |
151 | memcpy(dest: fileKey, src: state.buf, n: 16); |
152 | aes256DecryptBlock(s: &state, in: (unsigned char *)userEnc->c_str() + 16, last: false); |
153 | memcpy(dest: fileKey + 16, src: state.buf, n: 16); |
154 | |
155 | return true; |
156 | } |
157 | } |
158 | |
159 | return false; |
160 | } else { |
161 | |
162 | // try using the supplied owner password to generate the user password |
163 | if (ownerPassword) { |
164 | len = ownerPassword->getLength(); |
165 | if (len < 32) { |
166 | memcpy(dest: test, src: ownerPassword->c_str(), n: len); |
167 | memcpy(dest: test + len, src: passwordPad, n: 32 - len); |
168 | } else { |
169 | memcpy(dest: test, src: ownerPassword->c_str(), n: 32); |
170 | } |
171 | md5(msg: test, msgLen: 32, digest: test); |
172 | if (encRevision == 3) { |
173 | for (i = 0; i < 50; ++i) { |
174 | md5(msg: test, msgLen: keyLength, digest: test); |
175 | } |
176 | } |
177 | if (encRevision == 2) { |
178 | rc4InitKey(key: test, keyLen: keyLength, state: fState); |
179 | fx = fy = 0; |
180 | for (i = 0; i < 32; ++i) { |
181 | test2[i] = rc4DecryptByte(state: fState, x: &fx, y: &fy, c: ownerKey->getChar(i)); |
182 | } |
183 | } else { |
184 | memcpy(dest: test2, src: ownerKey->c_str(), n: 32); |
185 | for (i = 19; i >= 0; --i) { |
186 | for (j = 0; j < keyLength; ++j) { |
187 | tmpKey[j] = test[j] ^ i; |
188 | } |
189 | rc4InitKey(key: tmpKey, keyLen: keyLength, state: fState); |
190 | fx = fy = 0; |
191 | for (j = 0; j < 32; ++j) { |
192 | test2[j] = rc4DecryptByte(state: fState, x: &fx, y: &fy, c: test2[j]); |
193 | } |
194 | } |
195 | } |
196 | userPassword2 = new GooString((char *)test2, 32); |
197 | if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey, permissions, fileID, userPassword: userPassword2, fileKey, encryptMetadata)) { |
198 | *ownerPasswordOk = true; |
199 | delete userPassword2; |
200 | return true; |
201 | } |
202 | delete userPassword2; |
203 | } |
204 | |
205 | // try using the supplied user password |
206 | return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey, permissions, fileID, userPassword, fileKey, encryptMetadata); |
207 | } |
208 | } |
209 | |
210 | bool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength, const GooString *ownerKey, const GooString *userKey, int permissions, const GooString *fileID, const GooString *userPassword, unsigned char *fileKey, |
211 | bool encryptMetadata) |
212 | { |
213 | unsigned char *buf; |
214 | unsigned char test[32]; |
215 | unsigned char fState[256]; |
216 | unsigned char tmpKey[16]; |
217 | unsigned char fx, fy; |
218 | int len, i, j; |
219 | bool ok; |
220 | |
221 | // generate file key |
222 | buf = (unsigned char *)gmalloc(size: 72 + fileID->getLength()); |
223 | if (userPassword) { |
224 | len = userPassword->getLength(); |
225 | if (len < 32) { |
226 | memcpy(dest: buf, src: userPassword->c_str(), n: len); |
227 | memcpy(dest: buf + len, src: passwordPad, n: 32 - len); |
228 | } else { |
229 | memcpy(dest: buf, src: userPassword->c_str(), n: 32); |
230 | } |
231 | } else { |
232 | memcpy(dest: buf, src: passwordPad, n: 32); |
233 | } |
234 | memcpy(dest: buf + 32, src: ownerKey->c_str(), n: 32); |
235 | buf[64] = permissions & 0xff; |
236 | buf[65] = (permissions >> 8) & 0xff; |
237 | buf[66] = (permissions >> 16) & 0xff; |
238 | buf[67] = (permissions >> 24) & 0xff; |
239 | memcpy(dest: buf + 68, src: fileID->c_str(), n: fileID->getLength()); |
240 | len = 68 + fileID->getLength(); |
241 | if (!encryptMetadata) { |
242 | buf[len++] = 0xff; |
243 | buf[len++] = 0xff; |
244 | buf[len++] = 0xff; |
245 | buf[len++] = 0xff; |
246 | } |
247 | md5(msg: buf, msgLen: len, digest: fileKey); |
248 | if (encRevision == 3) { |
249 | for (i = 0; i < 50; ++i) { |
250 | md5(msg: fileKey, msgLen: keyLength, digest: fileKey); |
251 | } |
252 | } |
253 | |
254 | // test user password |
255 | if (encRevision == 2) { |
256 | rc4InitKey(key: fileKey, keyLen: keyLength, state: fState); |
257 | fx = fy = 0; |
258 | for (i = 0; i < 32; ++i) { |
259 | test[i] = rc4DecryptByte(state: fState, x: &fx, y: &fy, c: userKey->getChar(i)); |
260 | } |
261 | ok = memcmp(s1: test, s2: passwordPad, n: 32) == 0; |
262 | } else if (encRevision == 3) { |
263 | memcpy(dest: test, src: userKey->c_str(), n: 32); |
264 | for (i = 19; i >= 0; --i) { |
265 | for (j = 0; j < keyLength; ++j) { |
266 | tmpKey[j] = fileKey[j] ^ i; |
267 | } |
268 | rc4InitKey(key: tmpKey, keyLen: keyLength, state: fState); |
269 | fx = fy = 0; |
270 | for (j = 0; j < 32; ++j) { |
271 | test[j] = rc4DecryptByte(state: fState, x: &fx, y: &fy, c: test[j]); |
272 | } |
273 | } |
274 | memcpy(dest: buf, src: passwordPad, n: 32); |
275 | memcpy(dest: buf + 32, src: fileID->c_str(), n: fileID->getLength()); |
276 | md5(msg: buf, msgLen: 32 + fileID->getLength(), digest: buf); |
277 | ok = memcmp(s1: test, s2: buf, n: 16) == 0; |
278 | } else { |
279 | ok = false; |
280 | } |
281 | |
282 | gfree(p: buf); |
283 | return ok; |
284 | } |
285 | |
286 | //------------------------------------------------------------------------ |
287 | // BaseCryptStream |
288 | //------------------------------------------------------------------------ |
289 | |
290 | BaseCryptStream::BaseCryptStream(Stream *strA, const unsigned char *fileKey, CryptAlgorithm algoA, int keyLength, Ref refA) : FilterStream(strA) |
291 | { |
292 | algo = algoA; |
293 | |
294 | // construct object key |
295 | for (int i = 0; i < keyLength; ++i) { |
296 | objKey[i] = fileKey[i]; |
297 | } |
298 | for (std::size_t i = keyLength; i < sizeof(objKey); ++i) { |
299 | objKey[i] = 0; |
300 | } |
301 | |
302 | switch (algo) { |
303 | case cryptRC4: |
304 | if (likely(keyLength < static_cast<int>(sizeof(objKey) - 4))) { |
305 | objKey[keyLength] = refA.num & 0xff; |
306 | objKey[keyLength + 1] = (refA.num >> 8) & 0xff; |
307 | objKey[keyLength + 2] = (refA.num >> 16) & 0xff; |
308 | objKey[keyLength + 3] = refA.gen & 0xff; |
309 | objKey[keyLength + 4] = (refA.gen >> 8) & 0xff; |
310 | md5(msg: objKey, msgLen: keyLength + 5, digest: objKey); |
311 | } |
312 | if ((objKeyLength = keyLength + 5) > 16) { |
313 | objKeyLength = 16; |
314 | } |
315 | break; |
316 | case cryptAES: |
317 | objKey[keyLength] = refA.num & 0xff; |
318 | objKey[keyLength + 1] = (refA.num >> 8) & 0xff; |
319 | objKey[keyLength + 2] = (refA.num >> 16) & 0xff; |
320 | objKey[keyLength + 3] = refA.gen & 0xff; |
321 | objKey[keyLength + 4] = (refA.gen >> 8) & 0xff; |
322 | objKey[keyLength + 5] = 0x73; // 's' |
323 | objKey[keyLength + 6] = 0x41; // 'A' |
324 | objKey[keyLength + 7] = 0x6c; // 'l' |
325 | objKey[keyLength + 8] = 0x54; // 'T' |
326 | md5(msg: objKey, msgLen: keyLength + 9, digest: objKey); |
327 | if ((objKeyLength = keyLength + 5) > 16) { |
328 | objKeyLength = 16; |
329 | } |
330 | break; |
331 | case cryptAES256: |
332 | objKeyLength = keyLength; |
333 | break; |
334 | case cryptNone: |
335 | break; |
336 | } |
337 | |
338 | charactersRead = 0; |
339 | nextCharBuff = EOF; |
340 | autoDelete = true; |
341 | } |
342 | |
343 | BaseCryptStream::~BaseCryptStream() |
344 | { |
345 | if (autoDelete) { |
346 | delete str; |
347 | } |
348 | } |
349 | |
350 | void BaseCryptStream::reset() |
351 | { |
352 | charactersRead = 0; |
353 | nextCharBuff = EOF; |
354 | str->reset(); |
355 | } |
356 | |
357 | Goffset BaseCryptStream::getPos() |
358 | { |
359 | return charactersRead; |
360 | } |
361 | |
362 | int BaseCryptStream::getChar() |
363 | { |
364 | // Read next character and empty the buffer, so that a new character will be read next time |
365 | int c = lookChar(); |
366 | nextCharBuff = EOF; |
367 | |
368 | if (c != EOF) { |
369 | charactersRead++; |
370 | } |
371 | return c; |
372 | } |
373 | |
374 | bool BaseCryptStream::isBinary(bool last) const |
375 | { |
376 | return str->isBinary(last); |
377 | } |
378 | |
379 | void BaseCryptStream::setAutoDelete(bool val) |
380 | { |
381 | autoDelete = val; |
382 | } |
383 | |
384 | //------------------------------------------------------------------------ |
385 | // EncryptStream |
386 | //------------------------------------------------------------------------ |
387 | |
388 | EncryptStream::EncryptStream(Stream *strA, const unsigned char *fileKey, CryptAlgorithm algoA, int keyLength, Ref refA) : BaseCryptStream(strA, fileKey, algoA, keyLength, refA) |
389 | { |
390 | // Fill the CBC initialization vector for AES and AES-256 |
391 | switch (algo) { |
392 | case cryptAES: |
393 | grandom_fill(buff: state.aes.cbc, size: 16); |
394 | break; |
395 | case cryptAES256: |
396 | grandom_fill(buff: state.aes256.cbc, size: 16); |
397 | break; |
398 | default: |
399 | break; |
400 | } |
401 | } |
402 | |
403 | EncryptStream::~EncryptStream() { } |
404 | |
405 | void EncryptStream::reset() |
406 | { |
407 | BaseCryptStream::reset(); |
408 | |
409 | switch (algo) { |
410 | case cryptRC4: |
411 | state.rc4.x = state.rc4.y = 0; |
412 | rc4InitKey(key: objKey, keyLen: objKeyLength, state: state.rc4.state); |
413 | break; |
414 | case cryptAES: |
415 | aesKeyExpansion(s: &state.aes, objKey, objKeyLen: objKeyLength, decrypt: false); |
416 | memcpy(dest: state.aes.buf, src: state.aes.cbc, n: 16); // Copy CBC IV to buf |
417 | state.aes.bufIdx = 0; |
418 | state.aes.paddingReached = false; |
419 | break; |
420 | case cryptAES256: |
421 | aes256KeyExpansion(s: &state.aes256, objKey, objKeyLen: objKeyLength, decrypt: false); |
422 | memcpy(dest: state.aes256.buf, src: state.aes256.cbc, n: 16); // Copy CBC IV to buf |
423 | state.aes256.bufIdx = 0; |
424 | state.aes256.paddingReached = false; |
425 | break; |
426 | case cryptNone: |
427 | break; |
428 | } |
429 | } |
430 | |
431 | int EncryptStream::lookChar() |
432 | { |
433 | unsigned char in[16]; |
434 | int c; |
435 | |
436 | if (nextCharBuff != EOF) { |
437 | return nextCharBuff; |
438 | } |
439 | |
440 | c = EOF; // make gcc happy |
441 | switch (algo) { |
442 | case cryptRC4: |
443 | if ((c = str->getChar()) != EOF) { |
444 | // RC4 is XOR-based: the decryption algorithm works for encryption too |
445 | c = rc4DecryptByte(state: state.rc4.state, x: &state.rc4.x, y: &state.rc4.y, c: (unsigned char)c); |
446 | } |
447 | break; |
448 | case cryptAES: |
449 | if (state.aes.bufIdx == 16 && !state.aes.paddingReached) { |
450 | state.aes.paddingReached = !aesReadBlock(str, in, addPadding: true); |
451 | aesEncryptBlock(s: &state.aes, in); |
452 | } |
453 | if (state.aes.bufIdx == 16) { |
454 | c = EOF; |
455 | } else { |
456 | c = state.aes.buf[state.aes.bufIdx++]; |
457 | } |
458 | break; |
459 | case cryptAES256: |
460 | if (state.aes256.bufIdx == 16 && !state.aes256.paddingReached) { |
461 | state.aes256.paddingReached = !aesReadBlock(str, in, addPadding: true); |
462 | aes256EncryptBlock(s: &state.aes256, in); |
463 | } |
464 | if (state.aes256.bufIdx == 16) { |
465 | c = EOF; |
466 | } else { |
467 | c = state.aes256.buf[state.aes256.bufIdx++]; |
468 | } |
469 | break; |
470 | case cryptNone: |
471 | break; |
472 | } |
473 | return (nextCharBuff = c); |
474 | } |
475 | |
476 | //------------------------------------------------------------------------ |
477 | // DecryptStream |
478 | //------------------------------------------------------------------------ |
479 | |
480 | DecryptStream::DecryptStream(Stream *strA, const unsigned char *fileKey, CryptAlgorithm algoA, int keyLength, Ref refA) : BaseCryptStream(strA, fileKey, algoA, keyLength, refA) { } |
481 | |
482 | DecryptStream::~DecryptStream() { } |
483 | |
484 | void DecryptStream::reset() |
485 | { |
486 | int i; |
487 | BaseCryptStream::reset(); |
488 | |
489 | switch (algo) { |
490 | case cryptRC4: |
491 | state.rc4.x = state.rc4.y = 0; |
492 | rc4InitKey(key: objKey, keyLen: objKeyLength, state: state.rc4.state); |
493 | break; |
494 | case cryptAES: |
495 | aesKeyExpansion(s: &state.aes, objKey, objKeyLen: objKeyLength, decrypt: true); |
496 | for (i = 0; i < 16; ++i) { |
497 | state.aes.cbc[i] = str->getChar(); |
498 | } |
499 | state.aes.bufIdx = 16; |
500 | break; |
501 | case cryptAES256: |
502 | aes256KeyExpansion(s: &state.aes256, objKey, objKeyLen: objKeyLength, decrypt: true); |
503 | for (i = 0; i < 16; ++i) { |
504 | state.aes256.cbc[i] = str->getChar(); |
505 | } |
506 | state.aes256.bufIdx = 16; |
507 | break; |
508 | case cryptNone: |
509 | break; |
510 | } |
511 | } |
512 | |
513 | int DecryptStream::lookChar() |
514 | { |
515 | unsigned char in[16]; |
516 | int c; |
517 | |
518 | if (nextCharBuff != EOF) { |
519 | return nextCharBuff; |
520 | } |
521 | |
522 | c = EOF; // make gcc happy |
523 | switch (algo) { |
524 | case cryptRC4: |
525 | if ((c = str->getChar()) != EOF) { |
526 | c = rc4DecryptByte(state: state.rc4.state, x: &state.rc4.x, y: &state.rc4.y, c: (unsigned char)c); |
527 | } |
528 | break; |
529 | case cryptAES: |
530 | if (state.aes.bufIdx == 16) { |
531 | if (aesReadBlock(str, in, addPadding: false)) { |
532 | aesDecryptBlock(s: &state.aes, in, last: str->lookChar() == EOF); |
533 | } |
534 | } |
535 | if (state.aes.bufIdx == 16) { |
536 | c = EOF; |
537 | } else { |
538 | c = state.aes.buf[state.aes.bufIdx++]; |
539 | } |
540 | break; |
541 | case cryptAES256: |
542 | if (state.aes256.bufIdx == 16) { |
543 | if (aesReadBlock(str, in, addPadding: false)) { |
544 | aes256DecryptBlock(s: &state.aes256, in, last: str->lookChar() == EOF); |
545 | } |
546 | } |
547 | if (state.aes256.bufIdx == 16) { |
548 | c = EOF; |
549 | } else { |
550 | c = state.aes256.buf[state.aes256.bufIdx++]; |
551 | } |
552 | break; |
553 | case cryptNone: |
554 | break; |
555 | } |
556 | return (nextCharBuff = c); |
557 | } |
558 | |
559 | //------------------------------------------------------------------------ |
560 | // RC4-compatible decryption |
561 | //------------------------------------------------------------------------ |
562 | |
563 | static void rc4InitKey(const unsigned char *key, int keyLen, unsigned char *state) |
564 | { |
565 | unsigned char index1, index2; |
566 | unsigned char t; |
567 | int i; |
568 | |
569 | for (i = 0; i < 256; ++i) { |
570 | state[i] = i; |
571 | } |
572 | |
573 | if (unlikely(keyLen == 0)) { |
574 | return; |
575 | } |
576 | |
577 | index1 = index2 = 0; |
578 | for (i = 0; i < 256; ++i) { |
579 | index2 = (key[index1] + state[i] + index2) % 256; |
580 | t = state[i]; |
581 | state[i] = state[index2]; |
582 | state[index2] = t; |
583 | index1 = (index1 + 1) % keyLen; |
584 | } |
585 | } |
586 | |
587 | static unsigned char rc4DecryptByte(unsigned char *state, unsigned char *x, unsigned char *y, unsigned char c) |
588 | { |
589 | unsigned char x1, y1, tx, ty; |
590 | |
591 | x1 = *x = (*x + 1) % 256; |
592 | y1 = *y = (state[*x] + *y) % 256; |
593 | tx = state[x1]; |
594 | ty = state[y1]; |
595 | state[x1] = ty; |
596 | state[y1] = tx; |
597 | return c ^ state[(tx + ty) % 256]; |
598 | } |
599 | |
600 | //------------------------------------------------------------------------ |
601 | // AES decryption |
602 | //------------------------------------------------------------------------ |
603 | |
604 | // Returns false if EOF was reached, true otherwise |
605 | static bool aesReadBlock(Stream *str, unsigned char *in, bool addPadding) |
606 | { |
607 | int c, i; |
608 | |
609 | for (i = 0; i < 16; ++i) { |
610 | if ((c = str->getChar()) != EOF) { |
611 | in[i] = (unsigned char)c; |
612 | } else { |
613 | break; |
614 | } |
615 | } |
616 | |
617 | if (i == 16) { |
618 | return true; |
619 | } else { |
620 | if (addPadding) { |
621 | c = 16 - i; |
622 | while (i < 16) { |
623 | in[i++] = (unsigned char)c; |
624 | } |
625 | } |
626 | return false; |
627 | } |
628 | } |
629 | |
630 | static const unsigned char sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, |
631 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, |
632 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, |
633 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, |
634 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, |
635 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, |
636 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, |
637 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; |
638 | |
639 | static const unsigned char invSbox[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, |
640 | 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, |
641 | 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, |
642 | 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, |
643 | 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, |
644 | 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, |
645 | 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, |
646 | 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; |
647 | |
648 | static const unsigned int rcon[11] = { 0x00000000, // unused |
649 | 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000 }; |
650 | |
651 | static inline unsigned int subWord(unsigned int x) |
652 | { |
653 | return (sbox[x >> 24] << 24) | (sbox[(x >> 16) & 0xff] << 16) | (sbox[(x >> 8) & 0xff] << 8) | sbox[x & 0xff]; |
654 | } |
655 | |
656 | static inline unsigned int rotWord(unsigned int x) |
657 | { |
658 | return ((x << 8) & 0xffffffff) | (x >> 24); |
659 | } |
660 | |
661 | static inline void subBytes(unsigned char *state) |
662 | { |
663 | int i; |
664 | |
665 | for (i = 0; i < 16; ++i) { |
666 | state[i] = sbox[state[i]]; |
667 | } |
668 | } |
669 | |
670 | static inline void invSubBytes(unsigned char *state) |
671 | { |
672 | int i; |
673 | |
674 | for (i = 0; i < 16; ++i) { |
675 | state[i] = invSbox[state[i]]; |
676 | } |
677 | } |
678 | |
679 | static inline void shiftRows(unsigned char *state) |
680 | { |
681 | unsigned char t; |
682 | |
683 | t = state[4]; |
684 | state[4] = state[5]; |
685 | state[5] = state[6]; |
686 | state[6] = state[7]; |
687 | state[7] = t; |
688 | |
689 | t = state[8]; |
690 | state[8] = state[10]; |
691 | state[10] = t; |
692 | t = state[9]; |
693 | state[9] = state[11]; |
694 | state[11] = t; |
695 | |
696 | t = state[15]; |
697 | state[15] = state[14]; |
698 | state[14] = state[13]; |
699 | state[13] = state[12]; |
700 | state[12] = t; |
701 | } |
702 | |
703 | static inline void invShiftRows(unsigned char *state) |
704 | { |
705 | unsigned char t; |
706 | |
707 | t = state[7]; |
708 | state[7] = state[6]; |
709 | state[6] = state[5]; |
710 | state[5] = state[4]; |
711 | state[4] = t; |
712 | |
713 | t = state[8]; |
714 | state[8] = state[10]; |
715 | state[10] = t; |
716 | t = state[9]; |
717 | state[9] = state[11]; |
718 | state[11] = t; |
719 | |
720 | t = state[12]; |
721 | state[12] = state[13]; |
722 | state[13] = state[14]; |
723 | state[14] = state[15]; |
724 | state[15] = t; |
725 | } |
726 | |
727 | // {02} \cdot s |
728 | struct Mul02Table |
729 | { |
730 | constexpr Mul02Table() : values() |
731 | { |
732 | for (int s = 0; s < 256; s++) { |
733 | values[s] = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1); |
734 | } |
735 | } |
736 | |
737 | constexpr unsigned char operator()(uint8_t i) const { return values[i]; } |
738 | |
739 | unsigned char values[256]; |
740 | }; |
741 | |
742 | static constexpr Mul02Table mul02; |
743 | |
744 | // {03} \cdot s |
745 | struct Mul03Table |
746 | { |
747 | constexpr Mul03Table() : values() |
748 | { |
749 | for (int s = 0; s < 256; s++) { |
750 | const unsigned char s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1); |
751 | values[s] = s ^ s2; |
752 | } |
753 | } |
754 | |
755 | constexpr unsigned char operator()(uint8_t i) const { return values[i]; } |
756 | |
757 | unsigned char values[256]; |
758 | }; |
759 | |
760 | static constexpr Mul03Table mul03; |
761 | |
762 | // {09} \cdot s |
763 | struct Mul09Table |
764 | { |
765 | constexpr Mul09Table() : values() |
766 | { |
767 | for (int s = 0; s < 256; s++) { |
768 | const unsigned char s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1); |
769 | const unsigned char s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1); |
770 | const unsigned char s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1); |
771 | values[s] = s ^ s8; |
772 | } |
773 | } |
774 | |
775 | constexpr unsigned char operator()(uint8_t i) const { return values[i]; } |
776 | |
777 | unsigned char values[256]; |
778 | }; |
779 | |
780 | static constexpr Mul09Table mul09; |
781 | |
782 | // {0b} \cdot s |
783 | struct Mul0bTable |
784 | { |
785 | constexpr Mul0bTable() : values() |
786 | { |
787 | for (int s = 0; s < 256; s++) { |
788 | const unsigned char s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1); |
789 | const unsigned char s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1); |
790 | const unsigned char s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1); |
791 | values[s] = s ^ s2 ^ s8; |
792 | } |
793 | } |
794 | |
795 | constexpr unsigned char operator()(uint8_t i) const { return values[i]; } |
796 | |
797 | unsigned char values[256]; |
798 | }; |
799 | |
800 | static constexpr Mul0bTable mul0b; |
801 | |
802 | // {0d} \cdot s |
803 | struct Mul0dTable |
804 | { |
805 | constexpr Mul0dTable() : values() |
806 | { |
807 | for (int s = 0; s < 256; s++) { |
808 | const unsigned char s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1); |
809 | const unsigned char s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1); |
810 | const unsigned char s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1); |
811 | values[s] = s ^ s4 ^ s8; |
812 | } |
813 | } |
814 | |
815 | constexpr unsigned char operator()(uint8_t i) const { return values[i]; } |
816 | |
817 | unsigned char values[256]; |
818 | }; |
819 | |
820 | static constexpr Mul0dTable mul0d; |
821 | |
822 | // {0e} \cdot s |
823 | struct Mul0eTable |
824 | { |
825 | constexpr Mul0eTable() : values() |
826 | { |
827 | for (int s = 0; s < 256; s++) { |
828 | const unsigned char s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1); |
829 | const unsigned char s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1); |
830 | const unsigned char s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1); |
831 | values[s] = s2 ^ s4 ^ s8; |
832 | } |
833 | } |
834 | |
835 | constexpr unsigned char operator()(uint8_t i) const { return values[i]; } |
836 | |
837 | unsigned char values[256]; |
838 | }; |
839 | |
840 | static constexpr Mul0eTable mul0e; |
841 | |
842 | static inline void mixColumns(unsigned char *state) |
843 | { |
844 | int c; |
845 | unsigned char s0, s1, s2, s3; |
846 | |
847 | for (c = 0; c < 4; ++c) { |
848 | s0 = state[c]; |
849 | s1 = state[4 + c]; |
850 | s2 = state[8 + c]; |
851 | s3 = state[12 + c]; |
852 | state[c] = mul02(s0) ^ mul03(s1) ^ s2 ^ s3; |
853 | state[4 + c] = s0 ^ mul02(s1) ^ mul03(s2) ^ s3; |
854 | state[8 + c] = s0 ^ s1 ^ mul02(s2) ^ mul03(s3); |
855 | state[12 + c] = mul03(s0) ^ s1 ^ s2 ^ mul02(s3); |
856 | } |
857 | } |
858 | |
859 | static inline void invMixColumns(unsigned char *state) |
860 | { |
861 | int c; |
862 | unsigned char s0, s1, s2, s3; |
863 | |
864 | for (c = 0; c < 4; ++c) { |
865 | s0 = state[c]; |
866 | s1 = state[4 + c]; |
867 | s2 = state[8 + c]; |
868 | s3 = state[12 + c]; |
869 | state[c] = mul0e(s0) ^ mul0b(s1) ^ mul0d(s2) ^ mul09(s3); |
870 | state[4 + c] = mul09(s0) ^ mul0e(s1) ^ mul0b(s2) ^ mul0d(s3); |
871 | state[8 + c] = mul0d(s0) ^ mul09(s1) ^ mul0e(s2) ^ mul0b(s3); |
872 | state[12 + c] = mul0b(s0) ^ mul0d(s1) ^ mul09(s2) ^ mul0e(s3); |
873 | } |
874 | } |
875 | |
876 | static inline void invMixColumnsW(unsigned int *w) |
877 | { |
878 | int c; |
879 | unsigned char s0, s1, s2, s3; |
880 | |
881 | for (c = 0; c < 4; ++c) { |
882 | s0 = w[c] >> 24; |
883 | s1 = w[c] >> 16; |
884 | s2 = w[c] >> 8; |
885 | s3 = w[c]; |
886 | w[c] = ((mul0e(s0) ^ mul0b(s1) ^ mul0d(s2) ^ mul09(s3)) << 24) | ((mul09(s0) ^ mul0e(s1) ^ mul0b(s2) ^ mul0d(s3)) << 16) | ((mul0d(s0) ^ mul09(s1) ^ mul0e(s2) ^ mul0b(s3)) << 8) | (mul0b(s0) ^ mul0d(s1) ^ mul09(s2) ^ mul0e(s3)); |
887 | } |
888 | } |
889 | |
890 | static inline void addRoundKey(unsigned char *state, const unsigned int *w) |
891 | { |
892 | int c; |
893 | |
894 | for (c = 0; c < 4; ++c) { |
895 | state[c] ^= w[c] >> 24; |
896 | state[4 + c] ^= w[c] >> 16; |
897 | state[8 + c] ^= w[c] >> 8; |
898 | state[12 + c] ^= w[c]; |
899 | } |
900 | } |
901 | |
902 | static void aesKeyExpansion(DecryptAESState *s, const unsigned char *objKey, int /*objKeyLen*/, bool decrypt) |
903 | { |
904 | unsigned int temp; |
905 | int i, round; |
906 | |
907 | //~ this assumes objKeyLen == 16 |
908 | |
909 | for (i = 0; i < 4; ++i) { |
910 | s->w[i] = (objKey[4 * i] << 24) + (objKey[4 * i + 1] << 16) + (objKey[4 * i + 2] << 8) + objKey[4 * i + 3]; |
911 | } |
912 | for (i = 4; i < 44; ++i) { |
913 | temp = s->w[i - 1]; |
914 | if (!(i & 3)) { |
915 | temp = subWord(x: rotWord(x: temp)) ^ rcon[i / 4]; |
916 | } |
917 | s->w[i] = s->w[i - 4] ^ temp; |
918 | } |
919 | |
920 | /* In case of decryption, adjust the key schedule for the equivalent inverse cipher */ |
921 | if (decrypt) { |
922 | for (round = 1; round <= 9; ++round) { |
923 | invMixColumnsW(w: &s->w[round * 4]); |
924 | } |
925 | } |
926 | } |
927 | |
928 | static void aesEncryptBlock(DecryptAESState *s, const unsigned char *in) |
929 | { |
930 | int c, round; |
931 | |
932 | // initial state (input is xor'd with previous output because of CBC) |
933 | for (c = 0; c < 4; ++c) { |
934 | s->state[c] = in[4 * c] ^ s->buf[4 * c]; |
935 | s->state[4 + c] = in[4 * c + 1] ^ s->buf[4 * c + 1]; |
936 | s->state[8 + c] = in[4 * c + 2] ^ s->buf[4 * c + 2]; |
937 | s->state[12 + c] = in[4 * c + 3] ^ s->buf[4 * c + 3]; |
938 | } |
939 | |
940 | // round 0 |
941 | addRoundKey(state: s->state, w: &s->w[0]); |
942 | |
943 | // rounds 1-9 |
944 | for (round = 1; round <= 9; ++round) { |
945 | subBytes(state: s->state); |
946 | shiftRows(state: s->state); |
947 | mixColumns(state: s->state); |
948 | addRoundKey(state: s->state, w: &s->w[round * 4]); |
949 | } |
950 | |
951 | // round 10 |
952 | subBytes(state: s->state); |
953 | shiftRows(state: s->state); |
954 | addRoundKey(state: s->state, w: &s->w[10 * 4]); |
955 | |
956 | for (c = 0; c < 4; ++c) { |
957 | s->buf[4 * c] = s->state[c]; |
958 | s->buf[4 * c + 1] = s->state[4 + c]; |
959 | s->buf[4 * c + 2] = s->state[8 + c]; |
960 | s->buf[4 * c + 3] = s->state[12 + c]; |
961 | } |
962 | |
963 | s->bufIdx = 0; |
964 | } |
965 | |
966 | static void aesDecryptBlock(DecryptAESState *s, const unsigned char *in, bool last) |
967 | { |
968 | int c, round, n, i; |
969 | |
970 | // initial state |
971 | for (c = 0; c < 4; ++c) { |
972 | s->state[c] = in[4 * c]; |
973 | s->state[4 + c] = in[4 * c + 1]; |
974 | s->state[8 + c] = in[4 * c + 2]; |
975 | s->state[12 + c] = in[4 * c + 3]; |
976 | } |
977 | |
978 | // round 0 |
979 | addRoundKey(state: s->state, w: &s->w[10 * 4]); |
980 | |
981 | // rounds 1-9 |
982 | for (round = 9; round >= 1; --round) { |
983 | invSubBytes(state: s->state); |
984 | invShiftRows(state: s->state); |
985 | invMixColumns(state: s->state); |
986 | addRoundKey(state: s->state, w: &s->w[round * 4]); |
987 | } |
988 | |
989 | // round 10 |
990 | invSubBytes(state: s->state); |
991 | invShiftRows(state: s->state); |
992 | addRoundKey(state: s->state, w: &s->w[0]); |
993 | |
994 | // CBC |
995 | for (c = 0; c < 4; ++c) { |
996 | s->buf[4 * c] = s->state[c] ^ s->cbc[4 * c]; |
997 | s->buf[4 * c + 1] = s->state[4 + c] ^ s->cbc[4 * c + 1]; |
998 | s->buf[4 * c + 2] = s->state[8 + c] ^ s->cbc[4 * c + 2]; |
999 | s->buf[4 * c + 3] = s->state[12 + c] ^ s->cbc[4 * c + 3]; |
1000 | } |
1001 | |
1002 | // save the input block for the next CBC |
1003 | for (i = 0; i < 16; ++i) { |
1004 | s->cbc[i] = in[i]; |
1005 | } |
1006 | |
1007 | // remove padding |
1008 | s->bufIdx = 0; |
1009 | if (last) { |
1010 | n = s->buf[15]; |
1011 | if (n < 1 || n > 16) { // this should never happen |
1012 | n = 16; |
1013 | } |
1014 | for (i = 15; i >= n; --i) { |
1015 | s->buf[i] = s->buf[i - n]; |
1016 | } |
1017 | s->bufIdx = n; |
1018 | } |
1019 | } |
1020 | |
1021 | //------------------------------------------------------------------------ |
1022 | // AES-256 decryption |
1023 | //------------------------------------------------------------------------ |
1024 | |
1025 | static void aes256KeyExpansion(DecryptAES256State *s, const unsigned char *objKey, int objKeyLen, bool decrypt) |
1026 | { |
1027 | unsigned int temp; |
1028 | int i, round; |
1029 | |
1030 | //~ this assumes objKeyLen == 32 |
1031 | |
1032 | for (i = 0; i < 8; ++i) { |
1033 | s->w[i] = (objKey[4 * i] << 24) + (objKey[4 * i + 1] << 16) + (objKey[4 * i + 2] << 8) + objKey[4 * i + 3]; |
1034 | } |
1035 | for (i = 8; i < 60; ++i) { |
1036 | temp = s->w[i - 1]; |
1037 | if ((i & 7) == 0) { |
1038 | temp = subWord(x: rotWord(x: temp)) ^ rcon[i / 8]; |
1039 | } else if ((i & 7) == 4) { |
1040 | temp = subWord(x: temp); |
1041 | } |
1042 | s->w[i] = s->w[i - 8] ^ temp; |
1043 | } |
1044 | |
1045 | /* In case of decryption, adjust the key schedule for the equivalent inverse cipher */ |
1046 | if (decrypt) { |
1047 | for (round = 1; round <= 13; ++round) { |
1048 | invMixColumnsW(w: &s->w[round * 4]); |
1049 | } |
1050 | } |
1051 | } |
1052 | |
1053 | static void aes256EncryptBlock(DecryptAES256State *s, const unsigned char *in) |
1054 | { |
1055 | int c, round; |
1056 | |
1057 | // initial state (input is xor'd with previous output because of CBC) |
1058 | for (c = 0; c < 4; ++c) { |
1059 | s->state[c] = in[4 * c] ^ s->buf[4 * c]; |
1060 | s->state[4 + c] = in[4 * c + 1] ^ s->buf[4 * c + 1]; |
1061 | s->state[8 + c] = in[4 * c + 2] ^ s->buf[4 * c + 2]; |
1062 | s->state[12 + c] = in[4 * c + 3] ^ s->buf[4 * c + 3]; |
1063 | } |
1064 | |
1065 | // round 0 |
1066 | addRoundKey(state: s->state, w: &s->w[0]); |
1067 | |
1068 | // rounds 1-13 |
1069 | for (round = 1; round <= 13; ++round) { |
1070 | subBytes(state: s->state); |
1071 | shiftRows(state: s->state); |
1072 | mixColumns(state: s->state); |
1073 | addRoundKey(state: s->state, w: &s->w[round * 4]); |
1074 | } |
1075 | |
1076 | // round 14 |
1077 | subBytes(state: s->state); |
1078 | shiftRows(state: s->state); |
1079 | addRoundKey(state: s->state, w: &s->w[14 * 4]); |
1080 | |
1081 | for (c = 0; c < 4; ++c) { |
1082 | s->buf[4 * c] = s->state[c]; |
1083 | s->buf[4 * c + 1] = s->state[4 + c]; |
1084 | s->buf[4 * c + 2] = s->state[8 + c]; |
1085 | s->buf[4 * c + 3] = s->state[12 + c]; |
1086 | } |
1087 | |
1088 | s->bufIdx = 0; |
1089 | } |
1090 | |
1091 | static void aes256DecryptBlock(DecryptAES256State *s, const unsigned char *in, bool last) |
1092 | { |
1093 | int c, round, n, i; |
1094 | |
1095 | // initial state |
1096 | for (c = 0; c < 4; ++c) { |
1097 | s->state[c] = in[4 * c]; |
1098 | s->state[4 + c] = in[4 * c + 1]; |
1099 | s->state[8 + c] = in[4 * c + 2]; |
1100 | s->state[12 + c] = in[4 * c + 3]; |
1101 | } |
1102 | |
1103 | // round 0 |
1104 | addRoundKey(state: s->state, w: &s->w[14 * 4]); |
1105 | |
1106 | // rounds 13-1 |
1107 | for (round = 13; round >= 1; --round) { |
1108 | invSubBytes(state: s->state); |
1109 | invShiftRows(state: s->state); |
1110 | invMixColumns(state: s->state); |
1111 | addRoundKey(state: s->state, w: &s->w[round * 4]); |
1112 | } |
1113 | |
1114 | // round 14 |
1115 | invSubBytes(state: s->state); |
1116 | invShiftRows(state: s->state); |
1117 | addRoundKey(state: s->state, w: &s->w[0]); |
1118 | |
1119 | // CBC |
1120 | for (c = 0; c < 4; ++c) { |
1121 | s->buf[4 * c] = s->state[c] ^ s->cbc[4 * c]; |
1122 | s->buf[4 * c + 1] = s->state[4 + c] ^ s->cbc[4 * c + 1]; |
1123 | s->buf[4 * c + 2] = s->state[8 + c] ^ s->cbc[4 * c + 2]; |
1124 | s->buf[4 * c + 3] = s->state[12 + c] ^ s->cbc[4 * c + 3]; |
1125 | } |
1126 | |
1127 | // save the input block for the next CBC |
1128 | for (i = 0; i < 16; ++i) { |
1129 | s->cbc[i] = in[i]; |
1130 | } |
1131 | |
1132 | // remove padding |
1133 | s->bufIdx = 0; |
1134 | if (last) { |
1135 | n = s->buf[15]; |
1136 | if (n < 1 || n > 16) { // this should never happen |
1137 | n = 16; |
1138 | } |
1139 | for (i = 15; i >= n; --i) { |
1140 | s->buf[i] = s->buf[i - n]; |
1141 | } |
1142 | s->bufIdx = n; |
1143 | if (n > 16) { |
1144 | error(category: errSyntaxError, pos: -1, msg: "Reducing bufIdx from {0:d} to 16 to not crash" , n); |
1145 | s->bufIdx = 16; |
1146 | } |
1147 | } |
1148 | } |
1149 | |
1150 | //------------------------------------------------------------------------ |
1151 | // MD5 message digest |
1152 | //------------------------------------------------------------------------ |
1153 | |
1154 | // this works around a bug in older Sun compilers |
1155 | static inline unsigned long rotateLeft(unsigned long x, int r) |
1156 | { |
1157 | x &= 0xffffffff; |
1158 | return ((x << r) | (x >> (32 - r))) & 0xffffffff; |
1159 | } |
1160 | |
1161 | static inline unsigned long md5Round1(unsigned long a, unsigned long b, unsigned long c, unsigned long d, unsigned long Xk, unsigned long s, unsigned long Ti) |
1162 | { |
1163 | return b + rotateLeft(x: (a + ((b & c) | (~b & d)) + Xk + Ti), r: s); |
1164 | } |
1165 | |
1166 | static inline unsigned long md5Round2(unsigned long a, unsigned long b, unsigned long c, unsigned long d, unsigned long Xk, unsigned long s, unsigned long Ti) |
1167 | { |
1168 | return b + rotateLeft(x: (a + ((b & d) | (c & ~d)) + Xk + Ti), r: s); |
1169 | } |
1170 | |
1171 | static inline unsigned long md5Round3(unsigned long a, unsigned long b, unsigned long c, unsigned long d, unsigned long Xk, unsigned long s, unsigned long Ti) |
1172 | { |
1173 | return b + rotateLeft(x: (a + (b ^ c ^ d) + Xk + Ti), r: s); |
1174 | } |
1175 | |
1176 | static inline unsigned long md5Round4(unsigned long a, unsigned long b, unsigned long c, unsigned long d, unsigned long Xk, unsigned long s, unsigned long Ti) |
1177 | { |
1178 | return b + rotateLeft(x: (a + (c ^ (b | ~d)) + Xk + Ti), r: s); |
1179 | } |
1180 | |
1181 | struct MD5State |
1182 | { |
1183 | unsigned long a, b, c, d; |
1184 | unsigned char buf[64]; |
1185 | int bufLen; |
1186 | int msgLen; |
1187 | unsigned char digest[16]; |
1188 | }; |
1189 | |
1190 | static void md5Start(MD5State *state) |
1191 | { |
1192 | state->a = 0x67452301; |
1193 | state->b = 0xefcdab89; |
1194 | state->c = 0x98badcfe; |
1195 | state->d = 0x10325476; |
1196 | state->bufLen = 0; |
1197 | state->msgLen = 0; |
1198 | } |
1199 | |
1200 | static void md5ProcessBlock(MD5State *state) |
1201 | { |
1202 | unsigned long x[16]; |
1203 | |
1204 | for (int i = 0; i < 16; ++i) { |
1205 | x[i] = state->buf[4 * i] | (state->buf[4 * i + 1] << 8) | (state->buf[4 * i + 2] << 16) | (state->buf[4 * i + 3] << 24); |
1206 | } |
1207 | |
1208 | unsigned long a = state->a; |
1209 | unsigned long b = state->b; |
1210 | unsigned long c = state->c; |
1211 | unsigned long d = state->d; |
1212 | |
1213 | // round 1 |
1214 | a = md5Round1(a, b, c, d, Xk: x[0], s: 7, Ti: 0xd76aa478); |
1215 | d = md5Round1(a: d, b: a, c: b, d: c, Xk: x[1], s: 12, Ti: 0xe8c7b756); |
1216 | c = md5Round1(a: c, b: d, c: a, d: b, Xk: x[2], s: 17, Ti: 0x242070db); |
1217 | b = md5Round1(a: b, b: c, c: d, d: a, Xk: x[3], s: 22, Ti: 0xc1bdceee); |
1218 | a = md5Round1(a, b, c, d, Xk: x[4], s: 7, Ti: 0xf57c0faf); |
1219 | d = md5Round1(a: d, b: a, c: b, d: c, Xk: x[5], s: 12, Ti: 0x4787c62a); |
1220 | c = md5Round1(a: c, b: d, c: a, d: b, Xk: x[6], s: 17, Ti: 0xa8304613); |
1221 | b = md5Round1(a: b, b: c, c: d, d: a, Xk: x[7], s: 22, Ti: 0xfd469501); |
1222 | a = md5Round1(a, b, c, d, Xk: x[8], s: 7, Ti: 0x698098d8); |
1223 | d = md5Round1(a: d, b: a, c: b, d: c, Xk: x[9], s: 12, Ti: 0x8b44f7af); |
1224 | c = md5Round1(a: c, b: d, c: a, d: b, Xk: x[10], s: 17, Ti: 0xffff5bb1); |
1225 | b = md5Round1(a: b, b: c, c: d, d: a, Xk: x[11], s: 22, Ti: 0x895cd7be); |
1226 | a = md5Round1(a, b, c, d, Xk: x[12], s: 7, Ti: 0x6b901122); |
1227 | d = md5Round1(a: d, b: a, c: b, d: c, Xk: x[13], s: 12, Ti: 0xfd987193); |
1228 | c = md5Round1(a: c, b: d, c: a, d: b, Xk: x[14], s: 17, Ti: 0xa679438e); |
1229 | b = md5Round1(a: b, b: c, c: d, d: a, Xk: x[15], s: 22, Ti: 0x49b40821); |
1230 | |
1231 | // round 2 |
1232 | a = md5Round2(a, b, c, d, Xk: x[1], s: 5, Ti: 0xf61e2562); |
1233 | d = md5Round2(a: d, b: a, c: b, d: c, Xk: x[6], s: 9, Ti: 0xc040b340); |
1234 | c = md5Round2(a: c, b: d, c: a, d: b, Xk: x[11], s: 14, Ti: 0x265e5a51); |
1235 | b = md5Round2(a: b, b: c, c: d, d: a, Xk: x[0], s: 20, Ti: 0xe9b6c7aa); |
1236 | a = md5Round2(a, b, c, d, Xk: x[5], s: 5, Ti: 0xd62f105d); |
1237 | d = md5Round2(a: d, b: a, c: b, d: c, Xk: x[10], s: 9, Ti: 0x02441453); |
1238 | c = md5Round2(a: c, b: d, c: a, d: b, Xk: x[15], s: 14, Ti: 0xd8a1e681); |
1239 | b = md5Round2(a: b, b: c, c: d, d: a, Xk: x[4], s: 20, Ti: 0xe7d3fbc8); |
1240 | a = md5Round2(a, b, c, d, Xk: x[9], s: 5, Ti: 0x21e1cde6); |
1241 | d = md5Round2(a: d, b: a, c: b, d: c, Xk: x[14], s: 9, Ti: 0xc33707d6); |
1242 | c = md5Round2(a: c, b: d, c: a, d: b, Xk: x[3], s: 14, Ti: 0xf4d50d87); |
1243 | b = md5Round2(a: b, b: c, c: d, d: a, Xk: x[8], s: 20, Ti: 0x455a14ed); |
1244 | a = md5Round2(a, b, c, d, Xk: x[13], s: 5, Ti: 0xa9e3e905); |
1245 | d = md5Round2(a: d, b: a, c: b, d: c, Xk: x[2], s: 9, Ti: 0xfcefa3f8); |
1246 | c = md5Round2(a: c, b: d, c: a, d: b, Xk: x[7], s: 14, Ti: 0x676f02d9); |
1247 | b = md5Round2(a: b, b: c, c: d, d: a, Xk: x[12], s: 20, Ti: 0x8d2a4c8a); |
1248 | |
1249 | // round 3 |
1250 | a = md5Round3(a, b, c, d, Xk: x[5], s: 4, Ti: 0xfffa3942); |
1251 | d = md5Round3(a: d, b: a, c: b, d: c, Xk: x[8], s: 11, Ti: 0x8771f681); |
1252 | c = md5Round3(a: c, b: d, c: a, d: b, Xk: x[11], s: 16, Ti: 0x6d9d6122); |
1253 | b = md5Round3(a: b, b: c, c: d, d: a, Xk: x[14], s: 23, Ti: 0xfde5380c); |
1254 | a = md5Round3(a, b, c, d, Xk: x[1], s: 4, Ti: 0xa4beea44); |
1255 | d = md5Round3(a: d, b: a, c: b, d: c, Xk: x[4], s: 11, Ti: 0x4bdecfa9); |
1256 | c = md5Round3(a: c, b: d, c: a, d: b, Xk: x[7], s: 16, Ti: 0xf6bb4b60); |
1257 | b = md5Round3(a: b, b: c, c: d, d: a, Xk: x[10], s: 23, Ti: 0xbebfbc70); |
1258 | a = md5Round3(a, b, c, d, Xk: x[13], s: 4, Ti: 0x289b7ec6); |
1259 | d = md5Round3(a: d, b: a, c: b, d: c, Xk: x[0], s: 11, Ti: 0xeaa127fa); |
1260 | c = md5Round3(a: c, b: d, c: a, d: b, Xk: x[3], s: 16, Ti: 0xd4ef3085); |
1261 | b = md5Round3(a: b, b: c, c: d, d: a, Xk: x[6], s: 23, Ti: 0x04881d05); |
1262 | a = md5Round3(a, b, c, d, Xk: x[9], s: 4, Ti: 0xd9d4d039); |
1263 | d = md5Round3(a: d, b: a, c: b, d: c, Xk: x[12], s: 11, Ti: 0xe6db99e5); |
1264 | c = md5Round3(a: c, b: d, c: a, d: b, Xk: x[15], s: 16, Ti: 0x1fa27cf8); |
1265 | b = md5Round3(a: b, b: c, c: d, d: a, Xk: x[2], s: 23, Ti: 0xc4ac5665); |
1266 | |
1267 | // round 4 |
1268 | a = md5Round4(a, b, c, d, Xk: x[0], s: 6, Ti: 0xf4292244); |
1269 | d = md5Round4(a: d, b: a, c: b, d: c, Xk: x[7], s: 10, Ti: 0x432aff97); |
1270 | c = md5Round4(a: c, b: d, c: a, d: b, Xk: x[14], s: 15, Ti: 0xab9423a7); |
1271 | b = md5Round4(a: b, b: c, c: d, d: a, Xk: x[5], s: 21, Ti: 0xfc93a039); |
1272 | a = md5Round4(a, b, c, d, Xk: x[12], s: 6, Ti: 0x655b59c3); |
1273 | d = md5Round4(a: d, b: a, c: b, d: c, Xk: x[3], s: 10, Ti: 0x8f0ccc92); |
1274 | c = md5Round4(a: c, b: d, c: a, d: b, Xk: x[10], s: 15, Ti: 0xffeff47d); |
1275 | b = md5Round4(a: b, b: c, c: d, d: a, Xk: x[1], s: 21, Ti: 0x85845dd1); |
1276 | a = md5Round4(a, b, c, d, Xk: x[8], s: 6, Ti: 0x6fa87e4f); |
1277 | d = md5Round4(a: d, b: a, c: b, d: c, Xk: x[15], s: 10, Ti: 0xfe2ce6e0); |
1278 | c = md5Round4(a: c, b: d, c: a, d: b, Xk: x[6], s: 15, Ti: 0xa3014314); |
1279 | b = md5Round4(a: b, b: c, c: d, d: a, Xk: x[13], s: 21, Ti: 0x4e0811a1); |
1280 | a = md5Round4(a, b, c, d, Xk: x[4], s: 6, Ti: 0xf7537e82); |
1281 | d = md5Round4(a: d, b: a, c: b, d: c, Xk: x[11], s: 10, Ti: 0xbd3af235); |
1282 | c = md5Round4(a: c, b: d, c: a, d: b, Xk: x[2], s: 15, Ti: 0x2ad7d2bb); |
1283 | b = md5Round4(a: b, b: c, c: d, d: a, Xk: x[9], s: 21, Ti: 0xeb86d391); |
1284 | |
1285 | // increment a, b, c, d |
1286 | state->a += a; |
1287 | state->b += b; |
1288 | state->c += c; |
1289 | state->d += d; |
1290 | |
1291 | state->bufLen = 0; |
1292 | } |
1293 | |
1294 | static void md5Append(MD5State *state, const unsigned char *data, int dataLen) |
1295 | { |
1296 | const unsigned char *p = data; |
1297 | int remain = dataLen; |
1298 | while (state->bufLen + remain >= 64) { |
1299 | const int k = 64 - state->bufLen; |
1300 | memcpy(dest: state->buf + state->bufLen, src: p, n: k); |
1301 | state->bufLen = 64; |
1302 | md5ProcessBlock(state); |
1303 | p += k; |
1304 | remain -= k; |
1305 | } |
1306 | if (remain > 0) { |
1307 | memcpy(dest: state->buf + state->bufLen, src: p, n: remain); |
1308 | state->bufLen += remain; |
1309 | } |
1310 | state->msgLen += dataLen; |
1311 | } |
1312 | |
1313 | static void md5Finish(MD5State *state) |
1314 | { |
1315 | // padding and length |
1316 | state->buf[state->bufLen++] = 0x80; |
1317 | if (state->bufLen > 56) { |
1318 | while (state->bufLen < 64) { |
1319 | state->buf[state->bufLen++] = 0x00; |
1320 | } |
1321 | md5ProcessBlock(state); |
1322 | } |
1323 | while (state->bufLen < 56) { |
1324 | state->buf[state->bufLen++] = 0x00; |
1325 | } |
1326 | state->buf[56] = (unsigned char)(state->msgLen << 3); |
1327 | state->buf[57] = (unsigned char)(state->msgLen >> 5); |
1328 | state->buf[58] = (unsigned char)(state->msgLen >> 13); |
1329 | state->buf[59] = (unsigned char)(state->msgLen >> 21); |
1330 | state->buf[60] = (unsigned char)(state->msgLen >> 29); |
1331 | state->buf[61] = (unsigned char)0; |
1332 | state->buf[62] = (unsigned char)0; |
1333 | state->buf[63] = (unsigned char)0; |
1334 | state->bufLen = 64; |
1335 | md5ProcessBlock(state); |
1336 | |
1337 | // break digest into bytes |
1338 | state->digest[0] = (unsigned char)state->a; |
1339 | state->digest[1] = (unsigned char)(state->a >> 8); |
1340 | state->digest[2] = (unsigned char)(state->a >> 16); |
1341 | state->digest[3] = (unsigned char)(state->a >> 24); |
1342 | state->digest[4] = (unsigned char)state->b; |
1343 | state->digest[5] = (unsigned char)(state->b >> 8); |
1344 | state->digest[6] = (unsigned char)(state->b >> 16); |
1345 | state->digest[7] = (unsigned char)(state->b >> 24); |
1346 | state->digest[8] = (unsigned char)state->c; |
1347 | state->digest[9] = (unsigned char)(state->c >> 8); |
1348 | state->digest[10] = (unsigned char)(state->c >> 16); |
1349 | state->digest[11] = (unsigned char)(state->c >> 24); |
1350 | state->digest[12] = (unsigned char)state->d; |
1351 | state->digest[13] = (unsigned char)(state->d >> 8); |
1352 | state->digest[14] = (unsigned char)(state->d >> 16); |
1353 | state->digest[15] = (unsigned char)(state->d >> 24); |
1354 | } |
1355 | |
1356 | void md5(const unsigned char *msg, int msgLen, unsigned char *digest) |
1357 | { |
1358 | if (msgLen < 0) { |
1359 | return; |
1360 | } |
1361 | MD5State state; |
1362 | md5Start(state: &state); |
1363 | md5Append(state: &state, data: msg, dataLen: msgLen); |
1364 | md5Finish(state: &state); |
1365 | for (int i = 0; i < 16; ++i) { |
1366 | digest[i] = state.digest[i]; |
1367 | } |
1368 | } |
1369 | |
1370 | //------------------------------------------------------------------------ |
1371 | // SHA-256 hash |
1372 | //------------------------------------------------------------------------ |
1373 | |
1374 | static const unsigned int sha256K[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, |
1375 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, |
1376 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, |
1377 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; |
1378 | |
1379 | static inline unsigned int rotr(unsigned int x, unsigned int n) |
1380 | { |
1381 | return (x >> n) | (x << (32 - n)); |
1382 | } |
1383 | |
1384 | static inline unsigned int sha256Ch(unsigned int x, unsigned int y, unsigned int z) |
1385 | { |
1386 | return (x & y) ^ (~x & z); |
1387 | } |
1388 | |
1389 | static inline unsigned int sha256Maj(unsigned int x, unsigned int y, unsigned int z) |
1390 | { |
1391 | return (x & y) ^ (x & z) ^ (y & z); |
1392 | } |
1393 | |
1394 | static inline unsigned int sha256Sigma0(unsigned int x) |
1395 | { |
1396 | return rotr(x, n: 2) ^ rotr(x, n: 13) ^ rotr(x, n: 22); |
1397 | } |
1398 | |
1399 | static inline unsigned int sha256Sigma1(unsigned int x) |
1400 | { |
1401 | return rotr(x, n: 6) ^ rotr(x, n: 11) ^ rotr(x, n: 25); |
1402 | } |
1403 | |
1404 | static inline unsigned int sha256sigma0(unsigned int x) |
1405 | { |
1406 | return rotr(x, n: 7) ^ rotr(x, n: 18) ^ (x >> 3); |
1407 | } |
1408 | |
1409 | static inline unsigned int sha256sigma1(unsigned int x) |
1410 | { |
1411 | return rotr(x, n: 17) ^ rotr(x, n: 19) ^ (x >> 10); |
1412 | } |
1413 | |
1414 | static void sha256HashBlock(const unsigned char *blk, unsigned int *H) |
1415 | { |
1416 | unsigned int W[64]; |
1417 | unsigned int a, b, c, d, e, f, g, h; |
1418 | unsigned int T1, T2; |
1419 | unsigned int t; |
1420 | |
1421 | // 1. prepare the message schedule |
1422 | for (t = 0; t < 16; ++t) { |
1423 | W[t] = (blk[t * 4] << 24) | (blk[t * 4 + 1] << 16) | (blk[t * 4 + 2] << 8) | blk[t * 4 + 3]; |
1424 | } |
1425 | for (t = 16; t < 64; ++t) { |
1426 | W[t] = sha256sigma1(x: W[t - 2]) + W[t - 7] + sha256sigma0(x: W[t - 15]) + W[t - 16]; |
1427 | } |
1428 | |
1429 | // 2. initialize the eight working variables |
1430 | a = H[0]; |
1431 | b = H[1]; |
1432 | c = H[2]; |
1433 | d = H[3]; |
1434 | e = H[4]; |
1435 | f = H[5]; |
1436 | g = H[6]; |
1437 | h = H[7]; |
1438 | |
1439 | // 3. |
1440 | for (t = 0; t < 64; ++t) { |
1441 | T1 = h + sha256Sigma1(x: e) + sha256Ch(x: e, y: f, z: g) + sha256K[t] + W[t]; |
1442 | T2 = sha256Sigma0(x: a) + sha256Maj(x: a, y: b, z: c); |
1443 | h = g; |
1444 | g = f; |
1445 | f = e; |
1446 | e = d + T1; |
1447 | d = c; |
1448 | c = b; |
1449 | b = a; |
1450 | a = T1 + T2; |
1451 | } |
1452 | |
1453 | // 4. compute the intermediate hash value |
1454 | H[0] += a; |
1455 | H[1] += b; |
1456 | H[2] += c; |
1457 | H[3] += d; |
1458 | H[4] += e; |
1459 | H[5] += f; |
1460 | H[6] += g; |
1461 | H[7] += h; |
1462 | } |
1463 | |
1464 | static void sha256(unsigned char *msg, int msgLen, unsigned char *hash) |
1465 | { |
1466 | unsigned char blk[64]; |
1467 | unsigned int H[8]; |
1468 | int blkLen, i; |
1469 | |
1470 | H[0] = 0x6a09e667; |
1471 | H[1] = 0xbb67ae85; |
1472 | H[2] = 0x3c6ef372; |
1473 | H[3] = 0xa54ff53a; |
1474 | H[4] = 0x510e527f; |
1475 | H[5] = 0x9b05688c; |
1476 | H[6] = 0x1f83d9ab; |
1477 | H[7] = 0x5be0cd19; |
1478 | |
1479 | blkLen = 0; |
1480 | for (i = 0; i + 64 <= msgLen; i += 64) { |
1481 | sha256HashBlock(blk: msg + i, H); |
1482 | } |
1483 | blkLen = msgLen - i; |
1484 | if (blkLen > 0) { |
1485 | memcpy(dest: blk, src: msg + i, n: blkLen); |
1486 | } |
1487 | |
1488 | // pad the message |
1489 | blk[blkLen++] = 0x80; |
1490 | if (blkLen > 56) { |
1491 | while (blkLen < 64) { |
1492 | blk[blkLen++] = 0; |
1493 | } |
1494 | sha256HashBlock(blk, H); |
1495 | blkLen = 0; |
1496 | } |
1497 | while (blkLen < 56) { |
1498 | blk[blkLen++] = 0; |
1499 | } |
1500 | blk[56] = 0; |
1501 | blk[57] = 0; |
1502 | blk[58] = 0; |
1503 | blk[59] = 0; |
1504 | blk[60] = (unsigned char)(msgLen >> 21); |
1505 | blk[61] = (unsigned char)(msgLen >> 13); |
1506 | blk[62] = (unsigned char)(msgLen >> 5); |
1507 | blk[63] = (unsigned char)(msgLen << 3); |
1508 | sha256HashBlock(blk, H); |
1509 | |
1510 | // copy the output into the buffer (convert words to bytes) |
1511 | for (i = 0; i < 8; ++i) { |
1512 | hash[i * 4] = (unsigned char)(H[i] >> 24); |
1513 | hash[i * 4 + 1] = (unsigned char)(H[i] >> 16); |
1514 | hash[i * 4 + 2] = (unsigned char)(H[i] >> 8); |
1515 | hash[i * 4 + 3] = (unsigned char)H[i]; |
1516 | } |
1517 | } |
1518 | //------------------------------------------------------------------------ |
1519 | // SHA-512 hash (see FIPS 180-4) |
1520 | //------------------------------------------------------------------------ |
1521 | // SHA 384 and SHA 512 use the same sequence of eighty constant 64 bit words. |
1522 | static const uint64_t shaK[80] = { 0x428a2f98d728ae22ull, 0x7137449123ef65cdull, 0xb5c0fbcfec4d3b2full, 0xe9b5dba58189dbbcull, 0x3956c25bf348b538ull, 0x59f111f1b605d019ull, 0x923f82a4af194f9bull, 0xab1c5ed5da6d8118ull, |
1523 | 0xd807aa98a3030242ull, 0x12835b0145706fbeull, 0x243185be4ee4b28cull, 0x550c7dc3d5ffb4e2ull, 0x72be5d74f27b896full, 0x80deb1fe3b1696b1ull, 0x9bdc06a725c71235ull, 0xc19bf174cf692694ull, |
1524 | 0xe49b69c19ef14ad2ull, 0xefbe4786384f25e3ull, 0x0fc19dc68b8cd5b5ull, 0x240ca1cc77ac9c65ull, 0x2de92c6f592b0275ull, 0x4a7484aa6ea6e483ull, 0x5cb0a9dcbd41fbd4ull, 0x76f988da831153b5ull, |
1525 | 0x983e5152ee66dfabull, 0xa831c66d2db43210ull, 0xb00327c898fb213full, 0xbf597fc7beef0ee4ull, 0xc6e00bf33da88fc2ull, 0xd5a79147930aa725ull, 0x06ca6351e003826full, 0x142929670a0e6e70ull, |
1526 | 0x27b70a8546d22ffcull, 0x2e1b21385c26c926ull, 0x4d2c6dfc5ac42aedull, 0x53380d139d95b3dfull, 0x650a73548baf63deull, 0x766a0abb3c77b2a8ull, 0x81c2c92e47edaee6ull, 0x92722c851482353bull, |
1527 | 0xa2bfe8a14cf10364ull, 0xa81a664bbc423001ull, 0xc24b8b70d0f89791ull, 0xc76c51a30654be30ull, 0xd192e819d6ef5218ull, 0xd69906245565a910ull, 0xf40e35855771202aull, 0x106aa07032bbd1b8ull, |
1528 | 0x19a4c116b8d2d0c8ull, 0x1e376c085141ab53ull, 0x2748774cdf8eeb99ull, 0x34b0bcb5e19b48a8ull, 0x391c0cb3c5c95a63ull, 0x4ed8aa4ae3418acbull, 0x5b9cca4f7763e373ull, 0x682e6ff3d6b2b8a3ull, |
1529 | 0x748f82ee5defb2fcull, 0x78a5636f43172f60ull, 0x84c87814a1f0ab72ull, 0x8cc702081a6439ecull, 0x90befffa23631e28ull, 0xa4506cebde82bde9ull, 0xbef9a3f7b2c67915ull, 0xc67178f2e372532bull, |
1530 | 0xca273eceea26619cull, 0xd186b8c721c0c207ull, 0xeada7dd6cde0eb1eull, 0xf57d4f7fee6ed178ull, 0x06f067aa72176fbaull, 0x0a637dc5a2c898a6ull, 0x113f9804bef90daeull, 0x1b710b35131c471bull, |
1531 | 0x28db77f523047d84ull, 0x32caab7b40c72493ull, 0x3c9ebe0a15c9bebcull, 0x431d67c49c100d4cull, 0x4cc5d4becb3e42b6ull, 0x597f299cfc657e2aull, 0x5fcb6fab3ad6faecull, 0x6c44198c4a475817ull }; |
1532 | |
1533 | static inline uint64_t rotr(uint64_t x, uint64_t n) |
1534 | { |
1535 | return (x >> n) | (x << (64 - n)); |
1536 | } |
1537 | static inline uint64_t sha512Ch(uint64_t x, uint64_t y, uint64_t z) |
1538 | { |
1539 | return (x & y) ^ (~x & z); |
1540 | } |
1541 | static inline uint64_t sha512Maj(uint64_t x, uint64_t y, uint64_t z) |
1542 | { |
1543 | return (x & y) ^ (x & z) ^ (y & z); |
1544 | } |
1545 | static inline uint64_t sha512Sigma0(uint64_t x) |
1546 | { |
1547 | return rotr(x, n: 28) ^ rotr(x, n: 34) ^ rotr(x, n: 39); |
1548 | } |
1549 | static inline uint64_t sha512Sigma1(uint64_t x) |
1550 | { |
1551 | return rotr(x, n: 14) ^ rotr(x, n: 18) ^ rotr(x, n: 41); |
1552 | } |
1553 | static inline uint64_t sha512sigma0(uint64_t x) |
1554 | { |
1555 | return rotr(x, n: 1) ^ rotr(x, n: 8) ^ (x >> 7); |
1556 | } |
1557 | static inline uint64_t sha512sigma1(uint64_t x) |
1558 | { |
1559 | return rotr(x, n: 19) ^ rotr(x, n: 61) ^ (x >> 6); |
1560 | } |
1561 | |
1562 | static void sha512HashBlock(const unsigned char *blk, uint64_t *H) |
1563 | { |
1564 | uint64_t W[80]; |
1565 | uint64_t a, b, c, d, e, f, g, h; |
1566 | uint64_t T1, T2; |
1567 | unsigned int t; |
1568 | |
1569 | // 1. prepare the message schedule |
1570 | for (t = 0; t < 16; ++t) { |
1571 | W[t] = (((uint64_t)blk[t * 8] << 56) | ((uint64_t)blk[t * 8 + 1] << 48) | ((uint64_t)blk[t * 8 + 2] << 40) | ((uint64_t)blk[t * 8 + 3] << 32) | ((uint64_t)blk[t * 8 + 4] << 24) | ((uint64_t)blk[t * 8 + 5] << 16) |
1572 | | ((uint64_t)blk[t * 8 + 6] << 8) | ((uint64_t)blk[t * 8 + 7])); |
1573 | } |
1574 | for (t = 16; t < 80; ++t) { |
1575 | W[t] = sha512sigma1(x: W[t - 2]) + W[t - 7] + sha512sigma0(x: W[t - 15]) + W[t - 16]; |
1576 | } |
1577 | |
1578 | // 2. initialize the eight working variables |
1579 | a = H[0]; |
1580 | b = H[1]; |
1581 | c = H[2]; |
1582 | d = H[3]; |
1583 | e = H[4]; |
1584 | f = H[5]; |
1585 | g = H[6]; |
1586 | h = H[7]; |
1587 | |
1588 | // 3. |
1589 | for (t = 0; t < 80; ++t) { |
1590 | T1 = h + sha512Sigma1(x: e) + sha512Ch(x: e, y: f, z: g) + shaK[t] + W[t]; |
1591 | T2 = sha512Sigma0(x: a) + sha512Maj(x: a, y: b, z: c); |
1592 | h = g; |
1593 | g = f; |
1594 | f = e; |
1595 | e = d + T1; |
1596 | d = c; |
1597 | c = b; |
1598 | b = a; |
1599 | a = T1 + T2; |
1600 | } |
1601 | |
1602 | // 4. compute the intermediate hash value |
1603 | H[0] += a; |
1604 | H[1] += b; |
1605 | H[2] += c; |
1606 | H[3] += d; |
1607 | H[4] += e; |
1608 | H[5] += f; |
1609 | H[6] += g; |
1610 | H[7] += h; |
1611 | } |
1612 | |
1613 | static void sha512(unsigned char *msg, int msgLen, unsigned char *hash) |
1614 | { |
1615 | unsigned char blk[128]; |
1616 | uint64_t H[8]; |
1617 | int blkLen = 0, i; |
1618 | // setting the initial hash value. |
1619 | H[0] = 0x6a09e667f3bcc908ull; |
1620 | H[1] = 0xbb67ae8584caa73bull; |
1621 | H[2] = 0x3c6ef372fe94f82bull; |
1622 | H[3] = 0xa54ff53a5f1d36f1ull; |
1623 | H[4] = 0x510e527fade682d1ull; |
1624 | H[5] = 0x9b05688c2b3e6c1full; |
1625 | H[6] = 0x1f83d9abfb41bd6bull; |
1626 | H[7] = 0x5be0cd19137e2179ull; |
1627 | |
1628 | for (i = 0; i + 128 <= msgLen; i += 128) { |
1629 | sha512HashBlock(blk: msg + i, H); |
1630 | } |
1631 | blkLen = msgLen - i; |
1632 | if (blkLen > 0) { |
1633 | memcpy(dest: blk, src: msg + i, n: blkLen); |
1634 | } |
1635 | |
1636 | // pad the message |
1637 | blk[blkLen++] = 0x80; |
1638 | if (blkLen > 112) { |
1639 | while (blkLen < 128) { |
1640 | blk[blkLen++] = 0; |
1641 | } |
1642 | sha512HashBlock(blk, H); |
1643 | blkLen = 0; |
1644 | } |
1645 | while (blkLen < 112) { |
1646 | blk[blkLen++] = 0; |
1647 | } |
1648 | blk[112] = 0; |
1649 | blk[113] = 0; |
1650 | blk[114] = 0; |
1651 | blk[115] = 0; |
1652 | blk[116] = 0; |
1653 | blk[117] = 0; |
1654 | blk[118] = 0; |
1655 | blk[119] = 0; |
1656 | blk[120] = 0; |
1657 | blk[121] = 0; |
1658 | blk[122] = 0; |
1659 | blk[123] = 0; |
1660 | blk[124] = (unsigned char)(msgLen >> 21); |
1661 | blk[125] = (unsigned char)(msgLen >> 13); |
1662 | blk[126] = (unsigned char)(msgLen >> 5); |
1663 | blk[127] = (unsigned char)(msgLen << 3); |
1664 | |
1665 | sha512HashBlock(blk, H); |
1666 | |
1667 | // copy the output into the buffer (convert words to bytes) |
1668 | for (i = 0; i < 8; ++i) { |
1669 | hash[i * 8] = (unsigned char)(H[i] >> 56); |
1670 | hash[i * 8 + 1] = (unsigned char)(H[i] >> 48); |
1671 | hash[i * 8 + 2] = (unsigned char)(H[i] >> 40); |
1672 | hash[i * 8 + 3] = (unsigned char)(H[i] >> 32); |
1673 | hash[i * 8 + 4] = (unsigned char)(H[i] >> 24); |
1674 | hash[i * 8 + 5] = (unsigned char)(H[i] >> 16); |
1675 | hash[i * 8 + 6] = (unsigned char)(H[i] >> 8); |
1676 | hash[i * 8 + 7] = (unsigned char)H[i]; |
1677 | } |
1678 | } |
1679 | |
1680 | //------------------------------------------------------------------------ |
1681 | // SHA-384 (see FIPS 180-4) |
1682 | //------------------------------------------------------------------------ |
1683 | // The algorithm is defined in the exact same manner as SHA 512 with 2 exceptions |
1684 | // 1.Initial hash value is different. |
1685 | // 2.A 384 bit message digest is obtained by truncating the final hash value. |
1686 | static void sha384(unsigned char *msg, int msgLen, unsigned char *hash) |
1687 | { |
1688 | unsigned char blk[128]; |
1689 | uint64_t H[8]; |
1690 | int blkLen, i; |
1691 | // setting initial hash values |
1692 | H[0] = 0xcbbb9d5dc1059ed8ull; |
1693 | H[1] = 0x629a292a367cd507ull; |
1694 | H[2] = 0x9159015a3070dd17ull; |
1695 | H[3] = 0x152fecd8f70e5939ull; |
1696 | H[4] = 0x67332667ffc00b31ull; |
1697 | H[5] = 0x8eb44a8768581511ull; |
1698 | H[6] = 0xdb0c2e0d64f98fa7ull; |
1699 | H[7] = 0x47b5481dbefa4fa4ull; |
1700 | // SHA 384 will use the same sha512HashBlock function. |
1701 | blkLen = 0; |
1702 | for (i = 0; i + 128 <= msgLen; i += 128) { |
1703 | sha512HashBlock(blk: msg + i, H); |
1704 | } |
1705 | blkLen = msgLen - i; |
1706 | if (blkLen > 0) { |
1707 | memcpy(dest: blk, src: msg + i, n: blkLen); |
1708 | } |
1709 | |
1710 | // pad the message |
1711 | blk[blkLen++] = 0x80; |
1712 | if (blkLen > 112) { |
1713 | while (blkLen < 128) { |
1714 | blk[blkLen++] = 0; |
1715 | } |
1716 | sha512HashBlock(blk, H); |
1717 | blkLen = 0; |
1718 | } |
1719 | while (blkLen < 112) { |
1720 | blk[blkLen++] = 0; |
1721 | } |
1722 | blk[112] = 0; |
1723 | blk[113] = 0; |
1724 | blk[114] = 0; |
1725 | blk[115] = 0; |
1726 | blk[116] = 0; |
1727 | blk[117] = 0; |
1728 | blk[118] = 0; |
1729 | blk[119] = 0; |
1730 | blk[120] = 0; |
1731 | blk[121] = 0; |
1732 | blk[122] = 0; |
1733 | blk[123] = 0; |
1734 | blk[124] = (unsigned char)(msgLen >> 21); |
1735 | blk[125] = (unsigned char)(msgLen >> 13); |
1736 | blk[126] = (unsigned char)(msgLen >> 5); |
1737 | blk[127] = (unsigned char)(msgLen << 3); |
1738 | |
1739 | sha512HashBlock(blk, H); |
1740 | |
1741 | // copy the output into the buffer (convert words to bytes) |
1742 | // hash is truncated to 384 bits. |
1743 | for (i = 0; i < 6; ++i) { |
1744 | hash[i * 8] = (unsigned char)(H[i] >> 56); |
1745 | hash[i * 8 + 1] = (unsigned char)(H[i] >> 48); |
1746 | hash[i * 8 + 2] = (unsigned char)(H[i] >> 40); |
1747 | hash[i * 8 + 3] = (unsigned char)(H[i] >> 32); |
1748 | hash[i * 8 + 4] = (unsigned char)(H[i] >> 24); |
1749 | hash[i * 8 + 5] = (unsigned char)(H[i] >> 16); |
1750 | hash[i * 8 + 6] = (unsigned char)(H[i] >> 8); |
1751 | hash[i * 8 + 7] = (unsigned char)H[i]; |
1752 | } |
1753 | } |
1754 | |
1755 | //------------------------------------------------------------------------ |
1756 | // Section 7.6.3.3 (Encryption Key algorithm) of ISO/DIS 32000-2 |
1757 | // Algorithm 2.B:Computing a hash (for revision 6). |
1758 | //------------------------------------------------------------------------ |
1759 | static void revision6Hash(const GooString *inputPassword, unsigned char *K, const char *userKey) |
1760 | { |
1761 | unsigned char K1[64 * (127 + 64 + 48)]; |
1762 | unsigned char E[64 * (127 + 64 + 48)]; |
1763 | DecryptAESState state; |
1764 | unsigned char aesKey[16]; |
1765 | unsigned char BE16byteNumber[16]; |
1766 | |
1767 | int inputPasswordLength = inputPassword->getLength(); |
1768 | int KLength = 32; |
1769 | const int userKeyLength = userKey ? 48 : 0; |
1770 | int sequenceLength; |
1771 | int totalLength; |
1772 | int rounds = 0; |
1773 | |
1774 | while (rounds < 64 || rounds < E[totalLength - 1] + 32) { |
1775 | sequenceLength = inputPasswordLength + KLength + userKeyLength; |
1776 | totalLength = 64 * sequenceLength; |
1777 | // a.make the string K1 |
1778 | memcpy(dest: K1, src: inputPassword->c_str(), n: inputPasswordLength); |
1779 | memcpy(dest: K1 + inputPasswordLength, src: K, n: KLength); |
1780 | if (userKey) { |
1781 | memcpy(dest: K1 + inputPasswordLength + KLength, src: userKey, n: userKeyLength); |
1782 | } |
1783 | for (int i = 1; i < 64; ++i) { |
1784 | memcpy(dest: K1 + (i * sequenceLength), src: K1, n: sequenceLength); |
1785 | } |
1786 | // b.Encrypt K1 |
1787 | memcpy(dest: aesKey, src: K, n: 16); |
1788 | memcpy(dest: state.cbc, src: K + 16, n: 16); |
1789 | memcpy(dest: state.buf, src: state.cbc, n: 16); // Copy CBC IV to buf |
1790 | state.bufIdx = 0; |
1791 | state.paddingReached = false; |
1792 | aesKeyExpansion(s: &state, objKey: aesKey, 16, decrypt: false); |
1793 | |
1794 | for (int i = 0; i < (4 * sequenceLength); i++) { |
1795 | aesEncryptBlock(s: &state, in: K1 + (16 * i)); |
1796 | memcpy(dest: E + (16 * i), src: state.buf, n: 16); |
1797 | } |
1798 | memcpy(dest: BE16byteNumber, src: E, n: 16); |
1799 | // c.Taking the first 16 Bytes of E as unsigned big-endian integer, |
1800 | // compute the remainder,modulo 3. |
1801 | uint64_t N1 = 0, N2 = 0, N3 = 0; |
1802 | // N1 contains first 8 bytes of BE16byteNumber |
1803 | N1 = ((uint64_t)BE16byteNumber[0] << 56 | (uint64_t)BE16byteNumber[1] << 48 | (uint64_t)BE16byteNumber[2] << 40 | (uint64_t)BE16byteNumber[3] << 32 | (uint64_t)BE16byteNumber[4] << 24 | (uint64_t)BE16byteNumber[5] << 16 |
1804 | | (uint64_t)BE16byteNumber[6] << 8 | (uint64_t)BE16byteNumber[7]); |
1805 | uint64_t rem = N1 % 3; |
1806 | // N2 contains 0s in higher 4 bytes and 9th to 12 th bytes of BE16byteNumber in lower 4 bytes. |
1807 | N2 = ((uint64_t)BE16byteNumber[8] << 24 | (uint64_t)BE16byteNumber[9] << 16 | (uint64_t)BE16byteNumber[10] << 8 | (uint64_t)BE16byteNumber[11]); |
1808 | rem = ((rem << 32) | N2) % 3; |
1809 | // N3 contains 0s in higher 4 bytes and 13th to 16th bytes of BE16byteNumber in lower 4 bytes. |
1810 | N3 = ((uint64_t)BE16byteNumber[12] << 24 | (uint64_t)BE16byteNumber[13] << 16 | (uint64_t)BE16byteNumber[14] << 8 | (uint64_t)BE16byteNumber[15]); |
1811 | rem = ((rem << 32) | N3) % 3; |
1812 | |
1813 | // d.If remainder is 0 perform SHA-256 |
1814 | if (rem == 0) { |
1815 | KLength = 32; |
1816 | sha256(msg: E, msgLen: totalLength, hash: K); |
1817 | } |
1818 | // remainder is 1 perform SHA-384 |
1819 | else if (rem == 1) { |
1820 | KLength = 48; |
1821 | sha384(msg: E, msgLen: totalLength, hash: K); |
1822 | } |
1823 | // remainder is 2 perform SHA-512 |
1824 | else if (rem == 2) { |
1825 | KLength = 64; |
1826 | sha512(msg: E, msgLen: totalLength, hash: K); |
1827 | } |
1828 | rounds++; |
1829 | } |
1830 | // the first 32 bytes of the final K are the output of the function. |
1831 | } |
1832 | |