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

Last change on this file since 250 was 250, checked in by Eugene Romanenko, 13 years ago

PDF plugin: poppler library updated to version 0.8.3

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