fix build with recent changes/gcc 6.3.0
[AROS-Contrib.git] / arospdf / xpdf / Decrypt.cc
blobe1da54f1c0bc8ffbb9b81db85b8c027d0e4c011c
1 //========================================================================
2 //
3 // Decrypt.cc
4 //
5 // Copyright 1996-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
9 #include <aconf.h>
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
15 #include <string.h>
16 #include "gmem.h"
17 #include "Decrypt.h"
19 static void rc4InitKey(Guchar *key, int keyLen, Guchar *state);
20 static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c);
21 static void aesKeyExpansion(DecryptAESState *s,
22 Guchar *objKey, int objKeyLen);
23 static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last);
24 static void md5(Guchar *msg, int msgLen, Guchar *digest);
26 static Guchar passwordPad[32] = {
27 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,
28 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,
29 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
30 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a
33 //------------------------------------------------------------------------
34 // Decrypt
35 //------------------------------------------------------------------------
37 GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength,
38 GString *ownerKey, GString *userKey,
39 int permissions, GString *fileID,
40 GString *ownerPassword, GString *userPassword,
41 Guchar *fileKey, GBool encryptMetadata,
42 GBool *ownerPasswordOk) {
43 Guchar test[32], test2[32];
44 GString *userPassword2;
45 Guchar fState[256];
46 Guchar tmpKey[16];
47 Guchar fx, fy;
48 int len, i, j;
50 // try using the supplied owner password to generate the user password
51 *ownerPasswordOk = gFalse;
52 if (ownerPassword) {
53 len = ownerPassword->getLength();
54 if (len < 32) {
55 memcpy(test, ownerPassword->getCString(), len);
56 memcpy(test + len, passwordPad, 32 - len);
57 } else {
58 memcpy(test, ownerPassword->getCString(), 32);
60 md5(test, 32, test);
61 if (encRevision == 3) {
62 for (i = 0; i < 50; ++i) {
63 md5(test, 16, test);
66 if (encRevision == 2) {
67 rc4InitKey(test, keyLength, fState);
68 fx = fy = 0;
69 for (i = 0; i < 32; ++i) {
70 test2[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i));
72 } else {
73 memcpy(test2, ownerKey->getCString(), 32);
74 for (i = 19; i >= 0; --i) {
75 for (j = 0; j < keyLength; ++j) {
76 tmpKey[j] = test[j] ^ i;
78 rc4InitKey(tmpKey, keyLength, fState);
79 fx = fy = 0;
80 for (j = 0; j < 32; ++j) {
81 test2[j] = rc4DecryptByte(fState, &fx, &fy, test2[j]);
85 userPassword2 = new GString((char *)test2, 32);
86 if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
87 permissions, fileID, userPassword2, fileKey,
88 encryptMetadata)) {
89 *ownerPasswordOk = gTrue;
90 delete userPassword2;
91 return gTrue;
93 delete userPassword2;
96 // try using the supplied user password
97 return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
98 permissions, fileID, userPassword, fileKey,
99 encryptMetadata);
102 GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength,
103 GString *ownerKey, GString *userKey,
104 int permissions, GString *fileID,
105 GString *userPassword, Guchar *fileKey,
106 GBool encryptMetadata) {
107 Guchar *buf;
108 Guchar test[32];
109 Guchar fState[256];
110 Guchar tmpKey[16];
111 Guchar fx, fy;
112 int len, i, j;
113 GBool ok;
115 // generate file key
116 buf = (Guchar *)gmalloc(72 + fileID->getLength());
117 if (userPassword) {
118 len = userPassword->getLength();
119 if (len < 32) {
120 memcpy(buf, userPassword->getCString(), len);
121 memcpy(buf + len, passwordPad, 32 - len);
122 } else {
123 memcpy(buf, userPassword->getCString(), 32);
125 } else {
126 memcpy(buf, passwordPad, 32);
128 memcpy(buf + 32, ownerKey->getCString(), 32);
129 buf[64] = permissions & 0xff;
130 buf[65] = (permissions >> 8) & 0xff;
131 buf[66] = (permissions >> 16) & 0xff;
132 buf[67] = (permissions >> 24) & 0xff;
133 memcpy(buf + 68, fileID->getCString(), fileID->getLength());
134 len = 68 + fileID->getLength();
135 if (!encryptMetadata) {
136 buf[len++] = 0xff;
137 buf[len++] = 0xff;
138 buf[len++] = 0xff;
139 buf[len++] = 0xff;
141 md5(buf, len, fileKey);
142 if (encRevision == 3) {
143 for (i = 0; i < 50; ++i) {
144 md5(fileKey, keyLength, fileKey);
148 // test user password
149 if (encRevision == 2) {
150 rc4InitKey(fileKey, keyLength, fState);
151 fx = fy = 0;
152 for (i = 0; i < 32; ++i) {
153 test[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i));
155 ok = memcmp(test, passwordPad, 32) == 0;
156 } else if (encRevision == 3) {
157 memcpy(test, userKey->getCString(), 32);
158 for (i = 19; i >= 0; --i) {
159 for (j = 0; j < keyLength; ++j) {
160 tmpKey[j] = fileKey[j] ^ i;
162 rc4InitKey(tmpKey, keyLength, fState);
163 fx = fy = 0;
164 for (j = 0; j < 32; ++j) {
165 test[j] = rc4DecryptByte(fState, &fx, &fy, test[j]);
168 memcpy(buf, passwordPad, 32);
169 memcpy(buf + 32, fileID->getCString(), fileID->getLength());
170 md5(buf, 32 + fileID->getLength(), buf);
171 ok = memcmp(test, buf, 16) == 0;
172 } else {
173 ok = gFalse;
176 gfree(buf);
177 return ok;
180 //------------------------------------------------------------------------
181 // DecryptStream
182 //------------------------------------------------------------------------
184 DecryptStream::DecryptStream(Stream *strA, Guchar *fileKey,
185 CryptAlgorithm algoA, int keyLength,
186 int objNum, int objGen):
187 FilterStream(strA)
189 int n, i;
191 algo = algoA;
193 // construct xObject key
194 for (i = 0; i < keyLength; ++i) {
195 objKey[i] = fileKey[i];
197 objKey[keyLength] = objNum & 0xff;
198 objKey[keyLength + 1] = (objNum >> 8) & 0xff;
199 objKey[keyLength + 2] = (objNum >> 16) & 0xff;
200 objKey[keyLength + 3] = objGen & 0xff;
201 objKey[keyLength + 4] = (objGen >> 8) & 0xff;
202 if (algo == cryptAES) {
203 objKey[keyLength + 5] = 0x73; // 's'
204 objKey[keyLength + 6] = 0x41; // 'A'
205 objKey[keyLength + 7] = 0x6c; // 'l'
206 objKey[keyLength + 8] = 0x54; // 'T'
207 n = keyLength + 9;
208 } else {
209 n = keyLength + 5;
211 md5(objKey, n, objKey);
212 if ((objKeyLength = keyLength + 5) > 16) {
213 objKeyLength = 16;
217 DecryptStream::~DecryptStream() {
218 delete str;
221 void DecryptStream::reset() {
222 int i;
224 str->reset();
225 switch (algo) {
226 case cryptRC4:
227 state.rc4.x = state.rc4.y = 0;
228 rc4InitKey(objKey, objKeyLength, state.rc4.state);
229 state.rc4.buf = EOF;
230 break;
231 case cryptAES:
232 aesKeyExpansion(&state.aes, objKey, objKeyLength);
233 for (i = 0; i < 16; ++i) {
234 state.aes.cbc[i] = str->getChar();
236 state.aes.bufIdx = 16;
237 break;
241 int DecryptStream::getChar() {
242 Guchar in[16];
243 int c, i;
245 c = EOF; // make gcc happy
246 switch (algo) {
247 case cryptRC4:
248 if (state.rc4.buf == EOF) {
249 c = str->getChar();
250 if (c != EOF) {
251 state.rc4.buf = rc4DecryptByte(state.rc4.state, &state.rc4.x,
252 &state.rc4.y, (Guchar)c);
255 c = state.rc4.buf;
256 state.rc4.buf = EOF;
257 break;
258 case cryptAES:
259 if (state.aes.bufIdx == 16) {
260 for (i = 0; i < 16; ++i) {
261 if ((c = str->getChar()) == EOF) {
262 return EOF;
264 in[i] = (Guchar)c;
266 aesDecryptBlock(&state.aes, in, str->lookChar() == EOF);
268 if (state.aes.bufIdx == 16) {
269 c = EOF;
270 } else {
271 c = state.aes.buf[state.aes.bufIdx++];
273 break;
275 return c;
278 int DecryptStream::lookChar() {
279 Guchar in[16];
280 int c, i;
282 c = EOF; // make gcc happy
283 switch (algo) {
284 case cryptRC4:
285 if (state.rc4.buf == EOF) {
286 c = str->getChar();
287 if (c != EOF) {
288 state.rc4.buf = rc4DecryptByte(state.rc4.state, &state.rc4.x,
289 &state.rc4.y, (Guchar)c);
292 c = state.rc4.buf;
293 break;
294 case cryptAES:
295 if (state.aes.bufIdx == 16) {
296 for (i = 0; i < 16; ++i) {
297 if ((c = str->getChar()) == EOF) {
298 return EOF;
300 in[i] = c;
302 aesDecryptBlock(&state.aes, in, str->lookChar() == EOF);
304 if (state.aes.bufIdx == 16) {
305 c = EOF;
306 } else {
307 c = state.aes.buf[state.aes.bufIdx];
309 break;
311 return c;
314 GBool DecryptStream::isBinary(GBool last) {
315 return str->isBinary(last);
318 //------------------------------------------------------------------------
319 // RC4-compatible decryption
320 //------------------------------------------------------------------------
322 static void rc4InitKey(Guchar *key, int keyLen, Guchar *state) {
323 Guchar index1, index2;
324 Guchar t;
325 int i;
327 for (i = 0; i < 256; ++i)
328 state[i] = i;
329 index1 = index2 = 0;
330 for (i = 0; i < 256; ++i) {
331 index2 = (key[index1] + state[i] + index2) % 256;
332 t = state[i];
333 state[i] = state[index2];
334 state[index2] = t;
335 index1 = (index1 + 1) % keyLen;
339 static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) {
340 Guchar x1, y1, tx, ty;
342 x1 = *x = (*x + 1) % 256;
343 y1 = *y = (state[*x] + *y) % 256;
344 tx = state[x1];
345 ty = state[y1];
346 state[x1] = ty;
347 state[y1] = tx;
348 return c ^ state[(tx + ty) % 256];
351 //------------------------------------------------------------------------
352 // AES decryption
353 //------------------------------------------------------------------------
355 static Guchar sbox[256] = {
356 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
357 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
358 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
359 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
360 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
361 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
362 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
363 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
364 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
365 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
366 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
367 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
368 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
369 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
370 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
371 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
374 static Guchar invSbox[256] = {
375 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
376 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
377 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
378 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
379 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
380 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
381 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
382 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
383 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
384 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
385 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
386 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
387 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
388 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
389 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
390 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
393 static Guint rcon[11] = {
394 0x00000000, // unused
395 0x01000000,
396 0x02000000,
397 0x04000000,
398 0x08000000,
399 0x10000000,
400 0x20000000,
401 0x40000000,
402 0x80000000,
403 0x1b000000,
404 0x36000000
407 static inline Guint subWord(Guint x) {
408 return (sbox[x >> 24] << 24)
409 | (sbox[(x >> 16) & 0xff] << 16)
410 | (sbox[(x >> 8) & 0xff] << 8)
411 | sbox[x & 0xff];
414 static inline Guint rotWord(Guint x) {
415 return ((x << 8) & 0xffffffff) | (x >> 24);
418 static inline void invSubBytes(Guchar *state) {
419 int i;
421 for (i = 0; i < 16; ++i) {
422 state[i] = invSbox[state[i]];
426 static inline void invShiftRows(Guchar *state) {
427 Guchar t;
429 t = state[7];
430 state[7] = state[6];
431 state[6] = state[5];
432 state[5] = state[4];
433 state[4] = t;
435 t = state[8];
436 state[8] = state[10];
437 state[10] = t;
438 t = state[9];
439 state[9] = state[11];
440 state[11] = t;
442 t = state[12];
443 state[12] = state[13];
444 state[13] = state[14];
445 state[14] = state[15];
446 state[15] = t;
449 // {09} \cdot s
450 static inline Guchar mul09(Guchar s) {
451 Guchar s2, s4, s8;
453 s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1);
454 s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1);
455 s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1);
456 return s ^ s8;
459 // {0b} \cdot s
460 static inline Guchar mul0b(Guchar s) {
461 Guchar s2, s4, s8;
463 s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1);
464 s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1);
465 s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1);
466 return s ^ s2 ^ s8;
469 // {0d} \cdot s
470 static inline Guchar mul0d(Guchar s) {
471 Guchar s2, s4, s8;
473 s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1);
474 s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1);
475 s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1);
476 return s ^ s4 ^ s8;
479 // {0e} \cdot s
480 static inline Guchar mul0e(Guchar s) {
481 Guchar s2, s4, s8;
483 s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1);
484 s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1);
485 s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1);
486 return s2 ^ s4 ^ s8;
489 static inline void invMixColumns(Guchar *state) {
490 int c;
491 Guchar s0, s1, s2, s3;
493 for (c = 0; c < 4; ++c) {
494 s0 = state[c];
495 s1 = state[4+c];
496 s2 = state[8+c];
497 s3 = state[12+c];
498 state[c] = mul0e(s0) ^ mul0b(s1) ^ mul0d(s2) ^ mul09(s3);
499 state[4+c] = mul09(s0) ^ mul0e(s1) ^ mul0b(s2) ^ mul0d(s3);
500 state[8+c] = mul0d(s0) ^ mul09(s1) ^ mul0e(s2) ^ mul0b(s3);
501 state[12+c] = mul0b(s0) ^ mul0d(s1) ^ mul09(s2) ^ mul0e(s3);
505 static inline void invMixColumnsW(Guint *w) {
506 int c;
507 Guchar s0, s1, s2, s3;
509 for (c = 0; c < 4; ++c) {
510 s0 = w[c] >> 24;
511 s1 = w[c] >> 16;
512 s2 = w[c] >> 8;
513 s3 = w[c];
514 w[c] = ((mul0e(s0) ^ mul0b(s1) ^ mul0d(s2) ^ mul09(s3)) << 24)
515 | ((mul09(s0) ^ mul0e(s1) ^ mul0b(s2) ^ mul0d(s3)) << 16)
516 | ((mul0d(s0) ^ mul09(s1) ^ mul0e(s2) ^ mul0b(s3)) << 8)
517 | (mul0b(s0) ^ mul0d(s1) ^ mul09(s2) ^ mul0e(s3));
521 static inline void addRoundKey(Guchar *state, Guint *w) {
522 int c;
524 for (c = 0; c < 4; ++c) {
525 state[c] ^= w[c] >> 24;
526 state[4+c] ^= w[c] >> 16;
527 state[8+c] ^= w[c] >> 8;
528 state[12+c] ^= w[c];
532 static void aesKeyExpansion(DecryptAESState *s,
533 Guchar *objKey, int objKeyLen) {
534 Guint temp;
535 int i, round;
537 //~ this assumes objKeyLen == 16
539 for (i = 0; i < 4; ++i) {
540 s->w[i] = (objKey[4*i] << 24) + (objKey[4*i+1] << 16) +
541 (objKey[4*i+2] << 8) + objKey[4*i+3];
543 for (i = 4; i < 44; ++i) {
544 temp = s->w[i-1];
545 if (!(i & 3)) {
546 temp = subWord(rotWord(temp)) ^ rcon[i/4];
548 s->w[i] = s->w[i-4] ^ temp;
550 for (round = 1; round <= 9; ++round) {
551 invMixColumnsW(&s->w[round * 4]);
555 static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last) {
556 int c, round, n, i;
558 // initial state
559 for (c = 0; c < 4; ++c) {
560 s->state[c] = in[4*c];
561 s->state[4+c] = in[4*c+1];
562 s->state[8+c] = in[4*c+2];
563 s->state[12+c] = in[4*c+3];
566 // round 0
567 addRoundKey(s->state, &s->w[10 * 4]);
569 // rounds 1-9
570 for (round = 9; round >= 1; --round) {
571 invSubBytes(s->state);
572 invShiftRows(s->state);
573 invMixColumns(s->state);
574 addRoundKey(s->state, &s->w[round * 4]);
577 // round 10
578 invSubBytes(s->state);
579 invShiftRows(s->state);
580 addRoundKey(s->state, &s->w[0]);
582 // CBC
583 for (c = 0; c < 4; ++c) {
584 s->buf[4*c] = s->state[c] ^ s->cbc[4*c];
585 s->buf[4*c+1] = s->state[4+c] ^ s->cbc[4*c+1];
586 s->buf[4*c+2] = s->state[8+c] ^ s->cbc[4*c+2];
587 s->buf[4*c+3] = s->state[12+c] ^ s->cbc[4*c+3];
590 // save the input block for the next CBC
591 for (i = 0; i < 16; ++i) {
592 s->cbc[i] = in[i];
595 // remove padding
596 s->bufIdx = 0;
597 if (last) {
598 n = s->buf[15];
599 for (i = 15; i >= n; --i) {
600 s->buf[i] = s->buf[i-n];
602 s->bufIdx = n;
606 //------------------------------------------------------------------------
607 // MD5 message digest
608 //------------------------------------------------------------------------
610 // this works around a bug in older Sun compilers
611 static inline Gulong rotateLeft(Gulong x, int r) {
612 x &= 0xffffffff;
613 return ((x << r) | (x >> (32 - r))) & 0xffffffff;
616 static inline Gulong md5Round1(Gulong a, Gulong b, Gulong c, Gulong d,
617 Gulong Xk, Gulong s, Gulong Ti) {
618 return b + rotateLeft((a + ((b & c) | (~b & d)) + Xk + Ti), s);
621 static inline Gulong md5Round2(Gulong a, Gulong b, Gulong c, Gulong d,
622 Gulong Xk, Gulong s, Gulong Ti) {
623 return b + rotateLeft((a + ((b & d) | (c & ~d)) + Xk + Ti), s);
626 static inline Gulong md5Round3(Gulong a, Gulong b, Gulong c, Gulong d,
627 Gulong Xk, Gulong s, Gulong Ti) {
628 return b + rotateLeft((a + (b ^ c ^ d) + Xk + Ti), s);
631 static inline Gulong md5Round4(Gulong a, Gulong b, Gulong c, Gulong d,
632 Gulong Xk, Gulong s, Gulong Ti) {
633 return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s);
636 static void md5(Guchar *msg, int msgLen, Guchar *digest) {
637 Gulong x[16];
638 Gulong a, b, c, d, aa, bb, cc, dd;
639 int n64;
640 int i, j, k;
642 // compute number of 64-byte blocks
643 // (length + pad byte (0x80) + 8 bytes for length)
644 n64 = (msgLen + 1 + 8 + 63) / 64;
646 // initialize a, b, c, d
647 a = 0x67452301;
648 b = 0xefcdab89;
649 c = 0x98badcfe;
650 d = 0x10325476;
652 // loop through blocks
653 k = 0;
654 for (i = 0; i < n64; ++i) {
656 // grab a 64-byte block
657 for (j = 0; j < 16 && k < msgLen - 3; ++j, k += 4)
658 x[j] = (((((msg[k+3] << 8) + msg[k+2]) << 8) + msg[k+1]) << 8) + msg[k];
659 if (i == n64 - 1) {
660 if (k == msgLen - 3)
661 x[j] = 0x80000000 + (((msg[k+2] << 8) + msg[k+1]) << 8) + msg[k];
662 else if (k == msgLen - 2)
663 x[j] = 0x800000 + (msg[k+1] << 8) + msg[k];
664 else if (k == msgLen - 1)
665 x[j] = 0x8000 + msg[k];
666 else
667 x[j] = 0x80;
668 ++j;
669 while (j < 16)
670 x[j++] = 0;
671 x[14] = msgLen << 3;
674 // save a, b, c, d
675 aa = a;
676 bb = b;
677 cc = c;
678 dd = d;
680 // round 1
681 a = md5Round1(a, b, c, d, x[0], 7, 0xd76aa478);
682 d = md5Round1(d, a, b, c, x[1], 12, 0xe8c7b756);
683 c = md5Round1(c, d, a, b, x[2], 17, 0x242070db);
684 b = md5Round1(b, c, d, a, x[3], 22, 0xc1bdceee);
685 a = md5Round1(a, b, c, d, x[4], 7, 0xf57c0faf);
686 d = md5Round1(d, a, b, c, x[5], 12, 0x4787c62a);
687 c = md5Round1(c, d, a, b, x[6], 17, 0xa8304613);
688 b = md5Round1(b, c, d, a, x[7], 22, 0xfd469501);
689 a = md5Round1(a, b, c, d, x[8], 7, 0x698098d8);
690 d = md5Round1(d, a, b, c, x[9], 12, 0x8b44f7af);
691 c = md5Round1(c, d, a, b, x[10], 17, 0xffff5bb1);
692 b = md5Round1(b, c, d, a, x[11], 22, 0x895cd7be);
693 a = md5Round1(a, b, c, d, x[12], 7, 0x6b901122);
694 d = md5Round1(d, a, b, c, x[13], 12, 0xfd987193);
695 c = md5Round1(c, d, a, b, x[14], 17, 0xa679438e);
696 b = md5Round1(b, c, d, a, x[15], 22, 0x49b40821);
698 // round 2
699 a = md5Round2(a, b, c, d, x[1], 5, 0xf61e2562);
700 d = md5Round2(d, a, b, c, x[6], 9, 0xc040b340);
701 c = md5Round2(c, d, a, b, x[11], 14, 0x265e5a51);
702 b = md5Round2(b, c, d, a, x[0], 20, 0xe9b6c7aa);
703 a = md5Round2(a, b, c, d, x[5], 5, 0xd62f105d);
704 d = md5Round2(d, a, b, c, x[10], 9, 0x02441453);
705 c = md5Round2(c, d, a, b, x[15], 14, 0xd8a1e681);
706 b = md5Round2(b, c, d, a, x[4], 20, 0xe7d3fbc8);
707 a = md5Round2(a, b, c, d, x[9], 5, 0x21e1cde6);
708 d = md5Round2(d, a, b, c, x[14], 9, 0xc33707d6);
709 c = md5Round2(c, d, a, b, x[3], 14, 0xf4d50d87);
710 b = md5Round2(b, c, d, a, x[8], 20, 0x455a14ed);
711 a = md5Round2(a, b, c, d, x[13], 5, 0xa9e3e905);
712 d = md5Round2(d, a, b, c, x[2], 9, 0xfcefa3f8);
713 c = md5Round2(c, d, a, b, x[7], 14, 0x676f02d9);
714 b = md5Round2(b, c, d, a, x[12], 20, 0x8d2a4c8a);
716 // round 3
717 a = md5Round3(a, b, c, d, x[5], 4, 0xfffa3942);
718 d = md5Round3(d, a, b, c, x[8], 11, 0x8771f681);
719 c = md5Round3(c, d, a, b, x[11], 16, 0x6d9d6122);
720 b = md5Round3(b, c, d, a, x[14], 23, 0xfde5380c);
721 a = md5Round3(a, b, c, d, x[1], 4, 0xa4beea44);
722 d = md5Round3(d, a, b, c, x[4], 11, 0x4bdecfa9);
723 c = md5Round3(c, d, a, b, x[7], 16, 0xf6bb4b60);
724 b = md5Round3(b, c, d, a, x[10], 23, 0xbebfbc70);
725 a = md5Round3(a, b, c, d, x[13], 4, 0x289b7ec6);
726 d = md5Round3(d, a, b, c, x[0], 11, 0xeaa127fa);
727 c = md5Round3(c, d, a, b, x[3], 16, 0xd4ef3085);
728 b = md5Round3(b, c, d, a, x[6], 23, 0x04881d05);
729 a = md5Round3(a, b, c, d, x[9], 4, 0xd9d4d039);
730 d = md5Round3(d, a, b, c, x[12], 11, 0xe6db99e5);
731 c = md5Round3(c, d, a, b, x[15], 16, 0x1fa27cf8);
732 b = md5Round3(b, c, d, a, x[2], 23, 0xc4ac5665);
734 // round 4
735 a = md5Round4(a, b, c, d, x[0], 6, 0xf4292244);
736 d = md5Round4(d, a, b, c, x[7], 10, 0x432aff97);
737 c = md5Round4(c, d, a, b, x[14], 15, 0xab9423a7);
738 b = md5Round4(b, c, d, a, x[5], 21, 0xfc93a039);
739 a = md5Round4(a, b, c, d, x[12], 6, 0x655b59c3);
740 d = md5Round4(d, a, b, c, x[3], 10, 0x8f0ccc92);
741 c = md5Round4(c, d, a, b, x[10], 15, 0xffeff47d);
742 b = md5Round4(b, c, d, a, x[1], 21, 0x85845dd1);
743 a = md5Round4(a, b, c, d, x[8], 6, 0x6fa87e4f);
744 d = md5Round4(d, a, b, c, x[15], 10, 0xfe2ce6e0);
745 c = md5Round4(c, d, a, b, x[6], 15, 0xa3014314);
746 b = md5Round4(b, c, d, a, x[13], 21, 0x4e0811a1);
747 a = md5Round4(a, b, c, d, x[4], 6, 0xf7537e82);
748 d = md5Round4(d, a, b, c, x[11], 10, 0xbd3af235);
749 c = md5Round4(c, d, a, b, x[2], 15, 0x2ad7d2bb);
750 b = md5Round4(b, c, d, a, x[9], 21, 0xeb86d391);
752 // increment a, b, c, d
753 a += aa;
754 b += bb;
755 c += cc;
756 d += dd;
759 // break digest into bytes
760 digest[0] = (Guchar)(a & 0xff);
761 digest[1] = (Guchar)((a >>= 8) & 0xff);
762 digest[2] = (Guchar)((a >>= 8) & 0xff);
763 digest[3] = (Guchar)((a >>= 8) & 0xff);
764 digest[4] = (Guchar)(b & 0xff);
765 digest[5] = (Guchar)((b >>= 8) & 0xff);
766 digest[6] = (Guchar)((b >>= 8) & 0xff);
767 digest[7] = (Guchar)((b >>= 8) & 0xff);
768 digest[8] = (Guchar)(c & 0xff);
769 digest[9] = (Guchar)((c >>= 8) & 0xff);
770 digest[10] = (Guchar)((c >>= 8) & 0xff);
771 digest[11] = (Guchar)((c >>= 8) & 0xff);
772 digest[12] = (Guchar)(d & 0xff);
773 digest[13] = (Guchar)((d >>= 8) & 0xff);
774 digest[14] = (Guchar)((d >>= 8) & 0xff);
775 digest[15] = (Guchar)((d >>= 8) & 0xff);