OLD | NEW |
| (Empty) |
1 // Copyright 2014 PDFium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
6 | |
7 #include "core/fpdfapi/fpdf_parser/cpdf_crypto_handler.h" | |
8 | |
9 #include <time.h> | |
10 | |
11 #include "core/fdrm/crypto/fx_crypt.h" | |
12 #include "core/fpdfapi/fpdf_parser/cpdf_parser.h" | |
13 #include "core/fpdfapi/fpdf_parser/cpdf_security_handler.h" | |
14 #include "core/fpdfapi/fpdf_parser/cpdf_simple_parser.h" | |
15 | |
16 void CPDF_CryptoHandler::CryptBlock(FX_BOOL bEncrypt, | |
17 uint32_t objnum, | |
18 uint32_t gennum, | |
19 const uint8_t* src_buf, | |
20 uint32_t src_size, | |
21 uint8_t* dest_buf, | |
22 uint32_t& dest_size) { | |
23 if (m_Cipher == FXCIPHER_NONE) { | |
24 FXSYS_memcpy(dest_buf, src_buf, src_size); | |
25 return; | |
26 } | |
27 uint8_t realkey[16]; | |
28 int realkeylen = 16; | |
29 if (m_Cipher != FXCIPHER_AES || m_KeyLen != 32) { | |
30 uint8_t key1[32]; | |
31 PopulateKey(objnum, gennum, key1); | |
32 | |
33 if (m_Cipher == FXCIPHER_AES) { | |
34 FXSYS_memcpy(key1 + m_KeyLen + 5, "sAlT", 4); | |
35 } | |
36 CRYPT_MD5Generate( | |
37 key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey); | |
38 realkeylen = m_KeyLen + 5; | |
39 if (realkeylen > 16) { | |
40 realkeylen = 16; | |
41 } | |
42 } | |
43 if (m_Cipher == FXCIPHER_AES) { | |
44 CRYPT_AESSetKey(m_pAESContext, 16, m_KeyLen == 32 ? m_EncryptKey : realkey, | |
45 m_KeyLen, bEncrypt); | |
46 if (bEncrypt) { | |
47 uint8_t iv[16]; | |
48 for (int i = 0; i < 16; i++) { | |
49 iv[i] = (uint8_t)rand(); | |
50 } | |
51 CRYPT_AESSetIV(m_pAESContext, iv); | |
52 FXSYS_memcpy(dest_buf, iv, 16); | |
53 int nblocks = src_size / 16; | |
54 CRYPT_AESEncrypt(m_pAESContext, dest_buf + 16, src_buf, nblocks * 16); | |
55 uint8_t padding[16]; | |
56 FXSYS_memcpy(padding, src_buf + nblocks * 16, src_size % 16); | |
57 FXSYS_memset(padding + src_size % 16, 16 - src_size % 16, | |
58 16 - src_size % 16); | |
59 CRYPT_AESEncrypt(m_pAESContext, dest_buf + nblocks * 16 + 16, padding, | |
60 16); | |
61 dest_size = 32 + nblocks * 16; | |
62 } else { | |
63 CRYPT_AESSetIV(m_pAESContext, src_buf); | |
64 CRYPT_AESDecrypt(m_pAESContext, dest_buf, src_buf + 16, src_size - 16); | |
65 dest_size = src_size - 16; | |
66 dest_size -= dest_buf[dest_size - 1]; | |
67 } | |
68 } else { | |
69 ASSERT(dest_size == src_size); | |
70 if (dest_buf != src_buf) { | |
71 FXSYS_memcpy(dest_buf, src_buf, src_size); | |
72 } | |
73 CRYPT_ArcFourCryptBlock(dest_buf, dest_size, realkey, realkeylen); | |
74 } | |
75 } | |
76 | |
77 struct AESCryptContext { | |
78 uint8_t m_Context[2048]; | |
79 FX_BOOL m_bIV; | |
80 uint8_t m_Block[16]; | |
81 uint32_t m_BlockOffset; | |
82 }; | |
83 | |
84 void* CPDF_CryptoHandler::CryptStart(uint32_t objnum, | |
85 uint32_t gennum, | |
86 FX_BOOL bEncrypt) { | |
87 if (m_Cipher == FXCIPHER_NONE) { | |
88 return this; | |
89 } | |
90 if (m_Cipher == FXCIPHER_AES && m_KeyLen == 32) { | |
91 AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1); | |
92 pContext->m_bIV = TRUE; | |
93 pContext->m_BlockOffset = 0; | |
94 CRYPT_AESSetKey(pContext->m_Context, 16, m_EncryptKey, 32, bEncrypt); | |
95 if (bEncrypt) { | |
96 for (int i = 0; i < 16; i++) { | |
97 pContext->m_Block[i] = (uint8_t)rand(); | |
98 } | |
99 CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); | |
100 } | |
101 return pContext; | |
102 } | |
103 uint8_t key1[48]; | |
104 PopulateKey(objnum, gennum, key1); | |
105 | |
106 if (m_Cipher == FXCIPHER_AES) { | |
107 FXSYS_memcpy(key1 + m_KeyLen + 5, "sAlT", 4); | |
108 } | |
109 uint8_t realkey[16]; | |
110 CRYPT_MD5Generate( | |
111 key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey); | |
112 int realkeylen = m_KeyLen + 5; | |
113 if (realkeylen > 16) { | |
114 realkeylen = 16; | |
115 } | |
116 if (m_Cipher == FXCIPHER_AES) { | |
117 AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1); | |
118 pContext->m_bIV = TRUE; | |
119 pContext->m_BlockOffset = 0; | |
120 CRYPT_AESSetKey(pContext->m_Context, 16, realkey, 16, bEncrypt); | |
121 if (bEncrypt) { | |
122 for (int i = 0; i < 16; i++) { | |
123 pContext->m_Block[i] = (uint8_t)rand(); | |
124 } | |
125 CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); | |
126 } | |
127 return pContext; | |
128 } | |
129 void* pContext = FX_Alloc(uint8_t, 1040); | |
130 CRYPT_ArcFourSetup(pContext, realkey, realkeylen); | |
131 return pContext; | |
132 } | |
133 | |
134 FX_BOOL CPDF_CryptoHandler::CryptStream(void* context, | |
135 const uint8_t* src_buf, | |
136 uint32_t src_size, | |
137 CFX_BinaryBuf& dest_buf, | |
138 FX_BOOL bEncrypt) { | |
139 if (!context) { | |
140 return FALSE; | |
141 } | |
142 if (m_Cipher == FXCIPHER_NONE) { | |
143 dest_buf.AppendBlock(src_buf, src_size); | |
144 return TRUE; | |
145 } | |
146 if (m_Cipher == FXCIPHER_RC4) { | |
147 int old_size = dest_buf.GetSize(); | |
148 dest_buf.AppendBlock(src_buf, src_size); | |
149 CRYPT_ArcFourCrypt(context, dest_buf.GetBuffer() + old_size, src_size); | |
150 return TRUE; | |
151 } | |
152 AESCryptContext* pContext = (AESCryptContext*)context; | |
153 if (pContext->m_bIV && bEncrypt) { | |
154 dest_buf.AppendBlock(pContext->m_Block, 16); | |
155 pContext->m_bIV = FALSE; | |
156 } | |
157 uint32_t src_off = 0; | |
158 uint32_t src_left = src_size; | |
159 while (1) { | |
160 uint32_t copy_size = 16 - pContext->m_BlockOffset; | |
161 if (copy_size > src_left) { | |
162 copy_size = src_left; | |
163 } | |
164 FXSYS_memcpy(pContext->m_Block + pContext->m_BlockOffset, src_buf + src_off, | |
165 copy_size); | |
166 src_off += copy_size; | |
167 src_left -= copy_size; | |
168 pContext->m_BlockOffset += copy_size; | |
169 if (pContext->m_BlockOffset == 16) { | |
170 if (!bEncrypt && pContext->m_bIV) { | |
171 CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); | |
172 pContext->m_bIV = FALSE; | |
173 pContext->m_BlockOffset = 0; | |
174 } else if (src_off < src_size) { | |
175 uint8_t block_buf[16]; | |
176 if (bEncrypt) { | |
177 CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, | |
178 16); | |
179 } else { | |
180 CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, | |
181 16); | |
182 } | |
183 dest_buf.AppendBlock(block_buf, 16); | |
184 pContext->m_BlockOffset = 0; | |
185 } | |
186 } | |
187 if (!src_left) { | |
188 break; | |
189 } | |
190 } | |
191 return TRUE; | |
192 } | |
193 FX_BOOL CPDF_CryptoHandler::CryptFinish(void* context, | |
194 CFX_BinaryBuf& dest_buf, | |
195 FX_BOOL bEncrypt) { | |
196 if (!context) { | |
197 return FALSE; | |
198 } | |
199 if (m_Cipher == FXCIPHER_NONE) { | |
200 return TRUE; | |
201 } | |
202 if (m_Cipher == FXCIPHER_RC4) { | |
203 FX_Free(context); | |
204 return TRUE; | |
205 } | |
206 AESCryptContext* pContext = (AESCryptContext*)context; | |
207 if (bEncrypt) { | |
208 uint8_t block_buf[16]; | |
209 if (pContext->m_BlockOffset == 16) { | |
210 CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); | |
211 dest_buf.AppendBlock(block_buf, 16); | |
212 pContext->m_BlockOffset = 0; | |
213 } | |
214 FXSYS_memset(pContext->m_Block + pContext->m_BlockOffset, | |
215 (uint8_t)(16 - pContext->m_BlockOffset), | |
216 16 - pContext->m_BlockOffset); | |
217 CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); | |
218 dest_buf.AppendBlock(block_buf, 16); | |
219 } else if (pContext->m_BlockOffset == 16) { | |
220 uint8_t block_buf[16]; | |
221 CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); | |
222 if (block_buf[15] <= 16) { | |
223 dest_buf.AppendBlock(block_buf, 16 - block_buf[15]); | |
224 } | |
225 } | |
226 FX_Free(pContext); | |
227 return TRUE; | |
228 } | |
229 | |
230 void CPDF_CryptoHandler::Decrypt(uint32_t objnum, | |
231 uint32_t gennum, | |
232 CFX_ByteString& str) { | |
233 CFX_BinaryBuf dest_buf; | |
234 void* context = DecryptStart(objnum, gennum); | |
235 DecryptStream(context, str.raw_str(), str.GetLength(), dest_buf); | |
236 DecryptFinish(context, dest_buf); | |
237 str = CFX_ByteString(dest_buf.GetBuffer(), dest_buf.GetSize()); | |
238 } | |
239 | |
240 void* CPDF_CryptoHandler::DecryptStart(uint32_t objnum, uint32_t gennum) { | |
241 return CryptStart(objnum, gennum, FALSE); | |
242 } | |
243 uint32_t CPDF_CryptoHandler::DecryptGetSize(uint32_t src_size) { | |
244 return m_Cipher == FXCIPHER_AES ? src_size - 16 : src_size; | |
245 } | |
246 | |
247 FX_BOOL CPDF_CryptoHandler::Init(CPDF_Dictionary* pEncryptDict, | |
248 CPDF_SecurityHandler* pSecurityHandler) { | |
249 const uint8_t* key; | |
250 if (!pSecurityHandler->GetCryptInfo(m_Cipher, key, m_KeyLen)) { | |
251 return FALSE; | |
252 } | |
253 if (m_KeyLen > 32 || m_KeyLen < 0) { | |
254 return FALSE; | |
255 } | |
256 if (m_Cipher != FXCIPHER_NONE) { | |
257 FXSYS_memcpy(m_EncryptKey, key, m_KeyLen); | |
258 } | |
259 if (m_Cipher == FXCIPHER_AES) { | |
260 m_pAESContext = FX_Alloc(uint8_t, 2048); | |
261 } | |
262 return TRUE; | |
263 } | |
264 | |
265 FX_BOOL CPDF_CryptoHandler::Init(int cipher, const uint8_t* key, int keylen) { | |
266 if (cipher == FXCIPHER_AES) { | |
267 switch (keylen) { | |
268 case 16: | |
269 case 24: | |
270 case 32: | |
271 break; | |
272 default: | |
273 return FALSE; | |
274 } | |
275 } else if (cipher == FXCIPHER_AES2) { | |
276 if (keylen != 32) { | |
277 return FALSE; | |
278 } | |
279 } else if (cipher == FXCIPHER_RC4) { | |
280 if (keylen < 5 || keylen > 16) { | |
281 return FALSE; | |
282 } | |
283 } else { | |
284 if (keylen > 32) { | |
285 keylen = 32; | |
286 } | |
287 } | |
288 m_Cipher = cipher; | |
289 m_KeyLen = keylen; | |
290 FXSYS_memcpy(m_EncryptKey, key, keylen); | |
291 if (m_Cipher == FXCIPHER_AES) { | |
292 m_pAESContext = FX_Alloc(uint8_t, 2048); | |
293 } | |
294 return TRUE; | |
295 } | |
296 FX_BOOL CPDF_CryptoHandler::DecryptStream(void* context, | |
297 const uint8_t* src_buf, | |
298 uint32_t src_size, | |
299 CFX_BinaryBuf& dest_buf) { | |
300 return CryptStream(context, src_buf, src_size, dest_buf, FALSE); | |
301 } | |
302 FX_BOOL CPDF_CryptoHandler::DecryptFinish(void* context, | |
303 CFX_BinaryBuf& dest_buf) { | |
304 return CryptFinish(context, dest_buf, FALSE); | |
305 } | |
306 uint32_t CPDF_CryptoHandler::EncryptGetSize(uint32_t objnum, | |
307 uint32_t version, | |
308 const uint8_t* src_buf, | |
309 uint32_t src_size) { | |
310 if (m_Cipher == FXCIPHER_AES) { | |
311 return src_size + 32; | |
312 } | |
313 return src_size; | |
314 } | |
315 FX_BOOL CPDF_CryptoHandler::EncryptContent(uint32_t objnum, | |
316 uint32_t gennum, | |
317 const uint8_t* src_buf, | |
318 uint32_t src_size, | |
319 uint8_t* dest_buf, | |
320 uint32_t& dest_size) { | |
321 CryptBlock(TRUE, objnum, gennum, src_buf, src_size, dest_buf, dest_size); | |
322 return TRUE; | |
323 } | |
324 CPDF_CryptoHandler::CPDF_CryptoHandler() { | |
325 m_pAESContext = nullptr; | |
326 m_Cipher = FXCIPHER_NONE; | |
327 m_KeyLen = 0; | |
328 } | |
329 CPDF_CryptoHandler::~CPDF_CryptoHandler() { | |
330 FX_Free(m_pAESContext); | |
331 } | |
332 | |
333 void CPDF_CryptoHandler::PopulateKey(uint32_t objnum, | |
334 uint32_t gennum, | |
335 uint8_t* key) { | |
336 FXSYS_memcpy(key, m_EncryptKey, m_KeyLen); | |
337 key[m_KeyLen + 0] = (uint8_t)objnum; | |
338 key[m_KeyLen + 1] = (uint8_t)(objnum >> 8); | |
339 key[m_KeyLen + 2] = (uint8_t)(objnum >> 16); | |
340 key[m_KeyLen + 3] = (uint8_t)gennum; | |
341 key[m_KeyLen + 4] = (uint8_t)(gennum >> 8); | |
342 } | |
OLD | NEW |