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