]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/Decrypt.cc
Import of Xpdf 2.00 for merge
[evince.git] / pdf / xpdf / Decrypt.cc
1 //========================================================================
2 //
3 // Decrypt.cc
4 //
5 // Copyright 1996-2002 Glyph & Cog, LLC
6 //
7 //========================================================================
8
9 #include <aconf.h>
10
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
14
15 #include "gmem.h"
16 #include "Decrypt.h"
17
18 static void rc4InitKey(Guchar *key, int keyLen, Guchar *state);
19 static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c);
20 static void md5(Guchar *msg, int msgLen, Guchar *digest);
21
22 static Guchar passwordPad[32] = {
23   0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,
24   0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, 
25   0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 
26   0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a
27 };
28
29 //------------------------------------------------------------------------
30 // Decrypt
31 //------------------------------------------------------------------------
32
33 Decrypt::Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen) {
34   int i;
35
36   // construct object key
37   for (i = 0; i < keyLength; ++i) {
38     objKey[i] = fileKey[i];
39   }
40   objKey[keyLength] = objNum & 0xff;
41   objKey[keyLength + 1] = (objNum >> 8) & 0xff;
42   objKey[keyLength + 2] = (objNum >> 16) & 0xff;
43   objKey[keyLength + 3] = objGen & 0xff;
44   objKey[keyLength + 4] = (objGen >> 8) & 0xff;
45   md5(objKey, keyLength + 5, objKey);
46
47   // set up for decryption
48   x = y = 0;
49   if ((objKeyLength = keyLength + 5) > 16) {
50     objKeyLength = 16;
51   }
52   rc4InitKey(objKey, objKeyLength, state);
53 }
54
55 void Decrypt::reset() {
56   x = y = 0;
57   rc4InitKey(objKey, objKeyLength, state);
58 }
59
60 Guchar Decrypt::decryptByte(Guchar c) {
61   return rc4DecryptByte(state, &x, &y, c);
62 }
63
64 GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength,
65                            GString *ownerKey, GString *userKey,
66                            int permissions, GString *fileID,
67                            GString *ownerPassword, GString *userPassword,
68                            Guchar *fileKey, GBool *ownerPasswordOk) {
69   Guchar test[32], test2[32];
70   GString *userPassword2;
71   Guchar fState[256];
72   Guchar tmpKey[16];
73   Guchar fx, fy;
74   int len, i, j;
75
76   // try using the supplied owner password to generate the user password
77   if (ownerPassword) {
78     len = ownerPassword->getLength();
79     if (len < 32) {
80       memcpy(test, ownerPassword->getCString(), len);
81       memcpy(test + len, passwordPad, 32 - len);
82     } else {
83       memcpy(test, ownerPassword->getCString(), 32);
84     }
85   } else {
86     memcpy(test, passwordPad, 32);
87   }
88   md5(test, 32, test);
89   if (encRevision == 3) {
90     for (i = 0; i < 50; ++i) {
91       md5(test, 16, test);
92     }
93   }
94   if (encRevision == 2) {
95     rc4InitKey(test, keyLength, fState);
96     fx = fy = 0;
97     for (i = 0; i < 32; ++i) {
98       test2[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i));
99     }
100   } else {
101     memcpy(test2, ownerKey->getCString(), 32);
102     for (i = 19; i >= 0; --i) {
103       for (j = 0; j < keyLength; ++j) {
104         tmpKey[j] = test[j] ^ i;
105       }
106       rc4InitKey(tmpKey, keyLength, fState);
107       fx = fy = 0;
108       for (j = 0; j < 32; ++j) {
109         test2[j] = rc4DecryptByte(fState, &fx, &fy, test2[j]);
110       }
111     }
112   }
113   userPassword2 = new GString((char *)test2, 32);
114   if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
115                    permissions, fileID, userPassword2, fileKey)) {
116     *ownerPasswordOk = gTrue;
117     delete userPassword2;
118     return gTrue;
119   }
120   *ownerPasswordOk = gFalse;
121   delete userPassword2;
122
123   // try using the supplied user password
124   return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
125                       permissions, fileID, userPassword, fileKey);
126 }
127
128 GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength,
129                             GString *ownerKey, GString *userKey,
130                             int permissions, GString *fileID,
131                             GString *userPassword, Guchar *fileKey) {
132   Guchar *buf;
133   Guchar test[32];
134   Guchar fState[256];
135   Guchar tmpKey[16];
136   Guchar fx, fy;
137   int len, i, j;
138   GBool ok;
139
140   // generate file key
141   buf = (Guchar *)gmalloc(68 + fileID->getLength());
142   if (userPassword) {
143     len = userPassword->getLength();
144     if (len < 32) {
145       memcpy(buf, userPassword->getCString(), len);
146       memcpy(buf + len, passwordPad, 32 - len);
147     } else {
148       memcpy(buf, userPassword->getCString(), 32);
149     }
150   } else {
151     memcpy(buf, passwordPad, 32);
152   }
153   memcpy(buf + 32, ownerKey->getCString(), 32);
154   buf[64] = permissions & 0xff;
155   buf[65] = (permissions >> 8) & 0xff;
156   buf[66] = (permissions >> 16) & 0xff;
157   buf[67] = (permissions >> 24) & 0xff;
158   memcpy(buf + 68, fileID->getCString(), fileID->getLength());
159   md5(buf, 68 + fileID->getLength(), fileKey);
160   if (encRevision == 3) {
161     for (i = 0; i < 50; ++i) {
162       md5(fileKey, keyLength, fileKey);
163     }
164   }
165
166   // test user password
167   if (encRevision == 2) {
168     rc4InitKey(fileKey, keyLength, fState);
169     fx = fy = 0;
170     for (i = 0; i < 32; ++i) {
171       test[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i));
172     }
173     ok = memcmp(test, passwordPad, 32) == 0;
174   } else if (encRevision == 3) {
175     memcpy(test, userKey->getCString(), 32);
176     for (i = 19; i >= 0; --i) {
177       for (j = 0; j < keyLength; ++j) {
178         tmpKey[j] = fileKey[j] ^ i;
179       }
180       rc4InitKey(tmpKey, keyLength, fState);
181       fx = fy = 0;
182       for (j = 0; j < 32; ++j) {
183         test[j] = rc4DecryptByte(fState, &fx, &fy, test[j]);
184       }
185     }
186     memcpy(buf, passwordPad, 32);
187     memcpy(buf + 32, fileID->getCString(), fileID->getLength());
188     md5(buf, 32 + fileID->getLength(), buf);
189     ok = memcmp(test, buf, 16) == 0;
190   } else {
191     ok = gFalse;
192   }
193
194   gfree(buf);
195   return ok;
196 }
197
198 //------------------------------------------------------------------------
199 // RC4-compatible decryption
200 //------------------------------------------------------------------------
201
202 static void rc4InitKey(Guchar *key, int keyLen, Guchar *state) {
203   Guchar index1, index2;
204   Guchar t;
205   int i;
206
207   for (i = 0; i < 256; ++i)
208     state[i] = i;
209   index1 = index2 = 0;
210   for (i = 0; i < 256; ++i) {
211     index2 = (key[index1] + state[i] + index2) % 256;
212     t = state[i];
213     state[i] = state[index2];
214     state[index2] = t;
215     index1 = (index1 + 1) % keyLen;
216   }
217 }
218
219 static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) {
220   Guchar x1, y1, tx, ty;
221
222   x1 = *x = (*x + 1) % 256;
223   y1 = *y = (state[*x] + *y) % 256;
224   tx = state[x1];
225   ty = state[y1];
226   state[x1] = ty;
227   state[y1] = tx;
228   return c ^ state[(tx + ty) % 256];
229 }
230
231 //------------------------------------------------------------------------
232 // MD5 message digest
233 //------------------------------------------------------------------------
234
235 // this works around a bug in older Sun compilers
236 static inline Gulong rotateLeft(Gulong x, int r) {
237   x &= 0xffffffff;
238   return ((x << r) | (x >> (32 - r))) & 0xffffffff;
239 }
240
241 static inline Gulong md5Round1(Gulong a, Gulong b, Gulong c, Gulong d,
242                                Gulong Xk,  Gulong s, Gulong Ti) {
243   return b + rotateLeft((a + ((b & c) | (~b & d)) + Xk + Ti), s);
244 }
245
246 static inline Gulong md5Round2(Gulong a, Gulong b, Gulong c, Gulong d,
247                                Gulong Xk,  Gulong s, Gulong Ti) {
248   return b + rotateLeft((a + ((b & d) | (c & ~d)) + Xk + Ti), s);
249 }
250
251 static inline Gulong md5Round3(Gulong a, Gulong b, Gulong c, Gulong d,
252                                Gulong Xk,  Gulong s, Gulong Ti) {
253   return b + rotateLeft((a + (b ^ c ^ d) + Xk + Ti), s);
254 }
255
256 static inline Gulong md5Round4(Gulong a, Gulong b, Gulong c, Gulong d,
257                                Gulong Xk,  Gulong s, Gulong Ti) {
258   return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s);
259 }
260
261 static void md5(Guchar *msg, int msgLen, Guchar *digest) {
262   Gulong x[16];
263   Gulong a, b, c, d, aa, bb, cc, dd;
264   int n64;
265   int i, j, k;
266
267   // compute number of 64-byte blocks
268   // (length + pad byte (0x80) + 8 bytes for length)
269   n64 = (msgLen + 1 + 8 + 63) / 64;
270
271   // initialize a, b, c, d
272   a = 0x67452301;
273   b = 0xefcdab89;
274   c = 0x98badcfe;
275   d = 0x10325476;
276
277   // loop through blocks
278   k = 0;
279   for (i = 0; i < n64; ++i) {
280
281     // grab a 64-byte block
282     for (j = 0; j < 16 && k < msgLen - 3; ++j, k += 4)
283       x[j] = (((((msg[k+3] << 8) + msg[k+2]) << 8) + msg[k+1]) << 8) + msg[k];
284     if (i == n64 - 1) {
285       if (k == msgLen - 3)
286         x[j] = 0x80000000 + (((msg[k+2] << 8) + msg[k+1]) << 8) + msg[k];
287       else if (k == msgLen - 2)
288         x[j] = 0x800000 + (msg[k+1] << 8) + msg[k];
289       else if (k == msgLen - 1)
290         x[j] = 0x8000 + msg[k];
291       else
292         x[j] = 0x80;
293       ++j;
294       while (j < 16)
295         x[j++] = 0;
296       x[14] = msgLen << 3;
297     }
298
299     // save a, b, c, d
300     aa = a;
301     bb = b;
302     cc = c;
303     dd = d;
304
305     // round 1
306     a = md5Round1(a, b, c, d, x[0],   7, 0xd76aa478);
307     d = md5Round1(d, a, b, c, x[1],  12, 0xe8c7b756);
308     c = md5Round1(c, d, a, b, x[2],  17, 0x242070db);
309     b = md5Round1(b, c, d, a, x[3],  22, 0xc1bdceee);
310     a = md5Round1(a, b, c, d, x[4],   7, 0xf57c0faf);
311     d = md5Round1(d, a, b, c, x[5],  12, 0x4787c62a);
312     c = md5Round1(c, d, a, b, x[6],  17, 0xa8304613);
313     b = md5Round1(b, c, d, a, x[7],  22, 0xfd469501);
314     a = md5Round1(a, b, c, d, x[8],   7, 0x698098d8);
315     d = md5Round1(d, a, b, c, x[9],  12, 0x8b44f7af);
316     c = md5Round1(c, d, a, b, x[10], 17, 0xffff5bb1);
317     b = md5Round1(b, c, d, a, x[11], 22, 0x895cd7be);
318     a = md5Round1(a, b, c, d, x[12],  7, 0x6b901122);
319     d = md5Round1(d, a, b, c, x[13], 12, 0xfd987193);
320     c = md5Round1(c, d, a, b, x[14], 17, 0xa679438e);
321     b = md5Round1(b, c, d, a, x[15], 22, 0x49b40821);
322
323     // round 2
324     a = md5Round2(a, b, c, d, x[1],   5, 0xf61e2562);
325     d = md5Round2(d, a, b, c, x[6],   9, 0xc040b340);
326     c = md5Round2(c, d, a, b, x[11], 14, 0x265e5a51);
327     b = md5Round2(b, c, d, a, x[0],  20, 0xe9b6c7aa);
328     a = md5Round2(a, b, c, d, x[5],   5, 0xd62f105d);
329     d = md5Round2(d, a, b, c, x[10],  9, 0x02441453);
330     c = md5Round2(c, d, a, b, x[15], 14, 0xd8a1e681);
331     b = md5Round2(b, c, d, a, x[4],  20, 0xe7d3fbc8);
332     a = md5Round2(a, b, c, d, x[9],   5, 0x21e1cde6);
333     d = md5Round2(d, a, b, c, x[14],  9, 0xc33707d6);
334     c = md5Round2(c, d, a, b, x[3],  14, 0xf4d50d87);
335     b = md5Round2(b, c, d, a, x[8],  20, 0x455a14ed);
336     a = md5Round2(a, b, c, d, x[13],  5, 0xa9e3e905);
337     d = md5Round2(d, a, b, c, x[2],   9, 0xfcefa3f8);
338     c = md5Round2(c, d, a, b, x[7],  14, 0x676f02d9);
339     b = md5Round2(b, c, d, a, x[12], 20, 0x8d2a4c8a);
340
341     // round 3
342     a = md5Round3(a, b, c, d, x[5],   4, 0xfffa3942);
343     d = md5Round3(d, a, b, c, x[8],  11, 0x8771f681);
344     c = md5Round3(c, d, a, b, x[11], 16, 0x6d9d6122);
345     b = md5Round3(b, c, d, a, x[14], 23, 0xfde5380c);
346     a = md5Round3(a, b, c, d, x[1],   4, 0xa4beea44);
347     d = md5Round3(d, a, b, c, x[4],  11, 0x4bdecfa9);
348     c = md5Round3(c, d, a, b, x[7],  16, 0xf6bb4b60);
349     b = md5Round3(b, c, d, a, x[10], 23, 0xbebfbc70);
350     a = md5Round3(a, b, c, d, x[13],  4, 0x289b7ec6);
351     d = md5Round3(d, a, b, c, x[0],  11, 0xeaa127fa);
352     c = md5Round3(c, d, a, b, x[3],  16, 0xd4ef3085);
353     b = md5Round3(b, c, d, a, x[6],  23, 0x04881d05);
354     a = md5Round3(a, b, c, d, x[9],   4, 0xd9d4d039);
355     d = md5Round3(d, a, b, c, x[12], 11, 0xe6db99e5);
356     c = md5Round3(c, d, a, b, x[15], 16, 0x1fa27cf8);
357     b = md5Round3(b, c, d, a, x[2],  23, 0xc4ac5665);
358
359     // round 4
360     a = md5Round4(a, b, c, d, x[0],   6, 0xf4292244);
361     d = md5Round4(d, a, b, c, x[7],  10, 0x432aff97);
362     c = md5Round4(c, d, a, b, x[14], 15, 0xab9423a7);
363     b = md5Round4(b, c, d, a, x[5],  21, 0xfc93a039);
364     a = md5Round4(a, b, c, d, x[12],  6, 0x655b59c3);
365     d = md5Round4(d, a, b, c, x[3],  10, 0x8f0ccc92);
366     c = md5Round4(c, d, a, b, x[10], 15, 0xffeff47d);
367     b = md5Round4(b, c, d, a, x[1],  21, 0x85845dd1);
368     a = md5Round4(a, b, c, d, x[8],   6, 0x6fa87e4f);
369     d = md5Round4(d, a, b, c, x[15], 10, 0xfe2ce6e0);
370     c = md5Round4(c, d, a, b, x[6],  15, 0xa3014314);
371     b = md5Round4(b, c, d, a, x[13], 21, 0x4e0811a1);
372     a = md5Round4(a, b, c, d, x[4],   6, 0xf7537e82);
373     d = md5Round4(d, a, b, c, x[11], 10, 0xbd3af235);
374     c = md5Round4(c, d, a, b, x[2],  15, 0x2ad7d2bb);
375     b = md5Round4(b, c, d, a, x[9],  21, 0xeb86d391);
376
377     // increment a, b, c, d
378     a += aa;
379     b += bb;
380     c += cc;
381     d += dd;
382   }
383
384   // break digest into bytes
385   digest[0] = a & 0xff;
386   digest[1] = (a >>= 8) & 0xff;
387   digest[2] = (a >>= 8) & 0xff;
388   digest[3] = (a >>= 8) & 0xff;
389   digest[4] = b & 0xff;
390   digest[5] = (b >>= 8) & 0xff;
391   digest[6] = (b >>= 8) & 0xff;
392   digest[7] = (b >>= 8) & 0xff;
393   digest[8] = c & 0xff;
394   digest[9] = (c >>= 8) & 0xff;
395   digest[10] = (c >>= 8) & 0xff;
396   digest[11] = (c >>= 8) & 0xff;
397   digest[12] = d & 0xff;
398   digest[13] = (d >>= 8) & 0xff;
399   digest[14] = (d >>= 8) & 0xff;
400   digest[15] = (d >>= 8) & 0xff;
401 }