source: trunk/poppler/mypoppler/poppler/Decrypt.cc @ 461

Last change on this file since 461 was 277, checked in by rbri, 12 years ago

PDF plugin: Poppler library updated to version 0.12.3

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