From a1193aedb8797fcb26f54d7b99e4662ae72e3de9 Mon Sep 17 00:00:00 2001 From: Tom Sepez Date: Wed, 9 Mar 2016 17:42:18 -0800 Subject: Split off IPDF_CryptoHandler into its own .cpp/.h files. CPDF_CryptoHandler was always a pure-virtual class, now it is named as IPDF_ to indicate this. R=dsinclair@chromium.org Review URL: https://codereview.chromium.org/1782673002 . --- core/src/fpdfapi/fpdf_edit/fpdf_edit_create.cpp | 14 +- core/src/fpdfapi/fpdf_parser/cpdf_parser.cpp | 5 +- .../fpdf_parser/cpdf_standard_crypto_handler.cpp | 343 ++++++++++++++++++++ .../fpdf_parser/cpdf_standard_crypto_handler.h | 64 ++++ .../fpdf_parser/cpdf_standard_security_handler.cpp | 3 +- .../fpdf_parser/cpdf_standard_security_handler.h | 2 +- .../src/fpdfapi/fpdf_parser/cpdf_syntax_parser.cpp | 5 +- core/src/fpdfapi/fpdf_parser/cpdf_syntax_parser.h | 8 +- .../fpdfapi/fpdf_parser/fpdf_parser_encrypt.cpp | 344 --------------------- 9 files changed, 428 insertions(+), 360 deletions(-) create mode 100644 core/src/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.cpp create mode 100644 core/src/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.h delete mode 100644 core/src/fpdfapi/fpdf_parser/fpdf_parser_encrypt.cpp (limited to 'core/src/fpdfapi') diff --git a/core/src/fpdfapi/fpdf_edit/fpdf_edit_create.cpp b/core/src/fpdfapi/fpdf_edit/fpdf_edit_create.cpp index 4cfafc51b6..848b12fbdd 100644 --- a/core/src/fpdfapi/fpdf_edit/fpdf_edit_create.cpp +++ b/core/src/fpdfapi/fpdf_edit/fpdf_edit_create.cpp @@ -12,7 +12,9 @@ #include "core/include/fpdfapi/cpdf_parser.h" #include "core/include/fpdfapi/fpdf_parser.h" #include "core/include/fpdfapi/fpdf_serial.h" +#include "core/include/fpdfapi/ipdf_crypto_handler.h" #include "core/include/fxcrt/fx_ext.h" +#include "core/src/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.h" #include "core/src/fpdfapi/fpdf_parser/cpdf_standard_security_handler.h" #include "third_party/base/stl_util.h" @@ -470,7 +472,7 @@ class CPDF_Encryptor { public: CPDF_Encryptor(); ~CPDF_Encryptor(); - FX_BOOL Initialize(CPDF_CryptoHandler* pHandler, + FX_BOOL Initialize(IPDF_CryptoHandler* pHandler, int objnum, uint8_t* src_data, FX_DWORD src_size); @@ -483,7 +485,7 @@ CPDF_Encryptor::CPDF_Encryptor() { m_dwSize = 0; m_bNewBuf = FALSE; } -FX_BOOL CPDF_Encryptor::Initialize(CPDF_CryptoHandler* pHandler, +FX_BOOL CPDF_Encryptor::Initialize(IPDF_CryptoHandler* pHandler, int objnum, uint8_t* src_data, FX_DWORD src_size) { @@ -540,7 +542,7 @@ FX_FILESIZE CPDF_ObjectStream::End(CPDF_Creator* pCreator) { return 0; } CFX_FileBufferArchive* pFile = &pCreator->m_File; - CPDF_CryptoHandler* pHandler = pCreator->m_pCryptoHandler; + IPDF_CryptoHandler* pHandler = pCreator->m_pCryptoHandler; FX_FILESIZE ObjOffset = pCreator->m_Offset; if (!m_dwObjNum) { m_dwObjNum = ++pCreator->m_dwLastObjNum; @@ -1016,7 +1018,7 @@ int32_t CPDF_Creator::AppendObjectNumberToXRef(FX_DWORD objnum) { } int32_t CPDF_Creator::WriteStream(const CPDF_Object* pStream, FX_DWORD objnum, - CPDF_CryptoHandler* pCrypto) { + IPDF_CryptoHandler* pCrypto) { CPDF_FlateEncoder encoder; encoder.Initialize(const_cast(pStream->AsStream()), pStream == m_pMetadata ? FALSE : m_bCompress); @@ -1059,7 +1061,7 @@ int32_t CPDF_Creator::WriteIndirectObj(FX_DWORD objnum, m_Offset += len; if (pObj->IsStream()) { - CPDF_CryptoHandler* pHandler = nullptr; + IPDF_CryptoHandler* pHandler = nullptr; pHandler = (pObj == m_pMetadata && !m_bEncryptMetadata) ? NULL : m_pCryptoHandler; if (WriteStream(pObj, objnum, pHandler) < 0) @@ -1139,7 +1141,7 @@ int32_t CPDF_Creator::WriteDirectObj(FX_DWORD objnum, encoder.Initialize(const_cast(pObj->AsStream()), m_bCompress); CPDF_Encryptor encryptor; - CPDF_CryptoHandler* pHandler = m_pCryptoHandler; + IPDF_CryptoHandler* pHandler = m_pCryptoHandler; encryptor.Initialize(pHandler, objnum, encoder.m_pData, encoder.m_dwSize); if ((FX_DWORD)encoder.m_pDict->GetIntegerBy("Length") != encryptor.m_dwSize) { diff --git a/core/src/fpdfapi/fpdf_parser/cpdf_parser.cpp b/core/src/fpdfapi/fpdf_parser/cpdf_parser.cpp index 45d29f9351..b016797d7d 100644 --- a/core/src/fpdfapi/fpdf_parser/cpdf_parser.cpp +++ b/core/src/fpdfapi/fpdf_parser/cpdf_parser.cpp @@ -10,6 +10,7 @@ #include "core/include/fpdfapi/cpdf_document.h" #include "core/include/fpdfapi/fpdf_parser.h" +#include "core/include/fpdfapi/ipdf_crypto_handler.h" #include "core/include/fxcrt/fx_ext.h" #include "core/include/fxcrt/fx_safe_types.h" #include "core/src/fpdfapi/fpdf_parser/cpdf_standard_security_handler.h" @@ -94,7 +95,7 @@ void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict) { m_pEncryptDict = pDict; } -CPDF_CryptoHandler* CPDF_Parser::GetCryptoHandler() { +IPDF_CryptoHandler* CPDF_Parser::GetCryptoHandler() { return m_pSyntax->m_pCryptoHandler.get(); } @@ -281,7 +282,7 @@ CPDF_Parser::Error CPDF_Parser::SetEncryptHandler() { return err; m_pSecurityHandler = std::move(pSecurityHandler); - std::unique_ptr pCryptoHandler( + std::unique_ptr pCryptoHandler( m_pSecurityHandler->CreateCryptoHandler()); if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler.get())) return HANDLER_ERROR; diff --git a/core/src/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.cpp b/core/src/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.cpp new file mode 100644 index 0000000000..d7a6fd59fe --- /dev/null +++ b/core/src/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.cpp @@ -0,0 +1,343 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/src/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.h" + +#include + +#include "core/include/fpdfapi/fpdf_parser.h" +#include "core/include/fpdfapi/cpdf_parser.h" +#include "core/include/fpdfapi/cpdf_simple_parser.h" +#include "core/include/fpdfapi/ipdf_security_handler.h" +#include "core/include/fdrm/fx_crypt.h" + +IPDF_CryptoHandler::~IPDF_CryptoHandler() {} + +void IPDF_CryptoHandler::Decrypt(FX_DWORD objnum, + FX_DWORD gennum, + CFX_ByteString& str) { + CFX_BinaryBuf dest_buf; + void* context = DecryptStart(objnum, gennum); + DecryptStream(context, (const uint8_t*)str, str.GetLength(), dest_buf); + DecryptFinish(context, dest_buf); + str = dest_buf; +} + +void CPDF_StandardCryptoHandler::CryptBlock(FX_BOOL bEncrypt, + FX_DWORD objnum, + FX_DWORD gennum, + const uint8_t* src_buf, + FX_DWORD src_size, + uint8_t* dest_buf, + FX_DWORD& dest_size) { + if (m_Cipher == FXCIPHER_NONE) { + FXSYS_memcpy(dest_buf, src_buf, src_size); + return; + } + uint8_t realkey[16]; + int realkeylen = 16; + if (m_Cipher != FXCIPHER_AES || m_KeyLen != 32) { + uint8_t key1[32]; + FXSYS_memcpy(key1, m_EncryptKey, m_KeyLen); + key1[m_KeyLen + 0] = (uint8_t)objnum; + key1[m_KeyLen + 1] = (uint8_t)(objnum >> 8); + key1[m_KeyLen + 2] = (uint8_t)(objnum >> 16); + key1[m_KeyLen + 3] = (uint8_t)gennum; + key1[m_KeyLen + 4] = (uint8_t)(gennum >> 8); + FXSYS_memcpy(key1 + m_KeyLen, &objnum, 3); + FXSYS_memcpy(key1 + m_KeyLen + 3, &gennum, 2); + if (m_Cipher == FXCIPHER_AES) { + FXSYS_memcpy(key1 + m_KeyLen + 5, "sAlT", 4); + } + CRYPT_MD5Generate( + key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey); + realkeylen = m_KeyLen + 5; + if (realkeylen > 16) { + realkeylen = 16; + } + } + if (m_Cipher == FXCIPHER_AES) { + CRYPT_AESSetKey(m_pAESContext, 16, m_KeyLen == 32 ? m_EncryptKey : realkey, + m_KeyLen, bEncrypt); + if (bEncrypt) { + uint8_t iv[16]; + for (int i = 0; i < 16; i++) { + iv[i] = (uint8_t)rand(); + } + CRYPT_AESSetIV(m_pAESContext, iv); + FXSYS_memcpy(dest_buf, iv, 16); + int nblocks = src_size / 16; + CRYPT_AESEncrypt(m_pAESContext, dest_buf + 16, src_buf, nblocks * 16); + uint8_t padding[16]; + FXSYS_memcpy(padding, src_buf + nblocks * 16, src_size % 16); + FXSYS_memset(padding + src_size % 16, 16 - src_size % 16, + 16 - src_size % 16); + CRYPT_AESEncrypt(m_pAESContext, dest_buf + nblocks * 16 + 16, padding, + 16); + dest_size = 32 + nblocks * 16; + } else { + CRYPT_AESSetIV(m_pAESContext, src_buf); + CRYPT_AESDecrypt(m_pAESContext, dest_buf, src_buf + 16, src_size - 16); + dest_size = src_size - 16; + dest_size -= dest_buf[dest_size - 1]; + } + } else { + ASSERT(dest_size == src_size); + if (dest_buf != src_buf) { + FXSYS_memcpy(dest_buf, src_buf, src_size); + } + CRYPT_ArcFourCryptBlock(dest_buf, dest_size, realkey, realkeylen); + } +} + +struct AESCryptContext { + uint8_t m_Context[2048]; + FX_BOOL m_bIV; + uint8_t m_Block[16]; + FX_DWORD m_BlockOffset; +}; + +void* CPDF_StandardCryptoHandler::CryptStart(FX_DWORD objnum, + FX_DWORD gennum, + FX_BOOL bEncrypt) { + if (m_Cipher == FXCIPHER_NONE) { + return this; + } + if (m_Cipher == FXCIPHER_AES && m_KeyLen == 32) { + AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1); + pContext->m_bIV = TRUE; + pContext->m_BlockOffset = 0; + CRYPT_AESSetKey(pContext->m_Context, 16, m_EncryptKey, 32, bEncrypt); + if (bEncrypt) { + for (int i = 0; i < 16; i++) { + pContext->m_Block[i] = (uint8_t)rand(); + } + CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); + } + return pContext; + } + uint8_t key1[48]; + FXSYS_memcpy(key1, m_EncryptKey, m_KeyLen); + FXSYS_memcpy(key1 + m_KeyLen, &objnum, 3); + FXSYS_memcpy(key1 + m_KeyLen + 3, &gennum, 2); + if (m_Cipher == FXCIPHER_AES) { + FXSYS_memcpy(key1 + m_KeyLen + 5, "sAlT", 4); + } + uint8_t realkey[16]; + CRYPT_MD5Generate( + key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey); + int realkeylen = m_KeyLen + 5; + if (realkeylen > 16) { + realkeylen = 16; + } + if (m_Cipher == FXCIPHER_AES) { + AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1); + pContext->m_bIV = TRUE; + pContext->m_BlockOffset = 0; + CRYPT_AESSetKey(pContext->m_Context, 16, realkey, 16, bEncrypt); + if (bEncrypt) { + for (int i = 0; i < 16; i++) { + pContext->m_Block[i] = (uint8_t)rand(); + } + CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); + } + return pContext; + } + void* pContext = FX_Alloc(uint8_t, 1040); + CRYPT_ArcFourSetup(pContext, realkey, realkeylen); + return pContext; +} +FX_BOOL CPDF_StandardCryptoHandler::CryptStream(void* context, + const uint8_t* src_buf, + FX_DWORD src_size, + CFX_BinaryBuf& dest_buf, + FX_BOOL bEncrypt) { + if (!context) { + return FALSE; + } + if (m_Cipher == FXCIPHER_NONE) { + dest_buf.AppendBlock(src_buf, src_size); + return TRUE; + } + if (m_Cipher == FXCIPHER_RC4) { + int old_size = dest_buf.GetSize(); + dest_buf.AppendBlock(src_buf, src_size); + CRYPT_ArcFourCrypt(context, dest_buf.GetBuffer() + old_size, src_size); + return TRUE; + } + AESCryptContext* pContext = (AESCryptContext*)context; + if (pContext->m_bIV && bEncrypt) { + dest_buf.AppendBlock(pContext->m_Block, 16); + pContext->m_bIV = FALSE; + } + FX_DWORD src_off = 0; + FX_DWORD src_left = src_size; + while (1) { + FX_DWORD copy_size = 16 - pContext->m_BlockOffset; + if (copy_size > src_left) { + copy_size = src_left; + } + FXSYS_memcpy(pContext->m_Block + pContext->m_BlockOffset, src_buf + src_off, + copy_size); + src_off += copy_size; + src_left -= copy_size; + pContext->m_BlockOffset += copy_size; + if (pContext->m_BlockOffset == 16) { + if (!bEncrypt && pContext->m_bIV) { + CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); + pContext->m_bIV = FALSE; + pContext->m_BlockOffset = 0; + } else if (src_off < src_size) { + uint8_t block_buf[16]; + if (bEncrypt) { + CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, + 16); + } else { + CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, + 16); + } + dest_buf.AppendBlock(block_buf, 16); + pContext->m_BlockOffset = 0; + } + } + if (!src_left) { + break; + } + } + return TRUE; +} +FX_BOOL CPDF_StandardCryptoHandler::CryptFinish(void* context, + CFX_BinaryBuf& dest_buf, + FX_BOOL bEncrypt) { + if (!context) { + return FALSE; + } + if (m_Cipher == FXCIPHER_NONE) { + return TRUE; + } + if (m_Cipher == FXCIPHER_RC4) { + FX_Free(context); + return TRUE; + } + AESCryptContext* pContext = (AESCryptContext*)context; + if (bEncrypt) { + uint8_t block_buf[16]; + if (pContext->m_BlockOffset == 16) { + CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); + dest_buf.AppendBlock(block_buf, 16); + pContext->m_BlockOffset = 0; + } + FXSYS_memset(pContext->m_Block + pContext->m_BlockOffset, + (uint8_t)(16 - pContext->m_BlockOffset), + 16 - pContext->m_BlockOffset); + CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); + dest_buf.AppendBlock(block_buf, 16); + } else if (pContext->m_BlockOffset == 16) { + uint8_t block_buf[16]; + CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); + if (block_buf[15] <= 16) { + dest_buf.AppendBlock(block_buf, 16 - block_buf[15]); + } + } + FX_Free(pContext); + return TRUE; +} +void* CPDF_StandardCryptoHandler::DecryptStart(FX_DWORD objnum, + FX_DWORD gennum) { + return CryptStart(objnum, gennum, FALSE); +} +FX_DWORD CPDF_StandardCryptoHandler::DecryptGetSize(FX_DWORD src_size) { + return m_Cipher == FXCIPHER_AES ? src_size - 16 : src_size; +} + +FX_BOOL CPDF_StandardCryptoHandler::Init( + CPDF_Dictionary* pEncryptDict, + IPDF_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) { + FXSYS_memcpy(m_EncryptKey, key, m_KeyLen); + } + if (m_Cipher == FXCIPHER_AES) { + m_pAESContext = FX_Alloc(uint8_t, 2048); + } + return TRUE; +} + +FX_BOOL CPDF_StandardCryptoHandler::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; + FXSYS_memcpy(m_EncryptKey, key, keylen); + if (m_Cipher == FXCIPHER_AES) { + m_pAESContext = FX_Alloc(uint8_t, 2048); + } + return TRUE; +} +FX_BOOL CPDF_StandardCryptoHandler::DecryptStream(void* context, + const uint8_t* src_buf, + FX_DWORD src_size, + CFX_BinaryBuf& dest_buf) { + return CryptStream(context, src_buf, src_size, dest_buf, FALSE); +} +FX_BOOL CPDF_StandardCryptoHandler::DecryptFinish(void* context, + CFX_BinaryBuf& dest_buf) { + return CryptFinish(context, dest_buf, FALSE); +} +FX_DWORD CPDF_StandardCryptoHandler::EncryptGetSize(FX_DWORD objnum, + FX_DWORD version, + const uint8_t* src_buf, + FX_DWORD src_size) { + if (m_Cipher == FXCIPHER_AES) { + return src_size + 32; + } + return src_size; +} +FX_BOOL CPDF_StandardCryptoHandler::EncryptContent(FX_DWORD objnum, + FX_DWORD gennum, + const uint8_t* src_buf, + FX_DWORD src_size, + uint8_t* dest_buf, + FX_DWORD& dest_size) { + CryptBlock(TRUE, objnum, gennum, src_buf, src_size, dest_buf, dest_size); + return TRUE; +} +CPDF_StandardCryptoHandler::CPDF_StandardCryptoHandler() { + m_pAESContext = NULL; + m_Cipher = FXCIPHER_NONE; + m_KeyLen = 0; +} +CPDF_StandardCryptoHandler::~CPDF_StandardCryptoHandler() { + FX_Free(m_pAESContext); +} diff --git a/core/src/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.h b/core/src/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.h new file mode 100644 index 0000000000..3ef1f7143f --- /dev/null +++ b/core/src/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.h @@ -0,0 +1,64 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_SRC_FPDFAPI_FPDF_PARSER_CPDF_STANDARD_CRYPTO_HANDLER_H_ +#define CORE_SRC_FPDFAPI_FPDF_PARSER_CPDF_STANDARD_CRYPTO_HANDLER_H_ + +#include "core/include/fpdfapi/ipdf_crypto_handler.h" + +class CPDF_StandardCryptoHandler : public IPDF_CryptoHandler { + public: + CPDF_StandardCryptoHandler(); + ~CPDF_StandardCryptoHandler() override; + + // IPDF_CryptoHandler + FX_BOOL Init(CPDF_Dictionary* pEncryptDict, + IPDF_SecurityHandler* pSecurityHandler) override; + FX_DWORD DecryptGetSize(FX_DWORD src_size) override; + void* DecryptStart(FX_DWORD objnum, FX_DWORD gennum) override; + FX_BOOL DecryptStream(void* context, + const uint8_t* src_buf, + FX_DWORD src_size, + CFX_BinaryBuf& dest_buf) override; + FX_BOOL DecryptFinish(void* context, CFX_BinaryBuf& dest_buf) override; + FX_DWORD EncryptGetSize(FX_DWORD objnum, + FX_DWORD version, + const uint8_t* src_buf, + FX_DWORD src_size) override; + FX_BOOL EncryptContent(FX_DWORD objnum, + FX_DWORD version, + const uint8_t* src_buf, + FX_DWORD src_size, + uint8_t* dest_buf, + FX_DWORD& dest_size) override; + + FX_BOOL Init(int cipher, const uint8_t* key, int keylen); + + protected: + virtual void CryptBlock(FX_BOOL bEncrypt, + FX_DWORD objnum, + FX_DWORD gennum, + const uint8_t* src_buf, + FX_DWORD src_size, + uint8_t* dest_buf, + FX_DWORD& dest_size); + virtual void* CryptStart(FX_DWORD objnum, FX_DWORD gennum, FX_BOOL bEncrypt); + virtual FX_BOOL CryptStream(void* context, + const uint8_t* src_buf, + FX_DWORD src_size, + CFX_BinaryBuf& dest_buf, + FX_BOOL bEncrypt); + virtual FX_BOOL CryptFinish(void* context, + CFX_BinaryBuf& dest_buf, + FX_BOOL bEncrypt); + + uint8_t m_EncryptKey[32]; + int m_KeyLen; + int m_Cipher; + uint8_t* m_pAESContext; +}; + +#endif // CORE_SRC_FPDFAPI_FPDF_PARSER_CPDF_STANDARD_CRYPTO_HANDLER_H_ diff --git a/core/src/fpdfapi/fpdf_parser/cpdf_standard_security_handler.cpp b/core/src/fpdfapi/fpdf_parser/cpdf_standard_security_handler.cpp index dab9b1f89e..60d6ba47dd 100644 --- a/core/src/fpdfapi/fpdf_parser/cpdf_standard_security_handler.cpp +++ b/core/src/fpdfapi/fpdf_parser/cpdf_standard_security_handler.cpp @@ -11,6 +11,7 @@ #include "core/include/fdrm/fx_crypt.h" #include "core/include/fpdfapi/cpdf_parser.h" #include "core/include/fpdfapi/fpdf_parser.h" +#include "core/src/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.h" namespace { @@ -78,7 +79,7 @@ CPDF_StandardSecurityHandler::CPDF_StandardSecurityHandler() { CPDF_StandardSecurityHandler::~CPDF_StandardSecurityHandler() {} -CPDF_CryptoHandler* CPDF_StandardSecurityHandler::CreateCryptoHandler() { +IPDF_CryptoHandler* CPDF_StandardSecurityHandler::CreateCryptoHandler() { return new CPDF_StandardCryptoHandler; } diff --git a/core/src/fpdfapi/fpdf_parser/cpdf_standard_security_handler.h b/core/src/fpdfapi/fpdf_parser/cpdf_standard_security_handler.h index 27aeaa8bc0..fa761a1846 100644 --- a/core/src/fpdfapi/fpdf_parser/cpdf_standard_security_handler.h +++ b/core/src/fpdfapi/fpdf_parser/cpdf_standard_security_handler.h @@ -27,7 +27,7 @@ class CPDF_StandardSecurityHandler : public IPDF_SecurityHandler { const uint8_t*& buffer, int& keylen) override; FX_BOOL IsMetadataEncrypted() override; - CPDF_CryptoHandler* CreateCryptoHandler() override; + IPDF_CryptoHandler* CreateCryptoHandler() override; void OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray, diff --git a/core/src/fpdfapi/fpdf_parser/cpdf_syntax_parser.cpp b/core/src/fpdfapi/fpdf_parser/cpdf_syntax_parser.cpp index 151139e4a4..f635e02e3a 100644 --- a/core/src/fpdfapi/fpdf_parser/cpdf_syntax_parser.cpp +++ b/core/src/fpdfapi/fpdf_parser/cpdf_syntax_parser.cpp @@ -10,6 +10,7 @@ #include "core/include/fpdfapi/fpdf_module.h" #include "core/include/fpdfapi/fpdf_parser.h" +#include "core/include/fpdfapi/ipdf_crypto_handler.h" #include "core/include/fxcrt/fx_ext.h" #include "core/src/fpdfapi/fpdf_parser/fpdf_parser_utility.h" #include "third_party/base/numerics/safe_math.h" @@ -636,7 +637,7 @@ CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict, const CFX_ByteStringC kEndStreamStr("endstream"); const CFX_ByteStringC kEndObjStr("endobj"); - CPDF_CryptoHandler* pCryptoHandler = + IPDF_CryptoHandler* pCryptoHandler = objnum == (FX_DWORD)m_MetadataObjnum ? nullptr : m_pCryptoHandler.get(); if (!pCryptoHandler) { FX_BOOL bSearchForKeyword = TRUE; @@ -974,6 +975,6 @@ FX_FILESIZE CPDF_SyntaxParser::FindTag(const CFX_ByteStringC& tag, } void CPDF_SyntaxParser::SetEncrypt( - std::unique_ptr pCryptoHandler) { + std::unique_ptr pCryptoHandler) { m_pCryptoHandler = std::move(pCryptoHandler); } diff --git a/core/src/fpdfapi/fpdf_parser/cpdf_syntax_parser.h b/core/src/fpdfapi/fpdf_parser/cpdf_syntax_parser.h index 44c98eafd8..c259efb1ee 100644 --- a/core/src/fpdfapi/fpdf_parser/cpdf_syntax_parser.h +++ b/core/src/fpdfapi/fpdf_parser/cpdf_syntax_parser.h @@ -11,12 +11,12 @@ #include "core/include/fxcrt/fx_basic.h" -class CPDF_CryptoHandler; +class CPDF_Dictionary; class CPDF_IndirectObjectHolder; class CPDF_Object; -class CPDF_Dictionary; class CPDF_Stream; class IFX_FileRead; +class IPDF_CryptoHandler; class CPDF_SyntaxParser { public: @@ -49,7 +49,7 @@ class CPDF_SyntaxParser { FX_FILESIZE limit); FX_FILESIZE FindTag(const CFX_ByteStringC& tag, FX_FILESIZE limit); - void SetEncrypt(std::unique_ptr pCryptoHandler); + void SetEncrypt(std::unique_ptr pCryptoHandler); FX_BOOL ReadBlock(uint8_t* pBuf, FX_DWORD size); FX_BOOL GetCharAt(FX_FILESIZE pos, uint8_t& ch); @@ -88,7 +88,7 @@ class CPDF_SyntaxParser { uint8_t* m_pFileBuf; FX_DWORD m_BufSize; FX_FILESIZE m_BufOffset; - std::unique_ptr m_pCryptoHandler; + std::unique_ptr m_pCryptoHandler; uint8_t m_WordBuffer[257]; FX_DWORD m_WordSize; }; diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_encrypt.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_encrypt.cpp deleted file mode 100644 index 5d710657be..0000000000 --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_encrypt.cpp +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/include/fpdfapi/fpdf_parser.h" - -#include "core/include/fpdfapi/cpdf_parser.h" -#include "core/include/fpdfapi/cpdf_simple_parser.h" -#include "core/include/fpdfapi/ipdf_security_handler.h" -#include "core/include/fdrm/fx_crypt.h" - -struct PDF_CRYPTOITEM { - int32_t m_Cipher; - int32_t m_KeyLen; - FX_BOOL m_bChecked; - CPDF_StandardCryptoHandler* m_pCryptoHandler; -}; - -void CPDF_StandardCryptoHandler::CryptBlock(FX_BOOL bEncrypt, - FX_DWORD objnum, - FX_DWORD gennum, - const uint8_t* src_buf, - FX_DWORD src_size, - uint8_t* dest_buf, - FX_DWORD& dest_size) { - if (m_Cipher == FXCIPHER_NONE) { - FXSYS_memcpy(dest_buf, src_buf, src_size); - return; - } - uint8_t realkey[16]; - int realkeylen = 16; - if (m_Cipher != FXCIPHER_AES || m_KeyLen != 32) { - uint8_t key1[32]; - FXSYS_memcpy(key1, m_EncryptKey, m_KeyLen); - key1[m_KeyLen + 0] = (uint8_t)objnum; - key1[m_KeyLen + 1] = (uint8_t)(objnum >> 8); - key1[m_KeyLen + 2] = (uint8_t)(objnum >> 16); - key1[m_KeyLen + 3] = (uint8_t)gennum; - key1[m_KeyLen + 4] = (uint8_t)(gennum >> 8); - FXSYS_memcpy(key1 + m_KeyLen, &objnum, 3); - FXSYS_memcpy(key1 + m_KeyLen + 3, &gennum, 2); - if (m_Cipher == FXCIPHER_AES) { - FXSYS_memcpy(key1 + m_KeyLen + 5, "sAlT", 4); - } - CRYPT_MD5Generate( - key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey); - realkeylen = m_KeyLen + 5; - if (realkeylen > 16) { - realkeylen = 16; - } - } - if (m_Cipher == FXCIPHER_AES) { - CRYPT_AESSetKey(m_pAESContext, 16, m_KeyLen == 32 ? m_EncryptKey : realkey, - m_KeyLen, bEncrypt); - if (bEncrypt) { - uint8_t iv[16]; - for (int i = 0; i < 16; i++) { - iv[i] = (uint8_t)rand(); - } - CRYPT_AESSetIV(m_pAESContext, iv); - FXSYS_memcpy(dest_buf, iv, 16); - int nblocks = src_size / 16; - CRYPT_AESEncrypt(m_pAESContext, dest_buf + 16, src_buf, nblocks * 16); - uint8_t padding[16]; - FXSYS_memcpy(padding, src_buf + nblocks * 16, src_size % 16); - FXSYS_memset(padding + src_size % 16, 16 - src_size % 16, - 16 - src_size % 16); - CRYPT_AESEncrypt(m_pAESContext, dest_buf + nblocks * 16 + 16, padding, - 16); - dest_size = 32 + nblocks * 16; - } else { - CRYPT_AESSetIV(m_pAESContext, src_buf); - CRYPT_AESDecrypt(m_pAESContext, dest_buf, src_buf + 16, src_size - 16); - dest_size = src_size - 16; - dest_size -= dest_buf[dest_size - 1]; - } - } else { - ASSERT(dest_size == src_size); - if (dest_buf != src_buf) { - FXSYS_memcpy(dest_buf, src_buf, src_size); - } - CRYPT_ArcFourCryptBlock(dest_buf, dest_size, realkey, realkeylen); - } -} - -struct AESCryptContext { - uint8_t m_Context[2048]; - FX_BOOL m_bIV; - uint8_t m_Block[16]; - FX_DWORD m_BlockOffset; -}; - -void* CPDF_StandardCryptoHandler::CryptStart(FX_DWORD objnum, - FX_DWORD gennum, - FX_BOOL bEncrypt) { - if (m_Cipher == FXCIPHER_NONE) { - return this; - } - if (m_Cipher == FXCIPHER_AES && m_KeyLen == 32) { - AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1); - pContext->m_bIV = TRUE; - pContext->m_BlockOffset = 0; - CRYPT_AESSetKey(pContext->m_Context, 16, m_EncryptKey, 32, bEncrypt); - if (bEncrypt) { - for (int i = 0; i < 16; i++) { - pContext->m_Block[i] = (uint8_t)rand(); - } - CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); - } - return pContext; - } - uint8_t key1[48]; - FXSYS_memcpy(key1, m_EncryptKey, m_KeyLen); - FXSYS_memcpy(key1 + m_KeyLen, &objnum, 3); - FXSYS_memcpy(key1 + m_KeyLen + 3, &gennum, 2); - if (m_Cipher == FXCIPHER_AES) { - FXSYS_memcpy(key1 + m_KeyLen + 5, "sAlT", 4); - } - uint8_t realkey[16]; - CRYPT_MD5Generate( - key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey); - int realkeylen = m_KeyLen + 5; - if (realkeylen > 16) { - realkeylen = 16; - } - if (m_Cipher == FXCIPHER_AES) { - AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1); - pContext->m_bIV = TRUE; - pContext->m_BlockOffset = 0; - CRYPT_AESSetKey(pContext->m_Context, 16, realkey, 16, bEncrypt); - if (bEncrypt) { - for (int i = 0; i < 16; i++) { - pContext->m_Block[i] = (uint8_t)rand(); - } - CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); - } - return pContext; - } - void* pContext = FX_Alloc(uint8_t, 1040); - CRYPT_ArcFourSetup(pContext, realkey, realkeylen); - return pContext; -} -FX_BOOL CPDF_StandardCryptoHandler::CryptStream(void* context, - const uint8_t* src_buf, - FX_DWORD src_size, - CFX_BinaryBuf& dest_buf, - FX_BOOL bEncrypt) { - if (!context) { - return FALSE; - } - if (m_Cipher == FXCIPHER_NONE) { - dest_buf.AppendBlock(src_buf, src_size); - return TRUE; - } - if (m_Cipher == FXCIPHER_RC4) { - int old_size = dest_buf.GetSize(); - dest_buf.AppendBlock(src_buf, src_size); - CRYPT_ArcFourCrypt(context, dest_buf.GetBuffer() + old_size, src_size); - return TRUE; - } - AESCryptContext* pContext = (AESCryptContext*)context; - if (pContext->m_bIV && bEncrypt) { - dest_buf.AppendBlock(pContext->m_Block, 16); - pContext->m_bIV = FALSE; - } - FX_DWORD src_off = 0; - FX_DWORD src_left = src_size; - while (1) { - FX_DWORD copy_size = 16 - pContext->m_BlockOffset; - if (copy_size > src_left) { - copy_size = src_left; - } - FXSYS_memcpy(pContext->m_Block + pContext->m_BlockOffset, src_buf + src_off, - copy_size); - src_off += copy_size; - src_left -= copy_size; - pContext->m_BlockOffset += copy_size; - if (pContext->m_BlockOffset == 16) { - if (!bEncrypt && pContext->m_bIV) { - CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); - pContext->m_bIV = FALSE; - pContext->m_BlockOffset = 0; - } else if (src_off < src_size) { - uint8_t block_buf[16]; - if (bEncrypt) { - CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, - 16); - } else { - CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, - 16); - } - dest_buf.AppendBlock(block_buf, 16); - pContext->m_BlockOffset = 0; - } - } - if (!src_left) { - break; - } - } - return TRUE; -} -FX_BOOL CPDF_StandardCryptoHandler::CryptFinish(void* context, - CFX_BinaryBuf& dest_buf, - FX_BOOL bEncrypt) { - if (!context) { - return FALSE; - } - if (m_Cipher == FXCIPHER_NONE) { - return TRUE; - } - if (m_Cipher == FXCIPHER_RC4) { - FX_Free(context); - return TRUE; - } - AESCryptContext* pContext = (AESCryptContext*)context; - if (bEncrypt) { - uint8_t block_buf[16]; - if (pContext->m_BlockOffset == 16) { - CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); - dest_buf.AppendBlock(block_buf, 16); - pContext->m_BlockOffset = 0; - } - FXSYS_memset(pContext->m_Block + pContext->m_BlockOffset, - (uint8_t)(16 - pContext->m_BlockOffset), - 16 - pContext->m_BlockOffset); - CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); - dest_buf.AppendBlock(block_buf, 16); - } else if (pContext->m_BlockOffset == 16) { - uint8_t block_buf[16]; - CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); - if (block_buf[15] <= 16) { - dest_buf.AppendBlock(block_buf, 16 - block_buf[15]); - } - } - FX_Free(pContext); - return TRUE; -} -void* CPDF_StandardCryptoHandler::DecryptStart(FX_DWORD objnum, - FX_DWORD gennum) { - return CryptStart(objnum, gennum, FALSE); -} -FX_DWORD CPDF_StandardCryptoHandler::DecryptGetSize(FX_DWORD src_size) { - return m_Cipher == FXCIPHER_AES ? src_size - 16 : src_size; -} - -FX_BOOL CPDF_StandardCryptoHandler::Init( - CPDF_Dictionary* pEncryptDict, - IPDF_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) { - FXSYS_memcpy(m_EncryptKey, key, m_KeyLen); - } - if (m_Cipher == FXCIPHER_AES) { - m_pAESContext = FX_Alloc(uint8_t, 2048); - } - return TRUE; -} - -FX_BOOL CPDF_StandardCryptoHandler::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; - FXSYS_memcpy(m_EncryptKey, key, keylen); - if (m_Cipher == FXCIPHER_AES) { - m_pAESContext = FX_Alloc(uint8_t, 2048); - } - return TRUE; -} -FX_BOOL CPDF_StandardCryptoHandler::DecryptStream(void* context, - const uint8_t* src_buf, - FX_DWORD src_size, - CFX_BinaryBuf& dest_buf) { - return CryptStream(context, src_buf, src_size, dest_buf, FALSE); -} -FX_BOOL CPDF_StandardCryptoHandler::DecryptFinish(void* context, - CFX_BinaryBuf& dest_buf) { - return CryptFinish(context, dest_buf, FALSE); -} -FX_DWORD CPDF_StandardCryptoHandler::EncryptGetSize(FX_DWORD objnum, - FX_DWORD version, - const uint8_t* src_buf, - FX_DWORD src_size) { - if (m_Cipher == FXCIPHER_AES) { - return src_size + 32; - } - return src_size; -} -FX_BOOL CPDF_StandardCryptoHandler::EncryptContent(FX_DWORD objnum, - FX_DWORD gennum, - const uint8_t* src_buf, - FX_DWORD src_size, - uint8_t* dest_buf, - FX_DWORD& dest_size) { - CryptBlock(TRUE, objnum, gennum, src_buf, src_size, dest_buf, dest_size); - return TRUE; -} -void CPDF_CryptoHandler::Decrypt(FX_DWORD objnum, - FX_DWORD gennum, - CFX_ByteString& str) { - CFX_BinaryBuf dest_buf; - void* context = DecryptStart(objnum, gennum); - DecryptStream(context, (const uint8_t*)str, str.GetLength(), dest_buf); - DecryptFinish(context, dest_buf); - str = dest_buf; -} -CPDF_StandardCryptoHandler::CPDF_StandardCryptoHandler() { - m_pAESContext = NULL; - m_Cipher = FXCIPHER_NONE; - m_KeyLen = 0; -} -CPDF_StandardCryptoHandler::~CPDF_StandardCryptoHandler() { - FX_Free(m_pAESContext); -} -- cgit v1.2.3