Initial commit.
[pdfium.git] / core / src / fpdfapi / fpdf_parser / fpdf_parser_encrypt.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4  \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include <time.h>\r
8 #include "../../../include/fpdfapi/fpdf_parser.h"\r
9 #include "../../../include/fdrm/fx_crypt.h"\r
10 const FX_BYTE defpasscode[32] = {\r
11     0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,\r
12     0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,\r
13     0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,\r
14     0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a\r
15 };\r
16 void CalcEncryptKey(CPDF_Dictionary* pEncrypt, FX_LPCBYTE password, FX_DWORD pass_size,\r
17                     FX_LPBYTE key, int keylen, FX_BOOL bIgnoreMeta, CPDF_Array* pIdArray)\r
18 {\r
19     int revision = pEncrypt->GetInteger(FX_BSTRC("R"));\r
20     FX_BYTE passcode[32];\r
21     for (FX_DWORD i = 0; i < 32; i ++) {\r
22         passcode[i] = i < pass_size ? password[i] : defpasscode[i - pass_size];\r
23     }\r
24     FX_BYTE md5[100];\r
25     CRYPT_MD5Start(md5);\r
26     CRYPT_MD5Update(md5, passcode, 32);\r
27     CFX_ByteString okey = pEncrypt->GetString(FX_BSTRC("O"));\r
28     CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)okey, okey.GetLength());\r
29     FX_DWORD perm = pEncrypt->GetInteger(FX_BSTRC("P"));\r
30     CRYPT_MD5Update(md5, (FX_LPBYTE)&perm, 4);\r
31     if (pIdArray) {\r
32         CFX_ByteString id = pIdArray->GetString(0);\r
33         CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)id, id.GetLength());\r
34     }\r
35     if (!bIgnoreMeta && revision >= 3 && !pEncrypt->GetInteger(FX_BSTRC("EncryptMetadata"), 1)) {\r
36         FX_DWORD tag = (FX_DWORD) - 1;\r
37         CRYPT_MD5Update(md5, (FX_LPBYTE)&tag, 4);\r
38     }\r
39     FX_BYTE digest[16];\r
40     CRYPT_MD5Finish(md5, digest);\r
41     FX_DWORD copy_len = keylen;\r
42     if (copy_len > sizeof(digest)) {\r
43         copy_len = sizeof(digest);\r
44     }\r
45     if (revision >= 3) {\r
46         for (int i = 0; i < 50; i ++) {\r
47             CRYPT_MD5Generate(digest, copy_len, digest);\r
48         }\r
49     }\r
50     FXSYS_memset32(key, 0, keylen);\r
51     FXSYS_memcpy32(key, digest, copy_len);\r
52 }\r
53 CPDF_CryptoHandler* CPDF_StandardSecurityHandler::CreateCryptoHandler()\r
54 {\r
55     return FX_NEW CPDF_StandardCryptoHandler;\r
56 }\r
57 typedef struct _PDF_CRYPTOITEM : public CFX_Object {\r
58     FX_INT32    m_Cipher;\r
59     FX_INT32    m_KeyLen;\r
60     FX_BOOL             m_bChecked;\r
61     CPDF_StandardCryptoHandler* m_pCryptoHandler;\r
62 } PDF_CRYPTOITEM;\r
63 CPDF_StandardSecurityHandler::CPDF_StandardSecurityHandler()\r
64 {\r
65     m_Version = 0;\r
66     m_Revision = 0;\r
67     m_pParser = NULL;\r
68     m_pEncryptDict = NULL;\r
69     m_bOwner = FALSE;\r
70     m_Permissions = 0;\r
71     m_Cipher = FXCIPHER_NONE;\r
72     m_KeyLen = 0;\r
73 }\r
74 CPDF_StandardSecurityHandler::~CPDF_StandardSecurityHandler()\r
75 {\r
76 }\r
77 FX_BOOL CPDF_StandardSecurityHandler::OnInit(CPDF_Parser* pParser, CPDF_Dictionary* pEncryptDict)\r
78 {\r
79     m_pParser = pParser;\r
80     if (!LoadDict(pEncryptDict)) {\r
81         return FALSE;\r
82     }\r
83     if (m_Cipher == FXCIPHER_NONE) {\r
84         return TRUE;\r
85     }\r
86     return CheckSecurity(m_KeyLen);\r
87 }\r
88 FX_BOOL CPDF_StandardSecurityHandler::CheckSecurity(FX_INT32 key_len)\r
89 {\r
90     CFX_ByteString password = m_pParser->GetPassword();\r
91     if (CheckPassword(password, password.GetLength(), TRUE, m_EncryptKey, key_len)) {\r
92         if (password.IsEmpty()) {\r
93             if (!CheckPassword(password, password.GetLength(), FALSE, m_EncryptKey, key_len)) {\r
94                 return FALSE;\r
95             }\r
96         }\r
97         m_bOwner = TRUE;\r
98         return TRUE;\r
99     }\r
100     return CheckPassword(password, password.GetLength(), FALSE, m_EncryptKey, key_len);\r
101 }\r
102 FX_DWORD CPDF_StandardSecurityHandler::GetPermissions()\r
103 {\r
104     return m_Permissions;\r
105 }\r
106 static FX_BOOL _LoadCryptInfo(CPDF_Dictionary* pEncryptDict, FX_BSTR name, int& cipher, int& keylen)\r
107 {\r
108     int Version = pEncryptDict->GetInteger(FX_BSTRC("V"));\r
109     int Revision = pEncryptDict->GetInteger(FX_BSTRC("R"));\r
110     cipher = FXCIPHER_RC4;\r
111     keylen = 0;\r
112     if (Version >= 4) {\r
113         CPDF_Dictionary* pCryptFilters = pEncryptDict->GetDict(FX_BSTRC("CF"));\r
114         if (pCryptFilters == NULL) {\r
115             return FALSE;\r
116         }\r
117         if (name == FX_BSTRC("Identity")) {\r
118             cipher = FXCIPHER_NONE;\r
119         } else {\r
120             CPDF_Dictionary* pDefFilter = pCryptFilters->GetDict(name);\r
121             if (pDefFilter == NULL) {\r
122                 return FALSE;\r
123             }\r
124             int nKeyBits = 0;\r
125             if (Version == 4) {\r
126                 nKeyBits = pDefFilter->GetInteger(FX_BSTRC("Length"), 0);\r
127                 if (nKeyBits == 0) {\r
128                     nKeyBits = pEncryptDict->GetInteger(FX_BSTRC("Length"), 128);\r
129                 }\r
130             } else {\r
131                 nKeyBits = pEncryptDict->GetInteger(FX_BSTRC("Length"), 256);\r
132             }\r
133             if (nKeyBits < 40) {\r
134                 nKeyBits *= 8;\r
135             }\r
136             keylen = nKeyBits / 8;\r
137             CFX_ByteString cipher_name = pDefFilter->GetString(FX_BSTRC("CFM"));\r
138             if (cipher_name == FX_BSTRC("AESV2") || cipher_name == FX_BSTRC("AESV3")) {\r
139                 cipher = FXCIPHER_AES;\r
140             }\r
141         }\r
142     } else {\r
143         keylen = Version > 1 ? pEncryptDict->GetInteger(FX_BSTRC("Length"), 40) / 8 : 5;\r
144     }\r
145     if (keylen > 32 || keylen < 0) {\r
146         return FALSE;\r
147     }\r
148     return TRUE;\r
149 }\r
150 FX_BOOL CPDF_StandardSecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict)\r
151 {\r
152     m_pEncryptDict = pEncryptDict;\r
153     m_bOwner = FALSE;\r
154     m_Version = pEncryptDict->GetInteger(FX_BSTRC("V"));\r
155     m_Revision = pEncryptDict->GetInteger(FX_BSTRC("R"));\r
156     m_Permissions = pEncryptDict->GetInteger(FX_BSTRC("P"), -1);\r
157     if (m_Version < 4) {\r
158         return _LoadCryptInfo(pEncryptDict, CFX_ByteString(), m_Cipher, m_KeyLen);\r
159     }\r
160     CFX_ByteString stmf_name = pEncryptDict->GetString(FX_BSTRC("StmF"));\r
161     CFX_ByteString strf_name = pEncryptDict->GetString(FX_BSTRC("StrF"));\r
162     if (stmf_name != strf_name) {\r
163         return FALSE;\r
164     }\r
165     if (!_LoadCryptInfo(pEncryptDict, strf_name, m_Cipher, m_KeyLen)) {\r
166         return FALSE;\r
167     }\r
168     return TRUE;\r
169 }\r
170 FX_BOOL CPDF_StandardSecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict, FX_DWORD type, int& cipher, int& key_len)\r
171 {\r
172     m_pEncryptDict = pEncryptDict;\r
173     m_bOwner = FALSE;\r
174     m_Version = pEncryptDict->GetInteger(FX_BSTRC("V"));\r
175     m_Revision = pEncryptDict->GetInteger(FX_BSTRC("R"));\r
176     m_Permissions = pEncryptDict->GetInteger(FX_BSTRC("P"), -1);\r
177     CFX_ByteString strf_name, stmf_name;\r
178     if (m_Version >= 4) {\r
179         stmf_name = pEncryptDict->GetString(FX_BSTRC("StmF"));\r
180         strf_name = pEncryptDict->GetString(FX_BSTRC("StrF"));\r
181         if (stmf_name != strf_name) {\r
182             return FALSE;\r
183         }\r
184     }\r
185     if (!_LoadCryptInfo(pEncryptDict, strf_name, cipher, key_len)) {\r
186         return FALSE;\r
187     }\r
188     m_Cipher = cipher;\r
189     m_KeyLen = key_len;\r
190     return TRUE;\r
191     return TRUE;\r
192 }\r
193 FX_BOOL CPDF_StandardSecurityHandler::GetCryptInfo(int& cipher, FX_LPCBYTE& buffer, int& keylen)\r
194 {\r
195     cipher = m_Cipher;\r
196     buffer = m_EncryptKey;\r
197     keylen = m_KeyLen;\r
198     return TRUE;\r
199 }\r
200 #define FX_GET_32WORD(n,b,i)                                                            \\r
201     {                                                                                                           \\r
202         (n) = (FX_DWORD)(( (FX_UINT64) (b)[(i)] << 24 )                 \\r
203                          | ( (FX_UINT64) (b)[(i) + 1] << 16 )                                   \\r
204                          | ( (FX_UINT64) (b)[(i) + 2] <<  8 )                                   \\r
205                          | ( (FX_UINT64) (b)[(i) + 3]       ));                                 \\r
206     }\r
207 int BigOrder64BitsMod3(FX_LPBYTE data)\r
208 {\r
209     FX_UINT64 ret = 0;\r
210     for (int i = 0; i < 4; ++i) {\r
211         FX_DWORD value;\r
212         FX_GET_32WORD(value, data, 4 * i);\r
213         ret <<= 32;\r
214         ret |= value;\r
215         ret %= 3;\r
216     }\r
217     return (int)ret;\r
218 }\r
219 void Revision6_Hash(FX_LPCBYTE password, FX_DWORD size, FX_LPCBYTE salt, FX_LPCBYTE vector, FX_LPBYTE hash)\r
220 {\r
221     int iBlockSize = 32;\r
222     FX_BYTE sha[128];\r
223     CRYPT_SHA256Start(sha);\r
224     CRYPT_SHA256Update(sha, password, size);\r
225     CRYPT_SHA256Update(sha, salt, 8);\r
226     if (vector) {\r
227         CRYPT_SHA256Update(sha, vector, 48);\r
228     }\r
229     FX_BYTE digest[32];\r
230     CRYPT_SHA256Finish(sha, digest);\r
231     CFX_ByteTextBuf buf;\r
232     FX_LPBYTE input = digest;\r
233     FX_LPBYTE key = input;\r
234     FX_LPBYTE iv = input + 16;\r
235     FX_LPBYTE E = buf.GetBuffer();\r
236     int iBufLen = buf.GetLength();\r
237     CFX_ByteTextBuf interDigest;\r
238     int i = 0;\r
239     FX_LPBYTE aes = FX_Alloc(FX_BYTE, 2048);\r
240     while (i < 64 || i < E[iBufLen - 1]  + 32) {\r
241         int iRoundSize = size + iBlockSize;\r
242         if (vector) {\r
243             iRoundSize += 48;\r
244         }\r
245         iBufLen = iRoundSize * 64;\r
246         buf.EstimateSize(iBufLen);\r
247         E = buf.GetBuffer();\r
248         CFX_ByteTextBuf content;\r
249         for (int j = 0; j < 64; ++j) {\r
250             content.AppendBlock(password, size);\r
251             content.AppendBlock(input, iBlockSize);\r
252             if (vector) {\r
253                 content.AppendBlock(vector, 48);\r
254             }\r
255         }\r
256         CRYPT_AESSetKey(aes, 16, key, 16, TRUE);\r
257         CRYPT_AESSetIV(aes, iv);\r
258         CRYPT_AESEncrypt(aes, E, content.GetBuffer(), iBufLen);\r
259         int iHash = 0;\r
260         switch (BigOrder64BitsMod3(E)) {\r
261             case 0:\r
262                 iHash = 0;\r
263                 iBlockSize = 32;\r
264                 break;\r
265             case 1:\r
266                 iHash = 1;\r
267                 iBlockSize = 48;\r
268                 break;\r
269             default:\r
270                 iHash = 2;\r
271                 iBlockSize = 64;\r
272                 break;\r
273         }\r
274         interDigest.EstimateSize(iBlockSize);\r
275         input = interDigest.GetBuffer();\r
276         if (iHash == 0) {\r
277             CRYPT_SHA256Generate(E, iBufLen, input);\r
278         } else if (iHash == 1) {\r
279             CRYPT_SHA384Generate(E, iBufLen, input);\r
280         } else if (iHash == 2) {\r
281             CRYPT_SHA512Generate(E, iBufLen, input);\r
282         }\r
283         key = input;\r
284         iv = input + 16;\r
285         ++i;\r
286     }\r
287     FX_Free(aes);\r
288     if (hash) {\r
289         FXSYS_memcpy32(hash, input, 32);\r
290     }\r
291 }\r
292 FX_BOOL CPDF_StandardSecurityHandler::AES256_CheckPassword(FX_LPCBYTE password, FX_DWORD size,\r
293         FX_BOOL bOwner, FX_LPBYTE key)\r
294 {\r
295     CFX_ByteString okey = m_pEncryptDict->GetString(FX_BSTRC("O"));\r
296     if (okey.GetLength() < 48) {\r
297         return FALSE;\r
298     }\r
299     CFX_ByteString ukey = m_pEncryptDict->GetString(FX_BSTRC("U"));\r
300     if (ukey.GetLength() < 48) {\r
301         return FALSE;\r
302     }\r
303     FX_LPCBYTE pkey = bOwner ? (FX_LPCBYTE)okey : (FX_LPCBYTE)ukey;\r
304     FX_BYTE sha[128];\r
305     FX_BYTE digest[32];\r
306     if (m_Revision >= 6) {\r
307         Revision6_Hash(password, size, (FX_LPCBYTE)pkey + 32, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest);\r
308     } else {\r
309         CRYPT_SHA256Start(sha);\r
310         CRYPT_SHA256Update(sha, password, size);\r
311         CRYPT_SHA256Update(sha, pkey + 32, 8);\r
312         if (bOwner) {\r
313             CRYPT_SHA256Update(sha, ukey, 48);\r
314         }\r
315         CRYPT_SHA256Finish(sha, digest);\r
316     }\r
317     if (FXSYS_memcmp32(digest, pkey, 32) != 0) {\r
318         return FALSE;\r
319     }\r
320     if (key == NULL) {\r
321         return TRUE;\r
322     }\r
323     if (m_Revision >= 6) {\r
324         Revision6_Hash(password, size, (FX_LPCBYTE)pkey + 40, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest);\r
325     } else {\r
326         CRYPT_SHA256Start(sha);\r
327         CRYPT_SHA256Update(sha, password, size);\r
328         CRYPT_SHA256Update(sha, pkey + 40, 8);\r
329         if (bOwner) {\r
330             CRYPT_SHA256Update(sha, ukey, 48);\r
331         }\r
332         CRYPT_SHA256Finish(sha, digest);\r
333     }\r
334     CFX_ByteString ekey = m_pEncryptDict->GetString(bOwner ? FX_BSTRC("OE") : FX_BSTRC("UE"));\r
335     if (ekey.GetLength() < 32) {\r
336         return FALSE;\r
337     }\r
338     FX_BYTE* aes = FX_Alloc(FX_BYTE, 2048);\r
339     CRYPT_AESSetKey(aes, 16, digest, 32, FALSE);\r
340     FX_BYTE iv[16];\r
341     FXSYS_memset32(iv, 0, 16);\r
342     CRYPT_AESSetIV(aes, iv);\r
343     CRYPT_AESDecrypt(aes, key, ekey, 32);\r
344     CRYPT_AESSetKey(aes, 16, key, 32, FALSE);\r
345     CRYPT_AESSetIV(aes, iv);\r
346     CFX_ByteString perms = m_pEncryptDict->GetString(FX_BSTRC("Perms"));\r
347     if (perms.IsEmpty()) {\r
348         return FALSE;\r
349     }\r
350     FX_BYTE perms_buf[16];\r
351     FXSYS_memset32(perms_buf, 0, sizeof(perms_buf));\r
352     FX_DWORD copy_len = sizeof(perms_buf);\r
353     if (copy_len > (FX_DWORD)perms.GetLength()) {\r
354         copy_len = perms.GetLength();\r
355     }\r
356     FXSYS_memcpy32(perms_buf, (FX_LPCBYTE)perms, copy_len);\r
357     FX_BYTE buf[16];\r
358     CRYPT_AESDecrypt(aes, buf, perms_buf, 16);\r
359     FX_Free(aes);\r
360     if (buf[9] != 'a' || buf[10] != 'd' || buf[11] != 'b') {\r
361         return FALSE;\r
362     }\r
363     if (FXDWORD_GET_LSBFIRST(buf) != m_Permissions) {\r
364         return FALSE;\r
365     }\r
366     if ((buf[8] == 'T' && !IsMetadataEncrypted()) || (buf[8] == 'F' && IsMetadataEncrypted())) {\r
367         return FALSE;\r
368     }\r
369     return TRUE;\r
370 }\r
371 int CPDF_StandardSecurityHandler::CheckPassword(FX_LPCBYTE password, FX_DWORD pass_size, FX_BOOL bOwner, FX_LPBYTE key)\r
372 {\r
373     return CheckPassword(password, pass_size, bOwner, key, m_KeyLen);\r
374 }\r
375 int CPDF_StandardSecurityHandler::CheckPassword(FX_LPCBYTE password, FX_DWORD size, FX_BOOL bOwner, FX_LPBYTE key, FX_INT32 key_len)\r
376 {\r
377     if (m_Revision >= 5) {\r
378         return AES256_CheckPassword(password, size, bOwner, key);\r
379     }\r
380     FX_BYTE keybuf[32];\r
381     if (key == NULL) {\r
382         key = keybuf;\r
383     }\r
384     if (bOwner) {\r
385         return CheckOwnerPassword(password, size, key, key_len);\r
386     }\r
387     return CheckUserPassword(password, size, FALSE, key, key_len) || CheckUserPassword(password, size, TRUE, key, key_len);\r
388 }\r
389 FX_BOOL CPDF_StandardSecurityHandler::CheckUserPassword(FX_LPCBYTE password, FX_DWORD pass_size,\r
390         FX_BOOL bIgnoreEncryptMeta, FX_LPBYTE key, FX_INT32 key_len)\r
391 {\r
392     CalcEncryptKey(m_pEncryptDict, password, pass_size, key, key_len, bIgnoreEncryptMeta,\r
393                    m_pParser->GetIDArray());\r
394     CFX_ByteString ukey = m_pEncryptDict->GetString(FX_BSTRC("U"));\r
395     if (ukey.GetLength() < 16) {\r
396         return FALSE;\r
397     }\r
398     FX_BYTE ukeybuf[32];\r
399     if (m_Revision == 2) {\r
400         FXSYS_memcpy32(ukeybuf, defpasscode, 32);\r
401         CRYPT_ArcFourCryptBlock(ukeybuf, 32, key, key_len);\r
402     } else {\r
403         FX_BYTE test[32], tmpkey[32];\r
404         FX_DWORD copy_len = sizeof(test);\r
405         if (copy_len > (FX_DWORD)ukey.GetLength()) {\r
406             copy_len = ukey.GetLength();\r
407         }\r
408         FXSYS_memset32(test, 0, sizeof(test));\r
409         FXSYS_memcpy32(test, (FX_LPCSTR)ukey, copy_len);\r
410         for (int i = 19; i >= 0; i --) {\r
411             for (int j = 0; j < key_len; j ++) {\r
412                 tmpkey[j] = key[j] ^ i;\r
413             }\r
414             CRYPT_ArcFourCryptBlock(test, 32, tmpkey, key_len);\r
415         }\r
416         FX_BYTE md5[100];\r
417         CRYPT_MD5Start(md5);\r
418         CRYPT_MD5Update(md5, defpasscode, 32);\r
419         CPDF_Array* pIdArray = m_pParser->GetIDArray();\r
420         if (pIdArray) {\r
421             CFX_ByteString id = pIdArray->GetString(0);\r
422             CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)id, id.GetLength());\r
423         }\r
424         CRYPT_MD5Finish(md5, ukeybuf);\r
425         return FXSYS_memcmp32(test, ukeybuf, 16) == 0;\r
426     }\r
427     if (FXSYS_memcmp32((FX_LPVOID)(FX_LPCSTR)ukey, ukeybuf, 16) == 0) {\r
428         return TRUE;\r
429     }\r
430     return FALSE;\r
431 }\r
432 CFX_ByteString CPDF_StandardSecurityHandler::GetUserPassword(FX_LPCBYTE owner_pass, FX_DWORD pass_size)\r
433 {\r
434     return GetUserPassword(owner_pass, pass_size, m_KeyLen);\r
435 }\r
436 CFX_ByteString CPDF_StandardSecurityHandler::GetUserPassword(FX_LPCBYTE owner_pass, FX_DWORD pass_size, FX_INT32 key_len)\r
437 {\r
438     CFX_ByteString okey = m_pEncryptDict->GetString(FX_BSTRC("O"));\r
439     FX_BYTE passcode[32];\r
440     FX_DWORD i;\r
441     for (i = 0; i < 32; i ++) {\r
442         passcode[i] = i < pass_size ? owner_pass[i] : defpasscode[i - pass_size];\r
443     }\r
444     FX_BYTE digest[16];\r
445     CRYPT_MD5Generate(passcode, 32, digest);\r
446     if (m_Revision >= 3) {\r
447         for (int i = 0; i < 50; i ++) {\r
448             CRYPT_MD5Generate(digest, 16, digest);\r
449         }\r
450     }\r
451     FX_BYTE enckey[32];\r
452     FXSYS_memset32(enckey, 0, sizeof(enckey));\r
453     FX_DWORD copy_len = key_len;\r
454     if (copy_len > sizeof(digest)) {\r
455         copy_len = sizeof(digest);\r
456     }\r
457     FXSYS_memcpy32(enckey, digest, copy_len);\r
458     int okeylen = okey.GetLength();\r
459     if (okeylen > 32) {\r
460         okeylen = 32;\r
461     }\r
462     FX_BYTE okeybuf[64];\r
463     FXSYS_memcpy32(okeybuf, (FX_LPCSTR)okey, okeylen);\r
464     if (m_Revision == 2) {\r
465         CRYPT_ArcFourCryptBlock(okeybuf, okeylen, enckey, key_len);\r
466     } else {\r
467         for (int i = 19; i >= 0; i --) {\r
468             FX_BYTE tempkey[32];\r
469             for (int j = 0; j < m_KeyLen; j ++) {\r
470                 tempkey[j] = enckey[j] ^ i;\r
471             }\r
472             CRYPT_ArcFourCryptBlock(okeybuf, okeylen, tempkey, key_len);\r
473         }\r
474     }\r
475     int len = 32;\r
476     while (len && defpasscode[len - 1] == okeybuf[len - 1]) {\r
477         len --;\r
478     }\r
479     return CFX_ByteString(okeybuf, len);\r
480 }\r
481 FX_BOOL CPDF_StandardSecurityHandler::CheckOwnerPassword(FX_LPCBYTE password, FX_DWORD pass_size,\r
482         FX_LPBYTE key, FX_INT32 key_len)\r
483 {\r
484     CFX_ByteString user_pass = GetUserPassword(password, pass_size, key_len);\r
485     if (CheckUserPassword(user_pass, user_pass.GetLength(), FALSE, key, key_len)) {\r
486         return TRUE;\r
487     }\r
488     return CheckUserPassword(user_pass, user_pass.GetLength(), TRUE, key, key_len);\r
489 }\r
490 FX_BOOL CPDF_StandardSecurityHandler::IsMetadataEncrypted()\r
491 {\r
492     return m_pEncryptDict->GetBoolean(FX_BSTRC("EncryptMetadata"), TRUE);\r
493 }\r
494 CPDF_SecurityHandler* FPDF_CreateStandardSecurityHandler()\r
495 {\r
496     return FX_NEW CPDF_StandardSecurityHandler;\r
497 }\r
498 void CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray,\r
499         FX_LPCBYTE user_pass, FX_DWORD user_size,\r
500         FX_LPCBYTE owner_pass, FX_DWORD owner_size, FX_BOOL bDefault, FX_DWORD type)\r
501 {\r
502     int cipher = 0, key_len = 0;\r
503     if (!LoadDict(pEncryptDict, type, cipher, key_len)) {\r
504         return;\r
505     }\r
506     if (bDefault && (owner_pass == NULL || owner_size == 0)) {\r
507         owner_pass = user_pass;\r
508         owner_size = user_size;\r
509     }\r
510     if (m_Revision >= 5) {\r
511         int t = (int)time(NULL);\r
512         FX_BYTE sha[128];\r
513         CRYPT_SHA256Start(sha);\r
514         CRYPT_SHA256Update(sha, (FX_BYTE*)&t, sizeof t);\r
515         CRYPT_SHA256Update(sha, m_EncryptKey, 32);\r
516         CRYPT_SHA256Update(sha, (FX_BYTE*)"there", 5);\r
517         CRYPT_SHA256Finish(sha, m_EncryptKey);\r
518         AES256_SetPassword(pEncryptDict, user_pass, user_size, FALSE, m_EncryptKey);\r
519         if (bDefault) {\r
520             AES256_SetPassword(pEncryptDict, owner_pass, owner_size, TRUE, m_EncryptKey);\r
521             AES256_SetPerms(pEncryptDict, m_Permissions, pEncryptDict->GetBoolean(FX_BSTRC("EncryptMetadata"), TRUE), m_EncryptKey);\r
522         }\r
523         return;\r
524     }\r
525     if (bDefault) {\r
526         FX_BYTE passcode[32];\r
527         FX_DWORD i;\r
528         for (i = 0; i < 32; i ++) {\r
529             passcode[i] = i < owner_size ? owner_pass[i] : defpasscode[i - owner_size];\r
530         }\r
531         FX_BYTE digest[16];\r
532         CRYPT_MD5Generate(passcode, 32, digest);\r
533         if (m_Revision >= 3) {\r
534             for (int i = 0; i < 50; i ++) {\r
535                 CRYPT_MD5Generate(digest, 16, digest);\r
536             }\r
537         }\r
538         FX_BYTE enckey[32];\r
539         FXSYS_memcpy32(enckey, digest, key_len);\r
540         for (i = 0; i < 32; i ++) {\r
541             passcode[i] = i < user_size ? user_pass[i] : defpasscode[i - user_size];\r
542         }\r
543         CRYPT_ArcFourCryptBlock(passcode, 32, enckey, key_len);\r
544         FX_BYTE tempkey[32];\r
545         if (m_Revision >= 3) {\r
546             for (i = 1; i <= 19; i ++) {\r
547                 for (int j = 0; j < key_len; j ++) {\r
548                     tempkey[j] = enckey[j] ^ (FX_BYTE)i;\r
549                 }\r
550                 CRYPT_ArcFourCryptBlock(passcode, 32, tempkey, key_len);\r
551             }\r
552         }\r
553         pEncryptDict->SetAtString(FX_BSTRC("O"), CFX_ByteString(passcode, 32));\r
554     }\r
555     CalcEncryptKey(m_pEncryptDict, (FX_LPBYTE)user_pass, user_size, m_EncryptKey, key_len, FALSE, pIdArray);\r
556     if (m_Revision < 3) {\r
557         FX_BYTE tempbuf[32];\r
558         FXSYS_memcpy32(tempbuf, defpasscode, 32);\r
559         CRYPT_ArcFourCryptBlock(tempbuf, 32, m_EncryptKey, key_len);\r
560         pEncryptDict->SetAtString(FX_BSTRC("U"), CFX_ByteString(tempbuf, 32));\r
561     } else {\r
562         FX_BYTE md5[100];\r
563         CRYPT_MD5Start(md5);\r
564         CRYPT_MD5Update(md5, defpasscode, 32);\r
565         if (pIdArray) {\r
566             CFX_ByteString id = pIdArray->GetString(0);\r
567             CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)id, id.GetLength());\r
568         }\r
569         FX_BYTE digest[32];\r
570         CRYPT_MD5Finish(md5, digest);\r
571         CRYPT_ArcFourCryptBlock(digest, 16, m_EncryptKey, key_len);\r
572         FX_BYTE tempkey[32];\r
573         for (int i = 1; i <= 19; i ++) {\r
574             for (int j = 0; j < key_len; j ++) {\r
575                 tempkey[j] = m_EncryptKey[j] ^ (FX_BYTE)i;\r
576             }\r
577             CRYPT_ArcFourCryptBlock(digest, 16, tempkey, key_len);\r
578         }\r
579         CRYPT_MD5Generate(digest, 16, digest + 16);\r
580         pEncryptDict->SetAtString(FX_BSTRC("U"), CFX_ByteString(digest, 32));\r
581     }\r
582 }\r
583 void CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray,\r
584         FX_LPCBYTE user_pass, FX_DWORD user_size,\r
585         FX_LPCBYTE owner_pass, FX_DWORD owner_size, FX_DWORD type)\r
586 {\r
587     OnCreate(pEncryptDict, pIdArray, user_pass, user_size, owner_pass, owner_size, TRUE, type);\r
588 }\r
589 void CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray, FX_LPCBYTE user_pass, FX_DWORD user_size, FX_DWORD type)\r
590 {\r
591     OnCreate(pEncryptDict, pIdArray, user_pass, user_size, NULL, 0, FALSE, type);\r
592 }\r
593 void CPDF_StandardSecurityHandler::AES256_SetPassword(CPDF_Dictionary* pEncryptDict, FX_LPCBYTE password, FX_DWORD size, FX_BOOL bOwner, FX_LPCBYTE key)\r
594 {\r
595     FX_BYTE sha[128];\r
596     CRYPT_SHA1Start(sha);\r
597     CRYPT_SHA1Update(sha, key, 32);\r
598     CRYPT_SHA1Update(sha, (FX_BYTE*)"hello", 5);\r
599     FX_BYTE digest[20];\r
600     CRYPT_SHA1Finish(sha, digest);\r
601     CFX_ByteString ukey = pEncryptDict->GetString(FX_BSTRC("U"));\r
602     FX_BYTE digest1[48];\r
603     if (m_Revision >= 6) {\r
604         Revision6_Hash(password, size, digest, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest1);\r
605     } else {\r
606         CRYPT_SHA256Start(sha);\r
607         CRYPT_SHA256Update(sha, password, size);\r
608         CRYPT_SHA256Update(sha, digest, 8);\r
609         if (bOwner) {\r
610             CRYPT_SHA256Update(sha, ukey, ukey.GetLength());\r
611         }\r
612         CRYPT_SHA256Finish(sha, digest1);\r
613     }\r
614     FXSYS_memcpy32(digest1 + 32, digest, 16);\r
615     pEncryptDict->SetAtString(bOwner ? FX_BSTRC("O") : FX_BSTRC("U"), CFX_ByteString(digest1, 48));\r
616     if (m_Revision >= 6) {\r
617         Revision6_Hash(password, size, digest + 8, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest1);\r
618     } else {\r
619         CRYPT_SHA256Start(sha);\r
620         CRYPT_SHA256Update(sha, password, size);\r
621         CRYPT_SHA256Update(sha, digest + 8, 8);\r
622         if (bOwner) {\r
623             CRYPT_SHA256Update(sha, ukey, ukey.GetLength());\r
624         }\r
625         CRYPT_SHA256Finish(sha, digest1);\r
626     }\r
627     FX_BYTE* aes = FX_Alloc(FX_BYTE, 2048);\r
628     CRYPT_AESSetKey(aes, 16, digest1, 32, TRUE);\r
629     FX_BYTE iv[16];\r
630     FXSYS_memset32(iv, 0, 16);\r
631     CRYPT_AESSetIV(aes, iv);\r
632     CRYPT_AESEncrypt(aes, digest1, key, 32);\r
633     FX_Free(aes);\r
634     pEncryptDict->SetAtString(bOwner ? FX_BSTRC("OE") : FX_BSTRC("UE"), CFX_ByteString(digest1, 32));\r
635 }\r
636 void CPDF_StandardSecurityHandler::AES256_SetPerms(CPDF_Dictionary* pEncryptDict, FX_DWORD permissions,\r
637         FX_BOOL bEncryptMetadata, FX_LPCBYTE key)\r
638 {\r
639     FX_BYTE buf[16];\r
640     buf[0] = (FX_BYTE)permissions;\r
641     buf[1] = (FX_BYTE)(permissions >> 8);\r
642     buf[2] = (FX_BYTE)(permissions >> 16);\r
643     buf[3] = (FX_BYTE)(permissions >> 24);\r
644     buf[4] = 0xff;\r
645     buf[5] = 0xff;\r
646     buf[6] = 0xff;\r
647     buf[7] = 0xff;\r
648     buf[8] = bEncryptMetadata ? 'T' : 'F';\r
649     buf[9] = 'a';\r
650     buf[10] = 'd';\r
651     buf[11] = 'b';\r
652     FX_BYTE* aes = FX_Alloc(FX_BYTE, 2048);\r
653     CRYPT_AESSetKey(aes, 16, key, 32, TRUE);\r
654     FX_BYTE iv[16], buf1[16];\r
655     FXSYS_memset32(iv, 0, 16);\r
656     CRYPT_AESSetIV(aes, iv);\r
657     CRYPT_AESEncrypt(aes, buf1, buf, 16);\r
658     FX_Free(aes);\r
659     pEncryptDict->SetAtString(FX_BSTRC("Perms"), CFX_ByteString(buf1, 16));\r
660 }\r
661 void CPDF_StandardCryptoHandler::CryptBlock(FX_BOOL bEncrypt, FX_DWORD objnum, FX_DWORD gennum, FX_LPCBYTE src_buf, FX_DWORD src_size,\r
662         FX_LPBYTE dest_buf, FX_DWORD& dest_size)\r
663 {\r
664     if (m_Cipher == FXCIPHER_NONE) {\r
665         FXSYS_memcpy32(dest_buf, src_buf, src_size);\r
666         return;\r
667     }\r
668     FX_BYTE realkey[16];\r
669     int realkeylen = 16;\r
670     if (m_Cipher != FXCIPHER_AES || m_KeyLen != 32) {\r
671         FX_BYTE key1[32];\r
672         FXSYS_memcpy32(key1, m_EncryptKey, m_KeyLen);\r
673         key1[m_KeyLen + 0] = (FX_BYTE)objnum;\r
674         key1[m_KeyLen + 1] = (FX_BYTE)(objnum >> 8);\r
675         key1[m_KeyLen + 2] = (FX_BYTE)(objnum >> 16);\r
676         key1[m_KeyLen + 3] = (FX_BYTE)gennum;\r
677         key1[m_KeyLen + 4] = (FX_BYTE)(gennum >> 8);\r
678         FXSYS_memcpy32(key1 + m_KeyLen, &objnum, 3);\r
679         FXSYS_memcpy32(key1 + m_KeyLen + 3, &gennum, 2);\r
680         if (m_Cipher == FXCIPHER_AES) {\r
681             FXSYS_memcpy32(key1 + m_KeyLen + 5, "sAlT", 4);\r
682         }\r
683         CRYPT_MD5Generate(key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey);\r
684         realkeylen = m_KeyLen + 5;\r
685         if (realkeylen > 16) {\r
686             realkeylen = 16;\r
687         }\r
688     }\r
689     if (m_Cipher == FXCIPHER_AES) {\r
690         CRYPT_AESSetKey(m_pAESContext, 16, m_KeyLen == 32 ? m_EncryptKey : realkey, m_KeyLen, bEncrypt);\r
691         if (bEncrypt) {\r
692             FX_BYTE iv[16];\r
693             for (int i = 0; i < 16; i ++) {\r
694                 iv[i] = (FX_BYTE)rand();\r
695             }\r
696             CRYPT_AESSetIV(m_pAESContext, iv);\r
697             FXSYS_memcpy32(dest_buf, iv, 16);\r
698             int nblocks = src_size / 16;\r
699             CRYPT_AESEncrypt(m_pAESContext, dest_buf + 16, src_buf, nblocks * 16);\r
700             FX_BYTE padding[16];\r
701             FXSYS_memcpy32(padding, src_buf + nblocks * 16, src_size % 16);\r
702             FXSYS_memset8(padding + src_size % 16, 16 - src_size % 16, 16 - src_size % 16);\r
703             CRYPT_AESEncrypt(m_pAESContext, dest_buf + nblocks * 16 + 16, padding, 16);\r
704             dest_size = 32 + nblocks * 16;\r
705         } else {\r
706             CRYPT_AESSetIV(m_pAESContext, src_buf);\r
707             CRYPT_AESDecrypt(m_pAESContext, dest_buf, src_buf + 16, src_size - 16);\r
708             dest_size = src_size - 16;\r
709             dest_size -= dest_buf[dest_size - 1];\r
710         }\r
711     } else {\r
712         ASSERT(dest_size == src_size);\r
713         if (dest_buf != src_buf) {\r
714             FXSYS_memcpy32(dest_buf, src_buf, src_size);\r
715         }\r
716         CRYPT_ArcFourCryptBlock(dest_buf, dest_size, realkey, realkeylen);\r
717     }\r
718 }\r
719 typedef struct _AESCryptContext {\r
720     FX_BYTE             m_Context[2048];\r
721     FX_BOOL             m_bIV;\r
722     FX_BYTE             m_Block[16];\r
723     FX_DWORD    m_BlockOffset;\r
724 } AESCryptContext;\r
725 FX_LPVOID CPDF_StandardCryptoHandler::CryptStart(FX_DWORD objnum, FX_DWORD gennum, FX_BOOL bEncrypt)\r
726 {\r
727     if (m_Cipher == FXCIPHER_NONE) {\r
728         return this;\r
729     }\r
730     if (m_Cipher == FXCIPHER_AES && m_KeyLen == 32) {\r
731         AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1);\r
732         pContext->m_bIV = TRUE;\r
733         pContext->m_BlockOffset = 0;\r
734         CRYPT_AESSetKey(pContext->m_Context, 16, m_EncryptKey, 32, bEncrypt);\r
735         if (bEncrypt) {\r
736             for (int i = 0; i < 16; i ++) {\r
737                 pContext->m_Block[i] = (FX_BYTE)rand();\r
738             }\r
739             CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block);\r
740         }\r
741         return pContext;\r
742     }\r
743     FX_BYTE key1[48];\r
744     FXSYS_memcpy32(key1, m_EncryptKey, m_KeyLen);\r
745     FXSYS_memcpy32(key1 + m_KeyLen, &objnum, 3);\r
746     FXSYS_memcpy32(key1 + m_KeyLen + 3, &gennum, 2);\r
747     if (m_Cipher == FXCIPHER_AES) {\r
748         FXSYS_memcpy32(key1 + m_KeyLen + 5, "sAlT", 4);\r
749     }\r
750     FX_BYTE realkey[16];\r
751     CRYPT_MD5Generate(key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey);\r
752     int realkeylen = m_KeyLen + 5;\r
753     if (realkeylen > 16) {\r
754         realkeylen = 16;\r
755     }\r
756     if (m_Cipher == FXCIPHER_AES) {\r
757         AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1);\r
758         pContext->m_bIV = TRUE;\r
759         pContext->m_BlockOffset = 0;\r
760         CRYPT_AESSetKey(pContext->m_Context, 16, realkey, 16, bEncrypt);\r
761         if (bEncrypt) {\r
762             for (int i = 0; i < 16; i ++) {\r
763                 pContext->m_Block[i] = (FX_BYTE)rand();\r
764             }\r
765             CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block);\r
766         }\r
767         return pContext;\r
768     }\r
769     void* pContext = FX_Alloc(FX_BYTE, 1040);\r
770     CRYPT_ArcFourSetup(pContext, realkey, realkeylen);\r
771     return pContext;\r
772 }\r
773 FX_BOOL CPDF_StandardCryptoHandler::CryptStream(FX_LPVOID context, FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf, FX_BOOL bEncrypt)\r
774 {\r
775     if (!context) {\r
776         return FALSE;\r
777     }\r
778     if (m_Cipher == FXCIPHER_NONE) {\r
779         dest_buf.AppendBlock(src_buf, src_size);\r
780         return TRUE;\r
781     }\r
782     if (m_Cipher == FXCIPHER_RC4) {\r
783         int old_size = dest_buf.GetSize();\r
784         dest_buf.AppendBlock(src_buf, src_size);\r
785         CRYPT_ArcFourCrypt(context, dest_buf.GetBuffer() + old_size, src_size);\r
786         return TRUE;\r
787     }\r
788     AESCryptContext* pContext = (AESCryptContext*)context;\r
789     if (pContext->m_bIV && bEncrypt) {\r
790         dest_buf.AppendBlock(pContext->m_Block, 16);\r
791         pContext->m_bIV = FALSE;\r
792     }\r
793     FX_DWORD src_off = 0;\r
794     FX_DWORD src_left = src_size;\r
795     while (1) {\r
796         FX_DWORD copy_size = 16 - pContext->m_BlockOffset;\r
797         if (copy_size > src_left) {\r
798             copy_size = src_left;\r
799         }\r
800         FXSYS_memcpy32(pContext->m_Block + pContext->m_BlockOffset, src_buf + src_off, copy_size);\r
801         src_off += copy_size;\r
802         src_left -= copy_size;\r
803         pContext->m_BlockOffset += copy_size;\r
804         if (pContext->m_BlockOffset == 16) {\r
805             if (!bEncrypt && pContext->m_bIV) {\r
806                 CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block);\r
807                 pContext->m_bIV = FALSE;\r
808                 pContext->m_BlockOffset = 0;\r
809             } else if (src_off < src_size) {\r
810                 FX_BYTE block_buf[16];\r
811                 if (bEncrypt) {\r
812                     CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16);\r
813                 } else {\r
814                     CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, 16);\r
815                 }\r
816                 dest_buf.AppendBlock(block_buf, 16);\r
817                 pContext->m_BlockOffset = 0;\r
818             }\r
819         }\r
820         if (!src_left) {\r
821             break;\r
822         }\r
823     }\r
824     return TRUE;\r
825 }\r
826 FX_BOOL CPDF_StandardCryptoHandler::CryptFinish(FX_LPVOID context, CFX_BinaryBuf& dest_buf, FX_BOOL bEncrypt)\r
827 {\r
828     if (!context) {\r
829         return FALSE;\r
830     }\r
831     if (m_Cipher == FXCIPHER_NONE) {\r
832         return TRUE;\r
833     }\r
834     if (m_Cipher == FXCIPHER_RC4) {\r
835         FX_Free(context);\r
836         return TRUE;\r
837     }\r
838     AESCryptContext* pContext = (AESCryptContext*)context;\r
839     if (bEncrypt) {\r
840         FX_BYTE block_buf[16];\r
841         if (pContext->m_BlockOffset == 16) {\r
842             CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16);\r
843             dest_buf.AppendBlock(block_buf, 16);\r
844             pContext->m_BlockOffset = 0;\r
845         }\r
846         FXSYS_memset8(pContext->m_Block + pContext->m_BlockOffset, (FX_BYTE)(16 - pContext->m_BlockOffset), 16 - pContext->m_BlockOffset);\r
847         CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16);\r
848         dest_buf.AppendBlock(block_buf, 16);\r
849     } else if (pContext->m_BlockOffset == 16) {\r
850         FX_BYTE block_buf[16];\r
851         CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, 16);\r
852         if (block_buf[15] <= 16) {\r
853             dest_buf.AppendBlock(block_buf, 16 - block_buf[15]);\r
854         }\r
855     }\r
856     FX_Free(pContext);\r
857     return TRUE;\r
858 }\r
859 FX_LPVOID CPDF_StandardCryptoHandler::DecryptStart(FX_DWORD objnum, FX_DWORD gennum)\r
860 {\r
861     return CryptStart(objnum, gennum, FALSE);\r
862 }\r
863 FX_DWORD CPDF_StandardCryptoHandler::DecryptGetSize(FX_DWORD src_size)\r
864 {\r
865     return m_Cipher == FXCIPHER_AES ? src_size - 16 : src_size;\r
866 }\r
867 FX_BOOL CPDF_StandardCryptoHandler::Init(CPDF_Dictionary* pEncryptDict, CPDF_SecurityHandler* pSecurityHandler)\r
868 {\r
869     FX_LPCBYTE key;\r
870     if (!pSecurityHandler->GetCryptInfo(m_Cipher, key, m_KeyLen)) {\r
871         return FALSE;\r
872     }\r
873     if (m_KeyLen > 32 || m_KeyLen < 0) {\r
874         return FALSE;\r
875     }\r
876     if (m_Cipher != FXCIPHER_NONE) {\r
877         FXSYS_memcpy32(m_EncryptKey, key, m_KeyLen);\r
878     }\r
879     if (m_Cipher == FXCIPHER_AES) {\r
880         m_pAESContext = FX_Alloc(FX_BYTE, 2048);\r
881     }\r
882     return TRUE;\r
883 }\r
884 FX_BOOL CPDF_StandardCryptoHandler::Init(int cipher, FX_LPCBYTE key, int keylen)\r
885 {\r
886     if (cipher == FXCIPHER_AES) {\r
887         switch(keylen) {\r
888             case 16:\r
889             case 24:\r
890             case 32:\r
891                 break;\r
892             default:\r
893                 return FALSE;\r
894         }\r
895     } else if (cipher == FXCIPHER_AES2) {\r
896         if (keylen != 32) {\r
897             return FALSE;\r
898         }\r
899     } else if (cipher == FXCIPHER_RC4) {\r
900         if (keylen < 5 || keylen > 16) {\r
901             return FALSE;\r
902         }\r
903     } else {\r
904         if (keylen > 32) {\r
905             keylen = 32;\r
906         }\r
907     }\r
908     m_Cipher = cipher;\r
909     m_KeyLen = keylen;\r
910     FXSYS_memcpy32(m_EncryptKey, key, keylen);\r
911     if (m_Cipher == FXCIPHER_AES) {\r
912         m_pAESContext = FX_Alloc(FX_BYTE, 2048);\r
913     }\r
914     return TRUE;\r
915 }\r
916 FX_BOOL CPDF_StandardCryptoHandler::DecryptStream(FX_LPVOID context, FX_LPCBYTE src_buf, FX_DWORD src_size,\r
917         CFX_BinaryBuf& dest_buf)\r
918 {\r
919     return CryptStream(context, src_buf, src_size, dest_buf, FALSE);\r
920 }\r
921 FX_BOOL CPDF_StandardCryptoHandler::DecryptFinish(FX_LPVOID context, CFX_BinaryBuf& dest_buf)\r
922 {\r
923     return CryptFinish(context, dest_buf, FALSE);\r
924 }\r
925 FX_DWORD CPDF_StandardCryptoHandler::EncryptGetSize(FX_DWORD objnum, FX_DWORD version, FX_LPCBYTE src_buf, FX_DWORD src_size)\r
926 {\r
927     if (m_Cipher == FXCIPHER_AES) {\r
928         return src_size + 32;\r
929     }\r
930     return src_size;\r
931 }\r
932 FX_BOOL CPDF_StandardCryptoHandler::EncryptContent(FX_DWORD objnum, FX_DWORD gennum, FX_LPCBYTE src_buf, FX_DWORD src_size,\r
933         FX_LPBYTE dest_buf, FX_DWORD& dest_size)\r
934 {\r
935     CryptBlock(TRUE, objnum, gennum, src_buf, src_size, dest_buf, dest_size);\r
936     return TRUE;\r
937 }\r
938 void CPDF_CryptoHandler::Decrypt(FX_DWORD objnum, FX_DWORD gennum, CFX_ByteString& str)\r
939 {\r
940     CFX_BinaryBuf dest_buf;\r
941     FX_LPVOID context = DecryptStart(objnum, gennum);\r
942     DecryptStream(context, (FX_LPCBYTE)str, str.GetLength(), dest_buf);\r
943     DecryptFinish(context, dest_buf);\r
944     str = dest_buf;\r
945 }\r
946 CPDF_StandardCryptoHandler::CPDF_StandardCryptoHandler()\r
947 {\r
948     m_pAESContext = NULL;\r
949     m_Cipher = FXCIPHER_NONE;\r
950     m_KeyLen = 0;\r
951 }\r
952 CPDF_StandardCryptoHandler::~CPDF_StandardCryptoHandler()\r
953 {\r
954     if (m_pAESContext) {\r
955         FX_Free(m_pAESContext);\r
956     }\r
957 }\r