diff options
-rw-r--r-- | core/fpdfapi/edit/cpdf_creator.cpp | 1 | ||||
-rw-r--r-- | core/fpdfapi/parser/cpdf_crypto_handler.cpp | 68 | ||||
-rw-r--r-- | core/fpdfapi/parser/cpdf_crypto_handler.h | 6 | ||||
-rw-r--r-- | core/fpdfapi/parser/cpdf_parser.cpp | 3 | ||||
-rw-r--r-- | core/fpdfapi/parser/cpdf_security_handler.cpp | 61 | ||||
-rw-r--r-- | core/fpdfapi/parser/cpdf_security_handler.h | 16 |
6 files changed, 65 insertions, 90 deletions
diff --git a/core/fpdfapi/edit/cpdf_creator.cpp b/core/fpdfapi/edit/cpdf_creator.cpp index d6384059d1..eecf37b981 100644 --- a/core/fpdfapi/edit/cpdf_creator.cpp +++ b/core/fpdfapi/edit/cpdf_creator.cpp @@ -807,7 +807,6 @@ void CPDF_Creator::InitID() { m_pSecurityHandler = pdfium::MakeUnique<CPDF_SecurityHandler>(); m_pSecurityHandler->OnCreate(m_pEncryptDict.Get(), m_pIDArray.get(), user_pass, flag); - m_pSecurityHandler->InitCryptoHandler(); m_bSecurityChanged = true; } } diff --git a/core/fpdfapi/parser/cpdf_crypto_handler.cpp b/core/fpdfapi/parser/cpdf_crypto_handler.cpp index 441ca8000d..e8f0265ae4 100644 --- a/core/fpdfapi/parser/cpdf_crypto_handler.cpp +++ b/core/fpdfapi/parser/cpdf_crypto_handler.cpp @@ -8,6 +8,7 @@ #include <time.h> +#include <algorithm> #include <stack> #include <utility> @@ -278,56 +279,6 @@ uint32_t CPDF_CryptoHandler::DecryptGetSize(uint32_t src_size) { return m_Cipher == FXCIPHER_AES ? src_size - 16 : src_size; } -bool CPDF_CryptoHandler::Init(CPDF_Dictionary* pEncryptDict, - CPDF_SecurityHandler* pSecurityHandler) { - const uint8_t* key; - if (!pSecurityHandler->GetCryptInfo(m_Cipher, key, m_KeyLen)) - return false; - - if (m_KeyLen > 32 || m_KeyLen < 0) - return false; - - if (m_Cipher != FXCIPHER_NONE) - memcpy(m_EncryptKey, key, m_KeyLen); - - if (m_Cipher == FXCIPHER_AES) - m_pAESContext.reset(FX_Alloc(CRYPT_aes_context, 1)); - - return true; -} - -bool CPDF_CryptoHandler::Init(int cipher, const uint8_t* key, int keylen) { - if (cipher == FXCIPHER_AES) { - switch (keylen) { - case 16: - case 24: - case 32: - break; - default: - return false; - } - } else if (cipher == FXCIPHER_AES2) { - if (keylen != 32) { - return false; - } - } else if (cipher == FXCIPHER_RC4) { - if (keylen < 5 || keylen > 16) { - return false; - } - } else { - if (keylen > 32) { - keylen = 32; - } - } - m_Cipher = cipher; - m_KeyLen = keylen; - memcpy(m_EncryptKey, key, keylen); - if (m_Cipher == FXCIPHER_AES) - m_pAESContext.reset(FX_Alloc(CRYPT_aes_context, 1)); - - return true; -} - bool CPDF_CryptoHandler::IsCipherAES() const { return m_Cipher == FXCIPHER_AES; } @@ -444,8 +395,21 @@ bool CPDF_CryptoHandler::EncryptContent(uint32_t objnum, return true; } -CPDF_CryptoHandler::CPDF_CryptoHandler() - : m_KeyLen(0), m_Cipher(FXCIPHER_NONE) {} +CPDF_CryptoHandler::CPDF_CryptoHandler(int cipher, + const uint8_t* key, + int keylen) + : m_KeyLen(std::min(keylen, 32)), m_Cipher(cipher) { + ASSERT(cipher != FXCIPHER_AES || keylen == 16 || keylen == 24 || + keylen == 32); + ASSERT(cipher != FXCIPHER_AES2 || keylen == 32); + ASSERT(cipher != FXCIPHER_RC4 || (keylen >= 5 && keylen <= 16)); + + if (m_Cipher != FXCIPHER_NONE) + memcpy(m_EncryptKey, key, m_KeyLen); + + if (m_Cipher == FXCIPHER_AES) + m_pAESContext.reset(FX_Alloc(CRYPT_aes_context, 1)); +} CPDF_CryptoHandler::~CPDF_CryptoHandler() {} diff --git a/core/fpdfapi/parser/cpdf_crypto_handler.h b/core/fpdfapi/parser/cpdf_crypto_handler.h index 7175088de4..32eeaef4c9 100644 --- a/core/fpdfapi/parser/cpdf_crypto_handler.h +++ b/core/fpdfapi/parser/cpdf_crypto_handler.h @@ -22,14 +22,11 @@ class CPDF_SecurityHandler; class CPDF_CryptoHandler { public: - CPDF_CryptoHandler(); + CPDF_CryptoHandler(int cipher, const uint8_t* key, int keylen); ~CPDF_CryptoHandler(); static bool IsSignatureDictionary(const CPDF_Dictionary* dictionary); - bool Init(CPDF_Dictionary* pEncryptDict, - CPDF_SecurityHandler* pSecurityHandler); - std::unique_ptr<CPDF_Object> DecryptObjectTree( std::unique_ptr<CPDF_Object> object); @@ -44,7 +41,6 @@ class CPDF_CryptoHandler { uint8_t* dest_buf, uint32_t& dest_size); - bool Init(int cipher, const uint8_t* key, int keylen); bool IsCipherAES() const; private: diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp index a1b8a2deba..02cba64541 100644 --- a/core/fpdfapi/parser/cpdf_parser.cpp +++ b/core/fpdfapi/parser/cpdf_parser.cpp @@ -311,9 +311,6 @@ CPDF_Parser::Error CPDF_Parser::SetEncryptHandler() { m_Password)) return PASSWORD_ERROR; - if (!pSecurityHandler->InitCryptoHandler()) - return HANDLER_ERROR; - m_pSecurityHandler = std::move(pSecurityHandler); } return SUCCESS; diff --git a/core/fpdfapi/parser/cpdf_security_handler.cpp b/core/fpdfapi/parser/cpdf_security_handler.cpp index 9c79b9389b..4a33de116f 100644 --- a/core/fpdfapi/parser/cpdf_security_handler.cpp +++ b/core/fpdfapi/parser/cpdf_security_handler.cpp @@ -70,6 +70,22 @@ void CalcEncryptKey(CPDF_Dictionary* pEncrypt, memcpy(key, digest, copy_len); } +bool IsValidKeyLengthForCipher(int cipher, int keylen) { + switch (cipher) { + case FXCIPHER_AES: + return keylen == 16 || keylen == 24 || keylen == 32; + case FXCIPHER_AES2: + return keylen == 32; + case FXCIPHER_RC4: + return keylen >= 5 && keylen <= 16; + case FXCIPHER_NONE: + return true; + default: + NOTREACHED(); + } + return false; +} + } // namespace CPDF_SecurityHandler::CPDF_SecurityHandler() @@ -93,7 +109,11 @@ bool CPDF_SecurityHandler::OnInit(CPDF_Dictionary* pEncryptDict, if (m_Cipher == FXCIPHER_NONE) { return true; } - return CheckSecurity(password); + if (!CheckSecurity(password)) + return false; + + InitCryptoHandler(); + return true; } bool CPDF_SecurityHandler::CheckSecurity(const ByteString& password) { @@ -152,7 +172,7 @@ static bool LoadCryptInfo(CPDF_Dictionary* pEncryptDict, if (keylen > 32 || keylen < 0) { return false; } - return true; + return IsValidKeyLengthForCipher(cipher, keylen); } bool CPDF_SecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict) { @@ -196,14 +216,6 @@ bool CPDF_SecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict, return true; } -bool CPDF_SecurityHandler::GetCryptInfo(int& cipher, - const uint8_t*& buffer, - int& keylen) { - cipher = m_Cipher; - buffer = m_EncryptKey; - keylen = m_KeyLen; - return true; -} #define FX_GET_32WORD(n, b, i) \ { \ (n) = (uint32_t)( \ @@ -507,12 +519,12 @@ bool CPDF_SecurityHandler::IsMetadataEncrypted() const { return m_pEncryptDict->GetBooleanFor("EncryptMetadata", true); } -void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, - CPDF_Array* pIdArray, - const ByteString& user_password, - const ByteString& owner_password, - bool bDefault, - uint32_t type) { +void CPDF_SecurityHandler::OnCreateInternal(CPDF_Dictionary* pEncryptDict, + CPDF_Array* pIdArray, + const ByteString& user_password, + const ByteString& owner_password, + bool bDefault, + uint32_t type) { int cipher = 0, key_len = 0; if (!LoadDict(pEncryptDict, type, cipher, key_len)) { return; @@ -598,19 +610,26 @@ void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, pEncryptDict->SetNewFor<CPDF_String>("U", ByteString(digest, 32), false); } } + void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray, const ByteString& user_password, const ByteString& owner_password, uint32_t type) { - OnCreate(pEncryptDict, pIdArray, user_password, owner_password, true, type); + OnCreateInternal(pEncryptDict, pIdArray, user_password, owner_password, true, + type); + InitCryptoHandler(); } + void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray, const ByteString& user_password, uint32_t type) { - OnCreate(pEncryptDict, pIdArray, user_password, ByteString(), false, type); + OnCreateInternal(pEncryptDict, pIdArray, user_password, ByteString(), false, + type); + InitCryptoHandler(); } + void CPDF_SecurityHandler::AES256_SetPassword(CPDF_Dictionary* pEncryptDict, const ByteString& password, bool bOwner, @@ -695,7 +714,7 @@ void CPDF_SecurityHandler::AES256_SetPerms(CPDF_Dictionary* pEncryptDict, pEncryptDict->SetNewFor<CPDF_String>("Perms", ByteString(buf1, 16), false); } -bool CPDF_SecurityHandler::InitCryptoHandler() { - m_pCryptoHandler = pdfium::MakeUnique<CPDF_CryptoHandler>(); - return m_pCryptoHandler->Init(m_pEncryptDict.Get(), this); +void CPDF_SecurityHandler::InitCryptoHandler() { + m_pCryptoHandler = + pdfium::MakeUnique<CPDF_CryptoHandler>(m_Cipher, m_EncryptKey, m_KeyLen); } diff --git a/core/fpdfapi/parser/cpdf_security_handler.h b/core/fpdfapi/parser/cpdf_security_handler.h index 753a8503a1..c92dc46862 100644 --- a/core/fpdfapi/parser/cpdf_security_handler.h +++ b/core/fpdfapi/parser/cpdf_security_handler.h @@ -33,7 +33,6 @@ class CPDF_SecurityHandler { const CPDF_Array* pIdArray, const ByteString& password); uint32_t GetPermissions(); - bool GetCryptInfo(int& cipher, const uint8_t*& buffer, int& keylen); bool IsMetadataEncrypted() const; void OnCreate(CPDF_Dictionary* pEncryptDict, @@ -53,7 +52,6 @@ class CPDF_SecurityHandler { uint8_t* key, int key_len); - bool InitCryptoHandler(); CPDF_CryptoHandler* GetCryptoHandler() const { return m_pCryptoHandler.get(); } @@ -84,14 +82,16 @@ class CPDF_SecurityHandler { uint32_t permission, bool bEncryptMetadata, const uint8_t* key); - void OnCreate(CPDF_Dictionary* pEncryptDict, - CPDF_Array* pIdArray, - const ByteString& user_password, - const ByteString& owner_password, - bool bDefault, - uint32_t type); + void OnCreateInternal(CPDF_Dictionary* pEncryptDict, + CPDF_Array* pIdArray, + const ByteString& user_password, + const ByteString& owner_password, + bool bDefault, + uint32_t type); bool CheckSecurity(const ByteString& password); + void InitCryptoHandler(); + int m_Version; int m_Revision; UnownedPtr<CPDF_Dictionary> m_pEncryptDict; |