7#include "core/fpdfapi/parser/cpdf_security_handler.h"
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"
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};
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);
41 memcpy(&output[len], kDefaultPasscode, remaining);
45void CalcEncryptKey(
const CPDF_Dictionary* pEncrypt,
46 const ByteString& password,
50 const ByteString& file_id) {
52 GetPassCode(password, passcode);
54 CRYPT_MD5Update(&md5, passcode);
56 CRYPT_MD5Update(&md5, okey.raw_span());
58 CRYPT_MD5Update(&md5, pdfium::as_bytes(pdfium::span_from_ref(perm)));
60 CRYPT_MD5Update(&md5, file_id.raw_span());
62 if (!ignore_metadata && is_revision_3_or_greater &&
64 constexpr uint32_t tag = 0xFFFFFFFF;
65 CRYPT_MD5Update(&md5, pdfium::as_bytes(pdfium::span_from_ref(tag)));
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);
74 memset(key, 0, keylen);
75 memcpy(key, digest, copy_len);
82 return keylen == 16 || keylen == 24 || keylen == 32;
86 return keylen >= 5 && keylen <= 16;
92#define FX_GET_32WORD(n, b, i)
95 ((uint64_t)(b)[(i)] << 24
) | ((uint64_t)(b)[(i) + 1
] << 16
) |
96 ((uint64_t)(b)[(i) + 2
] << 8
) | ((uint64_t)(b)[(i) + 3
]));
98int BigOrder64BitsMod3(uint8_t* data) {
100 for (
int i = 0; i < 4; ++i) {
110void Revision6_Hash(
const ByteString& password,
112 const uint8_t* vector,
116 CRYPT_SHA256Update(&sha, password
.raw_str(), password.GetLength());
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;
130 DataVector<uint8_t> interDigest;
134 while (i < 64 || i < E[iBufLen - 1] + 32) {
135 int iRoundSize = password.GetLength() + iBlockSize;
139 iBufLen = iRoundSize * 64;
142 DataVector<uint8_t> content;
143 for (
int j = 0; j < 64; ++j) {
146 content.insert(
std::end(content), input, input + iBlockSize);
148 content.insert(
std::end(content), vector, vector + 48);
153 CRYPT_AESEncrypt(&aes, E, content.data(), iBufLen);
155 switch (BigOrder64BitsMod3(E)) {
169 interDigest.resize(iBlockSize);
170 input = interDigest.data();
173 }
else if (iHash == 1) {
175 }
else if (iHash == 2) {
183 memcpy(hash, input, 32);
189CPDF_SecurityHandler::CPDF_SecurityHandler() =
default;
193bool CPDF_SecurityHandler::
OnInit(
const CPDF_Dictionary* pEncryptDict,
195 const ByteString& password) {
197 m_FileId = pIdArray->GetByteStringAt(0);
200 if (!LoadDict(pEncryptDict))
204 if (!CheckSecurity(password))
211bool CPDF_SecurityHandler::CheckSecurity(
const ByteString& password) {
212 if (!password
.IsEmpty() && CheckPassword(password,
true)) {
213 m_bOwnerUnlocked =
true;
216 return CheckPassword(password,
false);
220 uint32_t dwPermission =
221 m_bOwnerUnlocked && get_owner_perms ? 0xFFFFFFFF : m_Permissions;
222 if (m_pEncryptDict &&
223 m_pEncryptDict->GetByteStringFor(
"Filter") ==
"Standard") {
225 dwPermission &= 0xFFFFFFFC;
226 dwPermission |= 0xFFFFF0C0;
232 const ByteString& name,
234 size_t* keylen_out) {
240 RetainPtr<
const CPDF_Dictionary> pCryptFilters =
241 pEncryptDict->GetDictFor(
"CF");
245 if (name
== "Identity") {
248 RetainPtr<
const CPDF_Dictionary> pDefFilter =
249 pCryptFilters->GetDictFor(name);
255 nKeyBits = pDefFilter->GetIntegerFor(
"Length", 0);
268 keylen = nKeyBits / 8;
269 ByteString cipher_name = pDefFilter->GetByteStringFor(
"CFM");
270 if (cipher_name
== "AESV2" || cipher_name
== "AESV3")
277 if (keylen < 0 || keylen > 32)
279 if (!IsValidKeyLengthForCipher(*cipher, keylen))
282 *keylen_out = keylen;
286bool CPDF_SecurityHandler::LoadDict(
const CPDF_Dictionary* pEncryptDict) {
287 m_pEncryptDict.Reset(pEncryptDict);
292 return LoadCryptInfo(pEncryptDict, ByteString(), &m_Cipher, &m_KeyLen);
296 if (stmf_name
!= strf_name)
299 return LoadCryptInfo(pEncryptDict, strf_name, &m_Cipher, &m_KeyLen);
302bool CPDF_SecurityHandler::LoadDict(
const CPDF_Dictionary* pEncryptDict,
305 m_pEncryptDict.Reset(pEncryptDict);
310 ByteString strf_name;
311 ByteString stmf_name;
312 if (m_Version >= 4) {
315 if (stmf_name
!= strf_name)
318 if (!LoadCryptInfo(pEncryptDict, strf_name, cipher, key_len))
326bool CPDF_SecurityHandler::AES256_CheckPassword(
const ByteString& password,
328 DCHECK(m_pEncryptDict);
329 DCHECK(m_Revision >= 5);
331 ByteString okey = m_pEncryptDict->GetByteStringFor(
"O");
332 if (okey.GetLength() < 48)
335 ByteString ukey = m_pEncryptDict->GetByteStringFor(
"U");
336 if (ukey.GetLength() < 48)
342 if (m_Revision >= 6) {
343 Revision6_Hash(password, (
const uint8_t*)pkey + 32,
347 CRYPT_SHA256Update(&sha, password
.raw_str(), password.GetLength());
353 if (memcmp(digest, pkey, 32) != 0)
356 if (m_Revision >= 6) {
357 Revision6_Hash(password, (
const uint8_t*)pkey + 40,
361 CRYPT_SHA256Update(&sha, password
.raw_str(), password.GetLength());
367 ByteString ekey = m_pEncryptDict->GetByteStringFor(bOwner ?
"OE" :
"UE");
368 if (ekey.GetLength() < 32)
378 ByteString perms = m_pEncryptDict->GetByteStringFor(
"Perms");
382 uint8_t perms_buf[16] = {};
384 std::min(
sizeof(perms_buf),
static_cast<size_t>(perms.GetLength()));
388 if (buf[9] !=
'a' || buf[10] !=
'd' || buf[11] !=
'b')
391 if (FXSYS_UINT32_GET_LSBFIRST(buf) != m_Permissions)
401bool CPDF_SecurityHandler::CheckPassword(
const ByteString& password,
403 DCHECK_EQ(kUnknown, m_PasswordEncodingConversion);
404 if (CheckPasswordImpl(password, bOwner)) {
405 m_PasswordEncodingConversion = kNone;
409 ByteStringView password_view = password.AsStringView();
410 if (password_view.IsASCII())
413 if (m_Revision >= 5) {
414 ByteString utf8_password = WideString
::FromLatin1(password_view
).ToUTF8();
415 if (!CheckPasswordImpl(utf8_password, bOwner))
418 m_PasswordEncodingConversion = kLatin1ToUtf8;
422 ByteString latin1_password = WideString
::FromUTF8(password_view
).ToLatin1();
423 if (!CheckPasswordImpl(latin1_password, bOwner))
426 m_PasswordEncodingConversion = kUtf8toLatin1;
430bool CPDF_SecurityHandler::CheckPasswordImpl(
const ByteString& password,
433 return AES256_CheckPassword(password, bOwner);
436 return CheckOwnerPassword(password);
438 return CheckUserPassword(password,
false) ||
439 CheckUserPassword(password,
true);
442bool CPDF_SecurityHandler::CheckUserPassword(
const ByteString& password,
443 bool bIgnoreEncryptMeta) {
444 CalcEncryptKey(m_pEncryptDict.Get(), password, m_EncryptKey, m_KeyLen,
445 bIgnoreEncryptMeta, m_FileId);
447 m_pEncryptDict ? m_pEncryptDict->GetByteStringFor(
"U") : ByteString();
448 if (ukey.GetLength() < 16) {
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;
459 uint8_t test[32] = {};
460 uint8_t tmpkey[32] = {};
461 uint32_t copy_len =
std::min(
sizeof(test), ukey.GetLength());
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});
470 CRYPT_MD5Update(&md5, kDefaultPasscode);
471 if (!m_FileId.IsEmpty())
472 CRYPT_MD5Update(&md5, m_FileId.raw_span());
474 return memcmp(test, ukeybuf, 16) == 0;
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)
485 DCHECK_EQ(kRequiredOkeyLength, okeylen);
486 uint8_t passcode[32];
487 GetPassCode(owner_password, passcode);
489 CRYPT_MD5Generate(passcode, digest);
490 if (m_Revision >= 3) {
491 for (uint32_t i = 0; i < 50; i++)
492 CRYPT_MD5Generate(digest, digest);
494 uint8_t enckey[32] = {};
495 size_t copy_len = std::min(m_KeyLen,
sizeof(digest));
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});
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});
511 size_t len = kRequiredOkeyLength;
512 while (len && kDefaultPasscode[len - 1] == okey_span[len - 1])
515 return ByteString(okeybuf, len);
518bool CPDF_SecurityHandler::CheckOwnerPassword(
const ByteString& password) {
519 ByteString user_pass = GetUserPassword(password);
520 return CheckUserPassword(user_pass,
false) ||
521 CheckUserPassword(user_pass,
true);
525 return m_pEncryptDict->GetBooleanFor(
"EncryptMetadata",
true);
529 ByteStringView password)
const {
530 switch (m_PasswordEncodingConversion) {
533 return ByteString(password);
539 NOTREACHED_NORETURN();
543void CPDF_SecurityHandler::
OnCreate(CPDF_Dictionary* pEncryptDict,
544 const CPDF_Array* pIdArray,
545 const ByteString& password) {
546 DCHECK(pEncryptDict);
550 if (!LoadDict(pEncryptDict, &cipher, &key_len)) {
554 if (m_Revision >= 5) {
556 FX_Random_GenerateMT(random,
std::size(random));
562 AES256_SetPassword(pEncryptDict, password);
563 AES256_SetPerms(pEncryptDict);
569 file_id = pIdArray->GetByteStringAt(0);
571 CalcEncryptKey(m_pEncryptDict.Get(), password, m_EncryptKey, key_len,
false,
573 if (m_Revision < 3) {
575 memcpy(tempbuf, kDefaultPasscode,
sizeof(kDefaultPasscode));
576 CRYPT_ArcFourCryptBlock(tempbuf, {m_EncryptKey, key_len});
577 pEncryptDict->SetNewFor<CPDF_String>(
"U", ByteString(tempbuf, 32),
false);
580 CRYPT_MD5Update(&md5, kDefaultPasscode);
582 CRYPT_MD5Update(&md5, file_id.raw_span());
586 pdfium::span<uint8_t> partial_digest_span(digest, 16u);
587 CRYPT_ArcFourCryptBlock(partial_digest_span, {m_EncryptKey, key_len});
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});
594 CRYPT_MD5Generate({digest, 16u}, digest + 16);
595 pEncryptDict->SetNewFor<CPDF_String>(
"U", ByteString(digest, 32),
false);
601void CPDF_SecurityHandler::AES256_SetPassword(CPDF_Dictionary* pEncryptDict,
602 const ByteString& password) {
613 if (m_Revision >= 6) {
614 Revision6_Hash(password, digest,
nullptr, digest1);
617 CRYPT_SHA256Update(&sha2, password
.raw_str(), password.GetLength());
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);
627 CRYPT_SHA256Update(&sha2, password
.raw_str(), password.GetLength());
636 pEncryptDict->SetNewFor<CPDF_String>(
"UE", ByteString(digest1, 32),
false);
639void CPDF_SecurityHandler::AES256_SetPerms(CPDF_Dictionary* pEncryptDict) {
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);
656 uint32_t* buf_random =
reinterpret_cast<uint32_t*>(&buf[12]);
667 pEncryptDict->SetNewFor<CPDF_String>(
"Perms", ByteString(buf1, 16),
false);
670void CPDF_SecurityHandler::InitCryptoHandler() {
672 std::make_unique<CPDF_CryptoHandler>(m_Cipher, m_EncryptKey, m_KeyLen);
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 IsMetadataEncrypted() 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
bool operator==(const char *ptr) const
bool operator!=(const ByteString &other) const
const char * c_str() const
ByteString & operator=(ByteString &&that) noexcept
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])
CRYPT_md5_context CRYPT_MD5Start()
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)