Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cpdf_security_handler.cpp
Go to the documentation of this file.
1// Copyright 2014 The PDFium Authors
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 <stdint.h>
10#include <time.h>
11
12#include <algorithm>
13#include <utility>
14
15#include "core/fdrm/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#include "core/fxcrt/data_vector.h"
22#include "core/fxcrt/fx_memcpy_wrappers.h"
23#include "core/fxcrt/fx_random.h"
24#include "third_party/base/check.h"
25#include "third_party/base/check_op.h"
26#include "third_party/base/notreached.h"
27
28namespace {
29
30const uint8_t kDefaultPasscode[32] = {
31 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e,
32 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68,
33 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a};
34
35void GetPassCode(const ByteString& password, pdfium::span<uint8_t> output) {
36 DCHECK_EQ(sizeof(kDefaultPasscode), output.size());
37 size_t len = std::min(password.GetLength(), output.size());
38 size_t remaining = output.size() - len;
39 FXSYS_memcpy(output.data(), password.raw_str(), len);
40 if (remaining) {
41 memcpy(&output[len], kDefaultPasscode, remaining);
42 }
43}
44
45void CalcEncryptKey(const CPDF_Dictionary* pEncrypt,
46 const ByteString& password,
47 uint8_t* key,
48 size_t keylen,
49 bool ignore_metadata,
50 const ByteString& file_id) {
51 uint8_t passcode[32];
52 GetPassCode(password, passcode);
54 CRYPT_MD5Update(&md5, passcode);
55 ByteString okey = pEncrypt->GetByteStringFor("O");
56 CRYPT_MD5Update(&md5, okey.raw_span());
57 uint32_t perm = pEncrypt->GetIntegerFor("P");
58 CRYPT_MD5Update(&md5, pdfium::as_bytes(pdfium::span_from_ref(perm)));
59 if (!file_id.IsEmpty())
60 CRYPT_MD5Update(&md5, file_id.raw_span());
61 const bool is_revision_3_or_greater = pEncrypt->GetIntegerFor("R") >= 3;
62 if (!ignore_metadata && is_revision_3_or_greater &&
63 !pEncrypt->GetBooleanFor("EncryptMetadata", true)) {
64 constexpr uint32_t tag = 0xFFFFFFFF;
65 CRYPT_MD5Update(&md5, pdfium::as_bytes(pdfium::span_from_ref(tag)));
66 }
67 uint8_t digest[16];
68 CRYPT_MD5Finish(&md5, digest);
69 size_t copy_len = std::min(keylen, sizeof(digest));
70 if (is_revision_3_or_greater) {
71 for (int i = 0; i < 50; i++)
72 CRYPT_MD5Generate({digest, copy_len}, digest);
73 }
74 memset(key, 0, keylen);
75 memcpy(key, digest, copy_len);
76}
77
78bool IsValidKeyLengthForCipher(CPDF_CryptoHandler::Cipher cipher,
79 size_t keylen) {
80 switch (cipher) {
82 return keylen == 16 || keylen == 24 || keylen == 32;
84 return keylen == 32;
86 return keylen >= 5 && keylen <= 16;
88 return true;
89 }
90}
91
92#define FX_GET_32WORD(n, b, i)
93 {
94 (n) = (uint32_t)(
95 ((uint64_t)(b)[(i)] << 24) | ((uint64_t)(b)[(i) + 1] << 16) |
96 ((uint64_t)(b)[(i) + 2] << 8) | ((uint64_t)(b)[(i) + 3]));
97 }
98int BigOrder64BitsMod3(uint8_t* data) {
99 uint64_t ret = 0;
100 for (int i = 0; i < 4; ++i) {
101 uint32_t value;
102 FX_GET_32WORD(value, data, 4 * i);
103 ret <<= 32;
104 ret |= value;
105 ret %= 3;
106 }
107 return (int)ret;
108}
109
110void Revision6_Hash(const ByteString& password,
111 const uint8_t* salt,
112 const uint8_t* vector,
113 uint8_t* hash) {
116 CRYPT_SHA256Update(&sha, password.raw_str(), password.GetLength());
117 CRYPT_SHA256Update(&sha, salt, 8);
118 if (vector)
119 CRYPT_SHA256Update(&sha, vector, 48);
120
121 uint8_t digest[32];
122 CRYPT_SHA256Finish(&sha, digest);
123
124 DataVector<uint8_t> buf;
125 uint8_t* input = digest;
126 uint8_t* key = input;
127 uint8_t* iv = input + 16;
128 uint8_t* E = nullptr;
129 int iBufLen = 0;
130 DataVector<uint8_t> interDigest;
131 int i = 0;
132 int iBlockSize = 32;
133 CRYPT_aes_context aes = {};
134 while (i < 64 || i < E[iBufLen - 1] + 32) {
135 int iRoundSize = password.GetLength() + iBlockSize;
136 if (vector) {
137 iRoundSize += 48;
138 }
139 iBufLen = iRoundSize * 64;
140 buf.resize(iBufLen);
141 E = buf.data();
142 DataVector<uint8_t> content;
143 for (int j = 0; j < 64; ++j) {
144 content.insert(std::end(content), password.raw_str(),
145 password.raw_str() + password.GetLength());
146 content.insert(std::end(content), input, input + iBlockSize);
147 if (vector) {
148 content.insert(std::end(content), vector, vector + 48);
149 }
150 }
151 CRYPT_AESSetKey(&aes, key, 16);
152 CRYPT_AESSetIV(&aes, iv);
153 CRYPT_AESEncrypt(&aes, E, content.data(), iBufLen);
154 int iHash = 0;
155 switch (BigOrder64BitsMod3(E)) {
156 case 0:
157 iHash = 0;
158 iBlockSize = 32;
159 break;
160 case 1:
161 iHash = 1;
162 iBlockSize = 48;
163 break;
164 default:
165 iHash = 2;
166 iBlockSize = 64;
167 break;
168 }
169 interDigest.resize(iBlockSize);
170 input = interDigest.data();
171 if (iHash == 0) {
172 CRYPT_SHA256Generate(E, iBufLen, input);
173 } else if (iHash == 1) {
174 CRYPT_SHA384Generate(E, iBufLen, input);
175 } else if (iHash == 2) {
176 CRYPT_SHA512Generate(E, iBufLen, input);
177 }
178 key = input;
179 iv = input + 16;
180 ++i;
181 }
182 if (hash) {
183 memcpy(hash, input, 32);
184 }
185}
186
187} // namespace
188
189CPDF_SecurityHandler::CPDF_SecurityHandler() = default;
190
191CPDF_SecurityHandler::~CPDF_SecurityHandler() = default;
192
193bool CPDF_SecurityHandler::OnInit(const CPDF_Dictionary* pEncryptDict,
194 RetainPtr<const CPDF_Array> pIdArray,
195 const ByteString& password) {
196 if (pIdArray)
197 m_FileId = pIdArray->GetByteStringAt(0);
198 else
199 m_FileId.clear();
200 if (!LoadDict(pEncryptDict))
201 return false;
202 if (m_Cipher == CPDF_CryptoHandler::Cipher::kNone)
203 return true;
204 if (!CheckSecurity(password))
205 return false;
206
207 InitCryptoHandler();
208 return true;
209}
210
211bool CPDF_SecurityHandler::CheckSecurity(const ByteString& password) {
212 if (!password.IsEmpty() && CheckPassword(password, true)) {
213 m_bOwnerUnlocked = true;
214 return true;
215 }
216 return CheckPassword(password, false);
217}
218
219uint32_t CPDF_SecurityHandler::GetPermissions(bool get_owner_perms) const {
220 uint32_t dwPermission =
221 m_bOwnerUnlocked && get_owner_perms ? 0xFFFFFFFF : m_Permissions;
222 if (m_pEncryptDict &&
223 m_pEncryptDict->GetByteStringFor("Filter") == "Standard") {
224 // See PDF Reference 1.7, page 123, table 3.20.
225 dwPermission &= 0xFFFFFFFC;
226 dwPermission |= 0xFFFFF0C0;
227 }
228 return dwPermission;
229}
230
231static bool LoadCryptInfo(const CPDF_Dictionary* pEncryptDict,
232 const ByteString& name,
233 CPDF_CryptoHandler::Cipher* cipher,
234 size_t* keylen_out) {
235 int Version = pEncryptDict->GetIntegerFor("V");
237 *keylen_out = 0;
238 int keylen = 0;
239 if (Version >= 4) {
240 RetainPtr<const CPDF_Dictionary> pCryptFilters =
241 pEncryptDict->GetDictFor("CF");
242 if (!pCryptFilters)
243 return false;
244
245 if (name == "Identity") {
247 } else {
248 RetainPtr<const CPDF_Dictionary> pDefFilter =
249 pCryptFilters->GetDictFor(name);
250 if (!pDefFilter)
251 return false;
252
253 int nKeyBits = 0;
254 if (Version == 4) {
255 nKeyBits = pDefFilter->GetIntegerFor("Length", 0);
256 if (nKeyBits == 0) {
257 nKeyBits = pEncryptDict->GetIntegerFor("Length", 128);
258 }
259 } else {
260 nKeyBits = pEncryptDict->GetIntegerFor("Length", 256);
261 }
262 if (nKeyBits < 0)
263 return false;
264
265 if (nKeyBits < 40) {
266 nKeyBits *= 8;
267 }
268 keylen = nKeyBits / 8;
269 ByteString cipher_name = pDefFilter->GetByteStringFor("CFM");
270 if (cipher_name == "AESV2" || cipher_name == "AESV3")
272 }
273 } else {
274 keylen = Version > 1 ? pEncryptDict->GetIntegerFor("Length", 40) / 8 : 5;
275 }
276
277 if (keylen < 0 || keylen > 32)
278 return false;
279 if (!IsValidKeyLengthForCipher(*cipher, keylen))
280 return false;
281
282 *keylen_out = keylen;
283 return true;
284}
285
286bool CPDF_SecurityHandler::LoadDict(const CPDF_Dictionary* pEncryptDict) {
287 m_pEncryptDict.Reset(pEncryptDict);
288 m_Version = pEncryptDict->GetIntegerFor("V");
289 m_Revision = pEncryptDict->GetIntegerFor("R");
290 m_Permissions = pEncryptDict->GetIntegerFor("P", -1);
291 if (m_Version < 4)
292 return LoadCryptInfo(pEncryptDict, ByteString(), &m_Cipher, &m_KeyLen);
293
294 ByteString stmf_name = pEncryptDict->GetByteStringFor("StmF");
295 ByteString strf_name = pEncryptDict->GetByteStringFor("StrF");
296 if (stmf_name != strf_name)
297 return false;
298
299 return LoadCryptInfo(pEncryptDict, strf_name, &m_Cipher, &m_KeyLen);
300}
301
302bool CPDF_SecurityHandler::LoadDict(const CPDF_Dictionary* pEncryptDict,
303 CPDF_CryptoHandler::Cipher* cipher,
304 size_t* key_len) {
305 m_pEncryptDict.Reset(pEncryptDict);
306 m_Version = pEncryptDict->GetIntegerFor("V");
307 m_Revision = pEncryptDict->GetIntegerFor("R");
308 m_Permissions = pEncryptDict->GetIntegerFor("P", -1);
309
310 ByteString strf_name;
311 ByteString stmf_name;
312 if (m_Version >= 4) {
313 stmf_name = pEncryptDict->GetByteStringFor("StmF");
314 strf_name = pEncryptDict->GetByteStringFor("StrF");
315 if (stmf_name != strf_name)
316 return false;
317 }
318 if (!LoadCryptInfo(pEncryptDict, strf_name, cipher, key_len))
319 return false;
320
321 m_Cipher = *cipher;
322 m_KeyLen = *key_len;
323 return true;
324}
325
326bool CPDF_SecurityHandler::AES256_CheckPassword(const ByteString& password,
327 bool bOwner) {
328 DCHECK(m_pEncryptDict);
329 DCHECK(m_Revision >= 5);
330
331 ByteString okey = m_pEncryptDict->GetByteStringFor("O");
332 if (okey.GetLength() < 48)
333 return false;
334
335 ByteString ukey = m_pEncryptDict->GetByteStringFor("U");
336 if (ukey.GetLength() < 48)
337 return false;
338
339 const uint8_t* pkey = bOwner ? okey.raw_str() : ukey.raw_str();
341 uint8_t digest[32];
342 if (m_Revision >= 6) {
343 Revision6_Hash(password, (const uint8_t*)pkey + 32,
344 bOwner ? ukey.raw_str() : nullptr, digest);
345 } else {
347 CRYPT_SHA256Update(&sha, password.raw_str(), password.GetLength());
348 CRYPT_SHA256Update(&sha, pkey + 32, 8);
349 if (bOwner)
351 CRYPT_SHA256Finish(&sha, digest);
352 }
353 if (memcmp(digest, pkey, 32) != 0)
354 return false;
355
356 if (m_Revision >= 6) {
357 Revision6_Hash(password, (const uint8_t*)pkey + 40,
358 bOwner ? ukey.raw_str() : nullptr, digest);
359 } else {
361 CRYPT_SHA256Update(&sha, password.raw_str(), password.GetLength());
362 CRYPT_SHA256Update(&sha, pkey + 40, 8);
363 if (bOwner)
365 CRYPT_SHA256Finish(&sha, digest);
366 }
367 ByteString ekey = m_pEncryptDict->GetByteStringFor(bOwner ? "OE" : "UE");
368 if (ekey.GetLength() < 32)
369 return false;
370
371 CRYPT_aes_context aes = {};
372 CRYPT_AESSetKey(&aes, digest, sizeof(digest));
373 uint8_t iv[16] = {};
374 CRYPT_AESSetIV(&aes, iv);
375 CRYPT_AESDecrypt(&aes, m_EncryptKey, ekey.raw_str(), 32);
376 CRYPT_AESSetKey(&aes, m_EncryptKey, sizeof(m_EncryptKey));
377 CRYPT_AESSetIV(&aes, iv);
378 ByteString perms = m_pEncryptDict->GetByteStringFor("Perms");
379 if (perms.IsEmpty())
380 return false;
381
382 uint8_t perms_buf[16] = {};
383 size_t copy_len =
384 std::min(sizeof(perms_buf), static_cast<size_t>(perms.GetLength()));
385 memcpy(perms_buf, perms.raw_str(), copy_len);
386 uint8_t buf[16];
387 CRYPT_AESDecrypt(&aes, buf, perms_buf, 16);
388 if (buf[9] != 'a' || buf[10] != 'd' || buf[11] != 'b')
389 return false;
390
391 if (FXSYS_UINT32_GET_LSBFIRST(buf) != m_Permissions)
392 return false;
393
394 // Relax this check as there appear to be some non-conforming documents
395 // in the wild. The value in the buffer is the truth; if it requires us
396 // to encrypt metadata, but the dictionary says otherwise, then we may
397 // have a tampered doc. Otherwise, give it a pass.
398 return buf[8] == 'F' || IsMetadataEncrypted();
399}
400
401bool CPDF_SecurityHandler::CheckPassword(const ByteString& password,
402 bool bOwner) {
403 DCHECK_EQ(kUnknown, m_PasswordEncodingConversion);
404 if (CheckPasswordImpl(password, bOwner)) {
405 m_PasswordEncodingConversion = kNone;
406 return true;
407 }
408
409 ByteStringView password_view = password.AsStringView();
410 if (password_view.IsASCII())
411 return false;
412
413 if (m_Revision >= 5) {
414 ByteString utf8_password = WideString::FromLatin1(password_view).ToUTF8();
415 if (!CheckPasswordImpl(utf8_password, bOwner))
416 return false;
417
418 m_PasswordEncodingConversion = kLatin1ToUtf8;
419 return true;
420 }
421
422 ByteString latin1_password = WideString::FromUTF8(password_view).ToLatin1();
423 if (!CheckPasswordImpl(latin1_password, bOwner))
424 return false;
425
426 m_PasswordEncodingConversion = kUtf8toLatin1;
427 return true;
428}
429
430bool CPDF_SecurityHandler::CheckPasswordImpl(const ByteString& password,
431 bool bOwner) {
432 if (m_Revision >= 5)
433 return AES256_CheckPassword(password, bOwner);
434
435 if (bOwner)
436 return CheckOwnerPassword(password);
437
438 return CheckUserPassword(password, false) ||
439 CheckUserPassword(password, true);
440}
441
442bool CPDF_SecurityHandler::CheckUserPassword(const ByteString& password,
443 bool bIgnoreEncryptMeta) {
444 CalcEncryptKey(m_pEncryptDict.Get(), password, m_EncryptKey, m_KeyLen,
445 bIgnoreEncryptMeta, m_FileId);
446 ByteString ukey =
447 m_pEncryptDict ? m_pEncryptDict->GetByteStringFor("U") : ByteString();
448 if (ukey.GetLength() < 16) {
449 return false;
450 }
451
452 uint8_t ukeybuf[32];
453 if (m_Revision == 2) {
454 memcpy(ukeybuf, kDefaultPasscode, sizeof(kDefaultPasscode));
455 CRYPT_ArcFourCryptBlock(ukeybuf, {m_EncryptKey, m_KeyLen});
456 return memcmp(ukey.c_str(), ukeybuf, 16) == 0;
457 }
458
459 uint8_t test[32] = {};
460 uint8_t tmpkey[32] = {};
461 uint32_t copy_len = std::min(sizeof(test), ukey.GetLength());
462
463 memcpy(test, ukey.c_str(), copy_len);
464 for (int32_t i = 19; i >= 0; i--) {
465 for (size_t j = 0; j < m_KeyLen; j++)
466 tmpkey[j] = m_EncryptKey[j] ^ static_cast<uint8_t>(i);
467 CRYPT_ArcFourCryptBlock(test, {tmpkey, m_KeyLen});
468 }
470 CRYPT_MD5Update(&md5, kDefaultPasscode);
471 if (!m_FileId.IsEmpty())
472 CRYPT_MD5Update(&md5, m_FileId.raw_span());
473 CRYPT_MD5Finish(&md5, ukeybuf);
474 return memcmp(test, ukeybuf, 16) == 0;
475}
476
477ByteString CPDF_SecurityHandler::GetUserPassword(
478 const ByteString& owner_password) const {
479 constexpr size_t kRequiredOkeyLength = 32;
480 ByteString okey = m_pEncryptDict->GetByteStringFor("O");
481 size_t okeylen = std::min<size_t>(okey.GetLength(), kRequiredOkeyLength);
482 if (okeylen < kRequiredOkeyLength)
483 return ByteString();
484
485 DCHECK_EQ(kRequiredOkeyLength, okeylen);
486 uint8_t passcode[32];
487 GetPassCode(owner_password, passcode);
488 uint8_t digest[16];
489 CRYPT_MD5Generate(passcode, digest);
490 if (m_Revision >= 3) {
491 for (uint32_t i = 0; i < 50; i++)
492 CRYPT_MD5Generate(digest, digest);
493 }
494 uint8_t enckey[32] = {};
495 size_t copy_len = std::min(m_KeyLen, sizeof(digest));
496
497 memcpy(enckey, digest, copy_len);
498 uint8_t okeybuf[32] = {};
499 memcpy(okeybuf, okey.c_str(), okeylen);
500 pdfium::span<uint8_t> okey_span(okeybuf, okeylen);
501 if (m_Revision == 2) {
502 CRYPT_ArcFourCryptBlock(okey_span, {enckey, m_KeyLen});
503 } else {
504 for (int32_t i = 19; i >= 0; i--) {
505 uint8_t tempkey[32] = {};
506 for (size_t j = 0; j < m_KeyLen; j++)
507 tempkey[j] = enckey[j] ^ static_cast<uint8_t>(i);
508 CRYPT_ArcFourCryptBlock(okey_span, {tempkey, m_KeyLen});
509 }
510 }
511 size_t len = kRequiredOkeyLength;
512 while (len && kDefaultPasscode[len - 1] == okey_span[len - 1])
513 len--;
514
515 return ByteString(okeybuf, len);
516}
517
518bool CPDF_SecurityHandler::CheckOwnerPassword(const ByteString& password) {
519 ByteString user_pass = GetUserPassword(password);
520 return CheckUserPassword(user_pass, false) ||
521 CheckUserPassword(user_pass, true);
522}
523
524bool CPDF_SecurityHandler::IsMetadataEncrypted() const {
525 return m_pEncryptDict->GetBooleanFor("EncryptMetadata", true);
526}
527
528ByteString CPDF_SecurityHandler::GetEncodedPassword(
529 ByteStringView password) const {
530 switch (m_PasswordEncodingConversion) {
531 case kNone:
532 // Do nothing.
533 return ByteString(password);
534 case kLatin1ToUtf8:
535 return WideString::FromLatin1(password).ToUTF8();
536 case kUtf8toLatin1:
537 return WideString::FromUTF8(password).ToLatin1();
538 default:
539 NOTREACHED_NORETURN();
540 }
541}
542
543void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict,
544 const CPDF_Array* pIdArray,
545 const ByteString& password) {
546 DCHECK(pEncryptDict);
547
549 size_t key_len = 0;
550 if (!LoadDict(pEncryptDict, &cipher, &key_len)) {
551 return;
552 }
553
554 if (m_Revision >= 5) {
555 uint32_t random[4];
556 FX_Random_GenerateMT(random, std::size(random));
559 CRYPT_SHA256Update(&sha, reinterpret_cast<uint8_t*>(random),
560 sizeof(random));
561 CRYPT_SHA256Finish(&sha, m_EncryptKey);
562 AES256_SetPassword(pEncryptDict, password);
563 AES256_SetPerms(pEncryptDict);
564 return;
565 }
566
567 ByteString file_id;
568 if (pIdArray)
569 file_id = pIdArray->GetByteStringAt(0);
570
571 CalcEncryptKey(m_pEncryptDict.Get(), password, m_EncryptKey, key_len, false,
572 file_id);
573 if (m_Revision < 3) {
574 uint8_t tempbuf[32];
575 memcpy(tempbuf, kDefaultPasscode, sizeof(kDefaultPasscode));
576 CRYPT_ArcFourCryptBlock(tempbuf, {m_EncryptKey, key_len});
577 pEncryptDict->SetNewFor<CPDF_String>("U", ByteString(tempbuf, 32), false);
578 } else {
580 CRYPT_MD5Update(&md5, kDefaultPasscode);
581 if (!file_id.IsEmpty())
582 CRYPT_MD5Update(&md5, file_id.raw_span());
583
584 uint8_t digest[32];
585 CRYPT_MD5Finish(&md5, digest);
586 pdfium::span<uint8_t> partial_digest_span(digest, 16u);
587 CRYPT_ArcFourCryptBlock(partial_digest_span, {m_EncryptKey, key_len});
588 uint8_t tempkey[32];
589 for (uint8_t i = 1; i <= 19; i++) {
590 for (size_t j = 0; j < key_len; j++)
591 tempkey[j] = m_EncryptKey[j] ^ i;
592 CRYPT_ArcFourCryptBlock(partial_digest_span, {tempkey, key_len});
593 }
594 CRYPT_MD5Generate({digest, 16u}, digest + 16);
595 pEncryptDict->SetNewFor<CPDF_String>("U", ByteString(digest, 32), false);
596 }
597
598 InitCryptoHandler();
599}
600
601void CPDF_SecurityHandler::AES256_SetPassword(CPDF_Dictionary* pEncryptDict,
602 const ByteString& password) {
605 CRYPT_SHA1Update(&sha, m_EncryptKey, sizeof(m_EncryptKey));
606 CRYPT_SHA1Update(&sha, (uint8_t*)"hello", 5);
607
608 uint8_t digest[20];
609 CRYPT_SHA1Finish(&sha, digest);
610
612 uint8_t digest1[48];
613 if (m_Revision >= 6) {
614 Revision6_Hash(password, digest, nullptr, digest1);
615 } else {
617 CRYPT_SHA256Update(&sha2, password.raw_str(), password.GetLength());
618 CRYPT_SHA256Update(&sha2, digest, 8);
619 CRYPT_SHA256Finish(&sha2, digest1);
620 }
621 memcpy(digest1 + 32, digest, 16);
622 pEncryptDict->SetNewFor<CPDF_String>("U", ByteString(digest1, 48), false);
623 if (m_Revision >= 6) {
624 Revision6_Hash(password, digest + 8, nullptr, digest1);
625 } else {
627 CRYPT_SHA256Update(&sha2, password.raw_str(), password.GetLength());
628 CRYPT_SHA256Update(&sha2, digest + 8, 8);
629 CRYPT_SHA256Finish(&sha2, digest1);
630 }
631 CRYPT_aes_context aes = {};
632 CRYPT_AESSetKey(&aes, digest1, 32);
633 uint8_t iv[16] = {};
634 CRYPT_AESSetIV(&aes, iv);
635 CRYPT_AESEncrypt(&aes, digest1, m_EncryptKey, sizeof(m_EncryptKey));
636 pEncryptDict->SetNewFor<CPDF_String>("UE", ByteString(digest1, 32), false);
637}
638
639void CPDF_SecurityHandler::AES256_SetPerms(CPDF_Dictionary* pEncryptDict) {
640 uint8_t buf[16];
641 buf[0] = static_cast<uint8_t>(m_Permissions);
642 buf[1] = static_cast<uint8_t>(m_Permissions >> 8);
643 buf[2] = static_cast<uint8_t>(m_Permissions >> 16);
644 buf[3] = static_cast<uint8_t>(m_Permissions >> 24);
645 buf[4] = 0xff;
646 buf[5] = 0xff;
647 buf[6] = 0xff;
648 buf[7] = 0xff;
649 buf[8] = pEncryptDict->GetBooleanFor("EncryptMetadata", true) ? 'T' : 'F';
650 buf[9] = 'a';
651 buf[10] = 'd';
652 buf[11] = 'b';
653
654 // In ISO 32000 Supplement for ExtensionLevel 3, Algorithm 3.10 says bytes 12
655 // to 15 should be random data.
656 uint32_t* buf_random = reinterpret_cast<uint32_t*>(&buf[12]);
657 FX_Random_GenerateMT(buf_random, 1);
658
659 CRYPT_aes_context aes = {};
660 CRYPT_AESSetKey(&aes, m_EncryptKey, sizeof(m_EncryptKey));
661
662 uint8_t iv[16] = {};
663 CRYPT_AESSetIV(&aes, iv);
664
665 uint8_t buf1[16];
666 CRYPT_AESEncrypt(&aes, buf1, buf, 16);
667 pEncryptDict->SetNewFor<CPDF_String>("Perms", ByteString(buf1, 16), false);
668}
669
670void CPDF_SecurityHandler::InitCryptoHandler() {
671 m_pCryptoHandler =
672 std::make_unique<CPDF_CryptoHandler>(m_Cipher, m_EncryptKey, m_KeyLen);
673}
int GetIntegerFor(const ByteString &key) const
bool GetBooleanFor(const ByteString &key, bool bDefault) const
ByteString GetByteStringFor(const ByteString &key) const
int GetIntegerFor(const ByteString &key, int default_int) const
bool OnInit(const CPDF_Dictionary *pEncryptDict, RetainPtr< const CPDF_Array > pIdArray, const ByteString &password)
~CPDF_SecurityHandler() override
uint32_t GetPermissions(bool get_owner_perms) const
void OnCreate(CPDF_Dictionary *pEncryptDict, const CPDF_Array *pIdArray, const ByteString &password)
ByteString GetEncodedPassword(ByteStringView password) const
const uint8_t * raw_str() const
Definition bytestring.h:80
bool operator==(const char *ptr) const
bool operator!=(const ByteString &other) const
Definition bytestring.h:132
const char * c_str() const
Definition bytestring.h:76
ByteString & operator=(ByteString &&that) noexcept
bool IsEmpty() const
Definition bytestring.h:119
static WideString FromUTF8(ByteStringView str)
static WideString FromLatin1(ByteStringView str)
static bool LoadCryptInfo(const CPDF_Dictionary *pEncryptDict, const ByteString &name, CPDF_CryptoHandler::Cipher *cipher, size_t *keylen_out)
#define FX_GET_32WORD(n, b, i)
void CRYPT_MD5Finish(CRYPT_md5_context *context, uint8_t digest[16])
Definition fx_crypt.cpp:214
CRYPT_md5_context CRYPT_MD5Start()
Definition fx_crypt.cpp:176
void CRYPT_AESSetIV(CRYPT_aes_context *context, const uint8_t *iv)
void CRYPT_SHA1Finish(CRYPT_sha1_context *context, uint8_t digest[20])
void CRYPT_AESEncrypt(CRYPT_aes_context *context, uint8_t *dest, const uint8_t *src, uint32_t size)
void CRYPT_AESSetKey(CRYPT_aes_context *context, const uint8_t *key, uint32_t keylen)
void CRYPT_SHA256Generate(const uint8_t *data, uint32_t size, uint8_t digest[32])
void CRYPT_SHA512Generate(const uint8_t *data, uint32_t size, uint8_t digest[64])
void CRYPT_SHA256Update(CRYPT_sha2_context *context, const uint8_t *data, uint32_t size)
void CRYPT_SHA1Update(CRYPT_sha1_context *context, const uint8_t *data, uint32_t size)
void CRYPT_SHA256Finish(CRYPT_sha2_context *context, uint8_t digest[32])
void CRYPT_SHA256Start(CRYPT_sha2_context *context)
void CRYPT_SHA1Start(CRYPT_sha1_context *context)
void CRYPT_AESDecrypt(CRYPT_aes_context *context, uint8_t *dest, const uint8_t *src, uint32_t size)
void CRYPT_SHA384Generate(const uint8_t *data, uint32_t size, uint8_t digest[48])
void FX_Random_GenerateMT(uint32_t *pBuffer, int32_t iCount)