Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(311)

Side by Side Diff: core/fpdfapi/fpdf_parser/cpdf_security_handler.cpp

Issue 2392603004: Move core/fpdfapi/fpdf_parser to core/fpdfapi/parser (Closed)
Patch Set: Rebase to master Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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_security_handler.h"
8
9 #include <time.h>
10
11 #include "core/fdrm/crypto/fx_crypt.h"
12 #include "core/fpdfapi/fpdf_parser/cpdf_array.h"
13 #include "core/fpdfapi/fpdf_parser/cpdf_crypto_handler.h"
14 #include "core/fpdfapi/fpdf_parser/cpdf_dictionary.h"
15 #include "core/fpdfapi/fpdf_parser/cpdf_object.h"
16 #include "core/fpdfapi/fpdf_parser/cpdf_parser.h"
17
18 namespace {
19
20 const uint8_t defpasscode[32] = {
21 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e,
22 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68,
23 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a};
24
25 void CalcEncryptKey(CPDF_Dictionary* pEncrypt,
26 const uint8_t* password,
27 uint32_t pass_size,
28 uint8_t* key,
29 int keylen,
30 FX_BOOL bIgnoreMeta,
31 CPDF_Array* pIdArray) {
32 int revision = pEncrypt->GetIntegerFor("R");
33 uint8_t passcode[32];
34 for (uint32_t i = 0; i < 32; i++) {
35 passcode[i] = i < pass_size ? password[i] : defpasscode[i - pass_size];
36 }
37 uint8_t md5[100];
38 CRYPT_MD5Start(md5);
39 CRYPT_MD5Update(md5, passcode, 32);
40 CFX_ByteString okey = pEncrypt->GetStringFor("O");
41 CRYPT_MD5Update(md5, (uint8_t*)okey.c_str(), okey.GetLength());
42 uint32_t perm = pEncrypt->GetIntegerFor("P");
43 CRYPT_MD5Update(md5, (uint8_t*)&perm, 4);
44 if (pIdArray) {
45 CFX_ByteString id = pIdArray->GetStringAt(0);
46 CRYPT_MD5Update(md5, (uint8_t*)id.c_str(), id.GetLength());
47 }
48 if (!bIgnoreMeta && revision >= 3 &&
49 !pEncrypt->GetIntegerFor("EncryptMetadata", 1)) {
50 uint32_t tag = (uint32_t)-1;
51 CRYPT_MD5Update(md5, (uint8_t*)&tag, 4);
52 }
53 uint8_t digest[16];
54 CRYPT_MD5Finish(md5, digest);
55 uint32_t copy_len = keylen;
56 if (copy_len > sizeof(digest)) {
57 copy_len = sizeof(digest);
58 }
59 if (revision >= 3) {
60 for (int i = 0; i < 50; i++) {
61 CRYPT_MD5Generate(digest, copy_len, digest);
62 }
63 }
64 FXSYS_memset(key, 0, keylen);
65 FXSYS_memcpy(key, digest, copy_len);
66 }
67
68 } // namespace
69
70 CPDF_SecurityHandler::CPDF_SecurityHandler()
71 : m_Version(0),
72 m_Revision(0),
73 m_pParser(nullptr),
74 m_pEncryptDict(nullptr),
75 m_Permissions(0),
76 m_Cipher(FXCIPHER_NONE),
77 m_KeyLen(0),
78 m_bOwnerUnlocked(false) {}
79
80 CPDF_SecurityHandler::~CPDF_SecurityHandler() {}
81
82 CPDF_CryptoHandler* CPDF_SecurityHandler::CreateCryptoHandler() {
83 return new CPDF_CryptoHandler;
84 }
85
86 FX_BOOL CPDF_SecurityHandler::OnInit(CPDF_Parser* pParser,
87 CPDF_Dictionary* pEncryptDict) {
88 m_pParser = pParser;
89 if (!LoadDict(pEncryptDict)) {
90 return FALSE;
91 }
92 if (m_Cipher == FXCIPHER_NONE) {
93 return TRUE;
94 }
95 return CheckSecurity(m_KeyLen);
96 }
97
98 FX_BOOL CPDF_SecurityHandler::CheckSecurity(int32_t key_len) {
99 CFX_ByteString password = m_pParser->GetPassword();
100 if (!password.IsEmpty() &&
101 CheckPassword(password.raw_str(), password.GetLength(), TRUE,
102 m_EncryptKey, key_len)) {
103 m_bOwnerUnlocked = true;
104 return TRUE;
105 }
106 return CheckPassword(password.raw_str(), password.GetLength(), FALSE,
107 m_EncryptKey, key_len);
108 }
109
110 uint32_t CPDF_SecurityHandler::GetPermissions() {
111 return m_bOwnerUnlocked ? 0xFFFFFFFF : m_Permissions;
112 }
113
114 static FX_BOOL LoadCryptInfo(CPDF_Dictionary* pEncryptDict,
115 const CFX_ByteString& name,
116 int& cipher,
117 int& keylen) {
118 int Version = pEncryptDict->GetIntegerFor("V");
119 cipher = FXCIPHER_RC4;
120 keylen = 0;
121 if (Version >= 4) {
122 CPDF_Dictionary* pCryptFilters = pEncryptDict->GetDictFor("CF");
123 if (!pCryptFilters) {
124 return FALSE;
125 }
126 if (name == "Identity") {
127 cipher = FXCIPHER_NONE;
128 } else {
129 CPDF_Dictionary* pDefFilter = pCryptFilters->GetDictFor(name);
130 if (!pDefFilter) {
131 return FALSE;
132 }
133 int nKeyBits = 0;
134 if (Version == 4) {
135 nKeyBits = pDefFilter->GetIntegerFor("Length", 0);
136 if (nKeyBits == 0) {
137 nKeyBits = pEncryptDict->GetIntegerFor("Length", 128);
138 }
139 } else {
140 nKeyBits = pEncryptDict->GetIntegerFor("Length", 256);
141 }
142 if (nKeyBits < 40) {
143 nKeyBits *= 8;
144 }
145 keylen = nKeyBits / 8;
146 CFX_ByteString cipher_name = pDefFilter->GetStringFor("CFM");
147 if (cipher_name == "AESV2" || cipher_name == "AESV3") {
148 cipher = FXCIPHER_AES;
149 }
150 }
151 } else {
152 keylen = Version > 1 ? pEncryptDict->GetIntegerFor("Length", 40) / 8 : 5;
153 }
154 if (keylen > 32 || keylen < 0) {
155 return FALSE;
156 }
157 return TRUE;
158 }
159
160 FX_BOOL CPDF_SecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict) {
161 m_pEncryptDict = pEncryptDict;
162 m_Version = pEncryptDict->GetIntegerFor("V");
163 m_Revision = pEncryptDict->GetIntegerFor("R");
164 m_Permissions = pEncryptDict->GetIntegerFor("P", -1);
165 if (m_Version < 4)
166 return LoadCryptInfo(pEncryptDict, CFX_ByteString(), m_Cipher, m_KeyLen);
167
168 CFX_ByteString stmf_name = pEncryptDict->GetStringFor("StmF");
169 CFX_ByteString strf_name = pEncryptDict->GetStringFor("StrF");
170 if (stmf_name != strf_name)
171 return FALSE;
172
173 return LoadCryptInfo(pEncryptDict, strf_name, m_Cipher, m_KeyLen);
174 }
175
176 FX_BOOL CPDF_SecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict,
177 uint32_t type,
178 int& cipher,
179 int& key_len) {
180 m_pEncryptDict = pEncryptDict;
181 m_Version = pEncryptDict->GetIntegerFor("V");
182 m_Revision = pEncryptDict->GetIntegerFor("R");
183 m_Permissions = pEncryptDict->GetIntegerFor("P", -1);
184
185 CFX_ByteString strf_name;
186 CFX_ByteString stmf_name;
187 if (m_Version >= 4) {
188 stmf_name = pEncryptDict->GetStringFor("StmF");
189 strf_name = pEncryptDict->GetStringFor("StrF");
190 if (stmf_name != strf_name)
191 return FALSE;
192 }
193 if (!LoadCryptInfo(pEncryptDict, strf_name, cipher, key_len))
194 return FALSE;
195
196 m_Cipher = cipher;
197 m_KeyLen = key_len;
198 return TRUE;
199 }
200
201 FX_BOOL CPDF_SecurityHandler::GetCryptInfo(int& cipher,
202 const uint8_t*& buffer,
203 int& keylen) {
204 cipher = m_Cipher;
205 buffer = m_EncryptKey;
206 keylen = m_KeyLen;
207 return TRUE;
208 }
209 #define FX_GET_32WORD(n, b, i) \
210 { \
211 (n) = (uint32_t)( \
212 ((uint64_t)(b)[(i)] << 24) | ((uint64_t)(b)[(i) + 1] << 16) | \
213 ((uint64_t)(b)[(i) + 2] << 8) | ((uint64_t)(b)[(i) + 3])); \
214 }
215 int BigOrder64BitsMod3(uint8_t* data) {
216 uint64_t ret = 0;
217 for (int i = 0; i < 4; ++i) {
218 uint32_t value;
219 FX_GET_32WORD(value, data, 4 * i);
220 ret <<= 32;
221 ret |= value;
222 ret %= 3;
223 }
224 return (int)ret;
225 }
226 void Revision6_Hash(const uint8_t* password,
227 uint32_t size,
228 const uint8_t* salt,
229 const uint8_t* vector,
230 uint8_t* hash) {
231 int iBlockSize = 32;
232 uint8_t sha[128];
233 CRYPT_SHA256Start(sha);
234 CRYPT_SHA256Update(sha, password, size);
235 CRYPT_SHA256Update(sha, salt, 8);
236 if (vector) {
237 CRYPT_SHA256Update(sha, vector, 48);
238 }
239 uint8_t digest[32];
240 CRYPT_SHA256Finish(sha, digest);
241 CFX_ByteTextBuf buf;
242 uint8_t* input = digest;
243 uint8_t* key = input;
244 uint8_t* iv = input + 16;
245 uint8_t* E = buf.GetBuffer();
246 int iBufLen = buf.GetLength();
247 CFX_ByteTextBuf interDigest;
248 int i = 0;
249 uint8_t* aes = FX_Alloc(uint8_t, 2048);
250 while (i < 64 || i < E[iBufLen - 1] + 32) {
251 int iRoundSize = size + iBlockSize;
252 if (vector) {
253 iRoundSize += 48;
254 }
255 iBufLen = iRoundSize * 64;
256 buf.EstimateSize(iBufLen);
257 E = buf.GetBuffer();
258 CFX_ByteTextBuf content;
259 for (int j = 0; j < 64; ++j) {
260 content.AppendBlock(password, size);
261 content.AppendBlock(input, iBlockSize);
262 if (vector) {
263 content.AppendBlock(vector, 48);
264 }
265 }
266 CRYPT_AESSetKey(aes, 16, key, 16, TRUE);
267 CRYPT_AESSetIV(aes, iv);
268 CRYPT_AESEncrypt(aes, E, content.GetBuffer(), iBufLen);
269 int iHash = 0;
270 switch (BigOrder64BitsMod3(E)) {
271 case 0:
272 iHash = 0;
273 iBlockSize = 32;
274 break;
275 case 1:
276 iHash = 1;
277 iBlockSize = 48;
278 break;
279 default:
280 iHash = 2;
281 iBlockSize = 64;
282 break;
283 }
284 interDigest.EstimateSize(iBlockSize);
285 input = interDigest.GetBuffer();
286 if (iHash == 0) {
287 CRYPT_SHA256Generate(E, iBufLen, input);
288 } else if (iHash == 1) {
289 CRYPT_SHA384Generate(E, iBufLen, input);
290 } else if (iHash == 2) {
291 CRYPT_SHA512Generate(E, iBufLen, input);
292 }
293 key = input;
294 iv = input + 16;
295 ++i;
296 }
297 FX_Free(aes);
298 if (hash) {
299 FXSYS_memcpy(hash, input, 32);
300 }
301 }
302 FX_BOOL CPDF_SecurityHandler::AES256_CheckPassword(const uint8_t* password,
303 uint32_t size,
304 FX_BOOL bOwner,
305 uint8_t* key) {
306 CFX_ByteString okey =
307 m_pEncryptDict ? m_pEncryptDict->GetStringFor("O") : CFX_ByteString();
308 if (okey.GetLength() < 48) {
309 return FALSE;
310 }
311 CFX_ByteString ukey =
312 m_pEncryptDict ? m_pEncryptDict->GetStringFor("U") : CFX_ByteString();
313 if (ukey.GetLength() < 48) {
314 return FALSE;
315 }
316 const uint8_t* pkey = (bOwner ? okey : ukey).raw_str();
317 uint8_t sha[128];
318 uint8_t digest[32];
319 if (m_Revision >= 6) {
320 Revision6_Hash(password, size, (const uint8_t*)pkey + 32,
321 bOwner ? ukey.raw_str() : nullptr, digest);
322 } else {
323 CRYPT_SHA256Start(sha);
324 CRYPT_SHA256Update(sha, password, size);
325 CRYPT_SHA256Update(sha, pkey + 32, 8);
326 if (bOwner) {
327 CRYPT_SHA256Update(sha, ukey.raw_str(), 48);
328 }
329 CRYPT_SHA256Finish(sha, digest);
330 }
331 if (FXSYS_memcmp(digest, pkey, 32) != 0) {
332 return FALSE;
333 }
334 if (!key) {
335 return TRUE;
336 }
337 if (m_Revision >= 6) {
338 Revision6_Hash(password, size, (const uint8_t*)pkey + 40,
339 bOwner ? ukey.raw_str() : nullptr, digest);
340 } else {
341 CRYPT_SHA256Start(sha);
342 CRYPT_SHA256Update(sha, password, size);
343 CRYPT_SHA256Update(sha, pkey + 40, 8);
344 if (bOwner) {
345 CRYPT_SHA256Update(sha, ukey.raw_str(), 48);
346 }
347 CRYPT_SHA256Finish(sha, digest);
348 }
349 CFX_ByteString ekey = m_pEncryptDict
350 ? m_pEncryptDict->GetStringFor(bOwner ? "OE" : "UE")
351 : CFX_ByteString();
352 if (ekey.GetLength() < 32) {
353 return FALSE;
354 }
355 uint8_t* aes = FX_Alloc(uint8_t, 2048);
356 CRYPT_AESSetKey(aes, 16, digest, 32, FALSE);
357 uint8_t iv[16];
358 FXSYS_memset(iv, 0, 16);
359 CRYPT_AESSetIV(aes, iv);
360 CRYPT_AESDecrypt(aes, key, ekey.raw_str(), 32);
361 CRYPT_AESSetKey(aes, 16, key, 32, FALSE);
362 CRYPT_AESSetIV(aes, iv);
363 CFX_ByteString perms = m_pEncryptDict->GetStringFor("Perms");
364 if (perms.IsEmpty()) {
365 return FALSE;
366 }
367 uint8_t perms_buf[16];
368 FXSYS_memset(perms_buf, 0, sizeof(perms_buf));
369 uint32_t copy_len = sizeof(perms_buf);
370 if (copy_len > (uint32_t)perms.GetLength()) {
371 copy_len = perms.GetLength();
372 }
373 FXSYS_memcpy(perms_buf, perms.raw_str(), copy_len);
374 uint8_t buf[16];
375 CRYPT_AESDecrypt(aes, buf, perms_buf, 16);
376 FX_Free(aes);
377 if (buf[9] != 'a' || buf[10] != 'd' || buf[11] != 'b') {
378 return FALSE;
379 }
380 if (FXDWORD_GET_LSBFIRST(buf) != m_Permissions) {
381 return FALSE;
382 }
383 if ((buf[8] == 'T' && !IsMetadataEncrypted()) ||
384 (buf[8] == 'F' && IsMetadataEncrypted())) {
385 return FALSE;
386 }
387 return TRUE;
388 }
389
390 int CPDF_SecurityHandler::CheckPassword(const uint8_t* password,
391 uint32_t size,
392 FX_BOOL bOwner,
393 uint8_t* key,
394 int32_t key_len) {
395 if (m_Revision >= 5) {
396 return AES256_CheckPassword(password, size, bOwner, key);
397 }
398 uint8_t keybuf[32];
399 if (!key) {
400 key = keybuf;
401 }
402 if (bOwner) {
403 return CheckOwnerPassword(password, size, key, key_len);
404 }
405 return CheckUserPassword(password, size, FALSE, key, key_len) ||
406 CheckUserPassword(password, size, TRUE, key, key_len);
407 }
408 FX_BOOL CPDF_SecurityHandler::CheckUserPassword(const uint8_t* password,
409 uint32_t pass_size,
410 FX_BOOL bIgnoreEncryptMeta,
411 uint8_t* key,
412 int32_t key_len) {
413 CalcEncryptKey(m_pEncryptDict, password, pass_size, key, key_len,
414 bIgnoreEncryptMeta, m_pParser->GetIDArray());
415 CFX_ByteString ukey =
416 m_pEncryptDict ? m_pEncryptDict->GetStringFor("U") : CFX_ByteString();
417 if (ukey.GetLength() < 16) {
418 return FALSE;
419 }
420 uint8_t ukeybuf[32];
421 if (m_Revision == 2) {
422 FXSYS_memcpy(ukeybuf, defpasscode, 32);
423 CRYPT_ArcFourCryptBlock(ukeybuf, 32, key, key_len);
424 } else {
425 uint8_t test[32], tmpkey[32];
426 uint32_t copy_len = sizeof(test);
427 if (copy_len > (uint32_t)ukey.GetLength()) {
428 copy_len = ukey.GetLength();
429 }
430 FXSYS_memset(test, 0, sizeof(test));
431 FXSYS_memset(tmpkey, 0, sizeof(tmpkey));
432 FXSYS_memcpy(test, ukey.c_str(), copy_len);
433 for (int32_t i = 19; i >= 0; i--) {
434 for (int j = 0; j < key_len; j++)
435 tmpkey[j] = key[j] ^ static_cast<uint8_t>(i);
436 CRYPT_ArcFourCryptBlock(test, 32, tmpkey, key_len);
437 }
438 uint8_t md5[100];
439 CRYPT_MD5Start(md5);
440 CRYPT_MD5Update(md5, defpasscode, 32);
441 CPDF_Array* pIdArray = m_pParser->GetIDArray();
442 if (pIdArray) {
443 CFX_ByteString id = pIdArray->GetStringAt(0);
444 CRYPT_MD5Update(md5, (uint8_t*)id.c_str(), id.GetLength());
445 }
446 CRYPT_MD5Finish(md5, ukeybuf);
447 return FXSYS_memcmp(test, ukeybuf, 16) == 0;
448 }
449 if (FXSYS_memcmp((void*)ukey.c_str(), ukeybuf, 16) == 0) {
450 return TRUE;
451 }
452 return FALSE;
453 }
454 CFX_ByteString CPDF_SecurityHandler::GetUserPassword(const uint8_t* owner_pass,
455 uint32_t pass_size,
456 int32_t key_len) {
457 CFX_ByteString okey = m_pEncryptDict->GetStringFor("O");
458 uint8_t passcode[32];
459 for (uint32_t i = 0; i < 32; i++) {
460 passcode[i] = i < pass_size ? owner_pass[i] : defpasscode[i - pass_size];
461 }
462 uint8_t digest[16];
463 CRYPT_MD5Generate(passcode, 32, digest);
464 if (m_Revision >= 3) {
465 for (uint32_t i = 0; i < 50; i++) {
466 CRYPT_MD5Generate(digest, 16, digest);
467 }
468 }
469 uint8_t enckey[32];
470 FXSYS_memset(enckey, 0, sizeof(enckey));
471 uint32_t copy_len = key_len;
472 if (copy_len > sizeof(digest)) {
473 copy_len = sizeof(digest);
474 }
475 FXSYS_memcpy(enckey, digest, copy_len);
476 int okeylen = okey.GetLength();
477 if (okeylen > 32) {
478 okeylen = 32;
479 }
480 uint8_t okeybuf[64];
481 FXSYS_memset(okeybuf, 0, sizeof(okeybuf));
482 FXSYS_memcpy(okeybuf, okey.c_str(), okeylen);
483 if (m_Revision == 2) {
484 CRYPT_ArcFourCryptBlock(okeybuf, okeylen, enckey, key_len);
485 } else {
486 for (int32_t i = 19; i >= 0; i--) {
487 uint8_t tempkey[32];
488 FXSYS_memset(tempkey, 0, sizeof(tempkey));
489 for (int j = 0; j < m_KeyLen; j++)
490 tempkey[j] = enckey[j] ^ static_cast<uint8_t>(i);
491 CRYPT_ArcFourCryptBlock(okeybuf, okeylen, tempkey, key_len);
492 }
493 }
494 int len = 32;
495 while (len && defpasscode[len - 1] == okeybuf[len - 1]) {
496 len--;
497 }
498 return CFX_ByteString(okeybuf, len);
499 }
500 FX_BOOL CPDF_SecurityHandler::CheckOwnerPassword(const uint8_t* password,
501 uint32_t pass_size,
502 uint8_t* key,
503 int32_t key_len) {
504 CFX_ByteString user_pass = GetUserPassword(password, pass_size, key_len);
505 if (CheckUserPassword(user_pass.raw_str(), user_pass.GetLength(), FALSE, key,
506 key_len)) {
507 return TRUE;
508 }
509 return CheckUserPassword(user_pass.raw_str(), user_pass.GetLength(), TRUE,
510 key, key_len);
511 }
512
513 bool CPDF_SecurityHandler::IsMetadataEncrypted() const {
514 return m_pEncryptDict->GetBooleanFor("EncryptMetadata", true);
515 }
516
517 void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict,
518 CPDF_Array* pIdArray,
519 const uint8_t* user_pass,
520 uint32_t user_size,
521 const uint8_t* owner_pass,
522 uint32_t owner_size,
523 FX_BOOL bDefault,
524 uint32_t type) {
525 int cipher = 0, key_len = 0;
526 if (!LoadDict(pEncryptDict, type, cipher, key_len)) {
527 return;
528 }
529 if (bDefault && (!owner_pass || owner_size == 0)) {
530 owner_pass = user_pass;
531 owner_size = user_size;
532 }
533 if (m_Revision >= 5) {
534 int t = (int)time(nullptr);
535 uint8_t sha[128];
536 CRYPT_SHA256Start(sha);
537 CRYPT_SHA256Update(sha, (uint8_t*)&t, sizeof t);
538 CRYPT_SHA256Update(sha, m_EncryptKey, 32);
539 CRYPT_SHA256Update(sha, (uint8_t*)"there", 5);
540 CRYPT_SHA256Finish(sha, m_EncryptKey);
541 AES256_SetPassword(pEncryptDict, user_pass, user_size, FALSE, m_EncryptKey);
542 if (bDefault) {
543 AES256_SetPassword(pEncryptDict, owner_pass, owner_size, TRUE,
544 m_EncryptKey);
545 AES256_SetPerms(pEncryptDict, m_Permissions,
546 pEncryptDict->GetBooleanFor("EncryptMetadata", true),
547 m_EncryptKey);
548 }
549 return;
550 }
551 if (bDefault) {
552 uint8_t passcode[32];
553 for (uint32_t i = 0; i < 32; i++) {
554 passcode[i] =
555 i < owner_size ? owner_pass[i] : defpasscode[i - owner_size];
556 }
557 uint8_t digest[16];
558 CRYPT_MD5Generate(passcode, 32, digest);
559 if (m_Revision >= 3) {
560 for (uint32_t i = 0; i < 50; i++)
561 CRYPT_MD5Generate(digest, 16, digest);
562 }
563 uint8_t enckey[32];
564 FXSYS_memcpy(enckey, digest, key_len);
565 for (uint32_t i = 0; i < 32; i++) {
566 passcode[i] = i < user_size ? user_pass[i] : defpasscode[i - user_size];
567 }
568 CRYPT_ArcFourCryptBlock(passcode, 32, enckey, key_len);
569 uint8_t tempkey[32];
570 if (m_Revision >= 3) {
571 for (uint8_t i = 1; i <= 19; i++) {
572 for (int j = 0; j < key_len; j++)
573 tempkey[j] = enckey[j] ^ i;
574 CRYPT_ArcFourCryptBlock(passcode, 32, tempkey, key_len);
575 }
576 }
577 pEncryptDict->SetStringFor("O", CFX_ByteString(passcode, 32));
578 }
579 CalcEncryptKey(m_pEncryptDict, (uint8_t*)user_pass, user_size, m_EncryptKey,
580 key_len, FALSE, pIdArray);
581 if (m_Revision < 3) {
582 uint8_t tempbuf[32];
583 FXSYS_memcpy(tempbuf, defpasscode, 32);
584 CRYPT_ArcFourCryptBlock(tempbuf, 32, m_EncryptKey, key_len);
585 pEncryptDict->SetStringFor("U", CFX_ByteString(tempbuf, 32));
586 } else {
587 uint8_t md5[100];
588 CRYPT_MD5Start(md5);
589 CRYPT_MD5Update(md5, defpasscode, 32);
590 if (pIdArray) {
591 CFX_ByteString id = pIdArray->GetStringAt(0);
592 CRYPT_MD5Update(md5, (uint8_t*)id.c_str(), id.GetLength());
593 }
594 uint8_t digest[32];
595 CRYPT_MD5Finish(md5, digest);
596 CRYPT_ArcFourCryptBlock(digest, 16, m_EncryptKey, key_len);
597 uint8_t tempkey[32];
598 for (uint8_t i = 1; i <= 19; i++) {
599 for (int j = 0; j < key_len; j++) {
600 tempkey[j] = m_EncryptKey[j] ^ i;
601 }
602 CRYPT_ArcFourCryptBlock(digest, 16, tempkey, key_len);
603 }
604 CRYPT_MD5Generate(digest, 16, digest + 16);
605 pEncryptDict->SetStringFor("U", CFX_ByteString(digest, 32));
606 }
607 }
608 void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict,
609 CPDF_Array* pIdArray,
610 const uint8_t* user_pass,
611 uint32_t user_size,
612 const uint8_t* owner_pass,
613 uint32_t owner_size,
614 uint32_t type) {
615 OnCreate(pEncryptDict, pIdArray, user_pass, user_size, owner_pass, owner_size,
616 TRUE, type);
617 }
618 void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict,
619 CPDF_Array* pIdArray,
620 const uint8_t* user_pass,
621 uint32_t user_size,
622 uint32_t type) {
623 OnCreate(pEncryptDict, pIdArray, user_pass, user_size, nullptr, 0, FALSE,
624 type);
625 }
626 void CPDF_SecurityHandler::AES256_SetPassword(CPDF_Dictionary* pEncryptDict,
627 const uint8_t* password,
628 uint32_t size,
629 FX_BOOL bOwner,
630 const uint8_t* key) {
631 uint8_t sha[128];
632 CRYPT_SHA1Start(sha);
633 CRYPT_SHA1Update(sha, key, 32);
634 CRYPT_SHA1Update(sha, (uint8_t*)"hello", 5);
635 uint8_t digest[20];
636 CRYPT_SHA1Finish(sha, digest);
637 CFX_ByteString ukey = pEncryptDict->GetStringFor("U");
638 uint8_t digest1[48];
639 if (m_Revision >= 6) {
640 Revision6_Hash(password, size, digest, bOwner ? ukey.raw_str() : nullptr,
641 digest1);
642 } else {
643 CRYPT_SHA256Start(sha);
644 CRYPT_SHA256Update(sha, password, size);
645 CRYPT_SHA256Update(sha, digest, 8);
646 if (bOwner) {
647 CRYPT_SHA256Update(sha, ukey.raw_str(), ukey.GetLength());
648 }
649 CRYPT_SHA256Finish(sha, digest1);
650 }
651 FXSYS_memcpy(digest1 + 32, digest, 16);
652 pEncryptDict->SetStringFor(bOwner ? "O" : "U", CFX_ByteString(digest1, 48));
653 if (m_Revision >= 6) {
654 Revision6_Hash(password, size, digest + 8,
655 bOwner ? ukey.raw_str() : nullptr, digest1);
656 } else {
657 CRYPT_SHA256Start(sha);
658 CRYPT_SHA256Update(sha, password, size);
659 CRYPT_SHA256Update(sha, digest + 8, 8);
660 if (bOwner) {
661 CRYPT_SHA256Update(sha, ukey.raw_str(), ukey.GetLength());
662 }
663 CRYPT_SHA256Finish(sha, digest1);
664 }
665 uint8_t* aes = FX_Alloc(uint8_t, 2048);
666 CRYPT_AESSetKey(aes, 16, digest1, 32, TRUE);
667 uint8_t iv[16];
668 FXSYS_memset(iv, 0, 16);
669 CRYPT_AESSetIV(aes, iv);
670 CRYPT_AESEncrypt(aes, digest1, key, 32);
671 FX_Free(aes);
672 pEncryptDict->SetStringFor(bOwner ? "OE" : "UE", CFX_ByteString(digest1, 32));
673 }
674 void CPDF_SecurityHandler::AES256_SetPerms(CPDF_Dictionary* pEncryptDict,
675 uint32_t permissions,
676 FX_BOOL bEncryptMetadata,
677 const uint8_t* key) {
678 uint8_t buf[16];
679 buf[0] = (uint8_t)permissions;
680 buf[1] = (uint8_t)(permissions >> 8);
681 buf[2] = (uint8_t)(permissions >> 16);
682 buf[3] = (uint8_t)(permissions >> 24);
683 buf[4] = 0xff;
684 buf[5] = 0xff;
685 buf[6] = 0xff;
686 buf[7] = 0xff;
687 buf[8] = bEncryptMetadata ? 'T' : 'F';
688 buf[9] = 'a';
689 buf[10] = 'd';
690 buf[11] = 'b';
691 uint8_t* aes = FX_Alloc(uint8_t, 2048);
692 CRYPT_AESSetKey(aes, 16, key, 32, TRUE);
693 uint8_t iv[16], buf1[16];
694 FXSYS_memset(iv, 0, 16);
695 CRYPT_AESSetIV(aes, iv);
696 CRYPT_AESEncrypt(aes, buf1, buf, 16);
697 FX_Free(aes);
698 pEncryptDict->SetStringFor("Perms", CFX_ByteString(buf1, 16));
699 }
OLDNEW
« no previous file with comments | « core/fpdfapi/fpdf_parser/cpdf_security_handler.h ('k') | core/fpdfapi/fpdf_parser/cpdf_security_handler_embeddertest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698