From 2fa0e13ec2a79cc85d5e018a6420e677b28160cc Mon Sep 17 00:00:00 2001 From: dsinclair Date: Tue, 19 Apr 2016 10:32:45 -0700 Subject: Remove IPDF_CryptoHandler and IPDF_SecurityHandler. This CL replaces the interfaces with the concrete classes. The concrete classes are also renamed to remove the Standard from their names. BUG=pdfium:468 Review URL: https://codereview.chromium.org/1898173002 --- core/fpdfapi/fpdf_edit/fpdf_edit_create.cpp | 22 +- core/fpdfapi/fpdf_edit/include/cpdf_creator.h | 6 +- core/fpdfapi/fpdf_parser/cpdf_crypto_handler.cpp | 337 ++++++++++ core/fpdfapi/fpdf_parser/cpdf_crypto_handler.h | 67 ++ core/fpdfapi/fpdf_parser/cpdf_parser.cpp | 12 +- core/fpdfapi/fpdf_parser/cpdf_security_handler.cpp | 707 ++++++++++++++++++++ core/fpdfapi/fpdf_parser/cpdf_security_handler.h | 109 ++++ .../fpdf_parser/cpdf_standard_crypto_handler.cpp | 342 ---------- .../fpdf_parser/cpdf_standard_crypto_handler.h | 64 -- .../fpdf_parser/cpdf_standard_security_handler.cpp | 715 --------------------- .../fpdf_parser/cpdf_standard_security_handler.h | 105 --- core/fpdfapi/fpdf_parser/cpdf_syntax_parser.cpp | 6 +- core/fpdfapi/fpdf_parser/cpdf_syntax_parser.h | 6 +- core/fpdfapi/fpdf_parser/include/cpdf_parser.h | 8 +- core/fpdfapi/fpdf_parser/ipdf_crypto_handler.h | 45 -- core/fpdfapi/fpdf_parser/ipdf_security_handler.h | 36 -- 16 files changed, 1250 insertions(+), 1337 deletions(-) create mode 100644 core/fpdfapi/fpdf_parser/cpdf_crypto_handler.cpp create mode 100644 core/fpdfapi/fpdf_parser/cpdf_crypto_handler.h create mode 100644 core/fpdfapi/fpdf_parser/cpdf_security_handler.cpp create mode 100644 core/fpdfapi/fpdf_parser/cpdf_security_handler.h delete mode 100644 core/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.cpp delete mode 100644 core/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.h delete mode 100644 core/fpdfapi/fpdf_parser/cpdf_standard_security_handler.cpp delete mode 100644 core/fpdfapi/fpdf_parser/cpdf_standard_security_handler.h delete mode 100644 core/fpdfapi/fpdf_parser/ipdf_crypto_handler.h delete mode 100644 core/fpdfapi/fpdf_parser/ipdf_security_handler.h (limited to 'core') diff --git a/core/fpdfapi/fpdf_edit/fpdf_edit_create.cpp b/core/fpdfapi/fpdf_edit/fpdf_edit_create.cpp index 0bd07a1819..7570a796e4 100644 --- a/core/fpdfapi/fpdf_edit/fpdf_edit_create.cpp +++ b/core/fpdfapi/fpdf_edit/fpdf_edit_create.cpp @@ -9,8 +9,8 @@ #include #include "core/fpdfapi/fpdf_edit/include/cpdf_creator.h" -#include "core/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.h" -#include "core/fpdfapi/fpdf_parser/cpdf_standard_security_handler.h" +#include "core/fpdfapi/fpdf_parser/cpdf_crypto_handler.h" +#include "core/fpdfapi/fpdf_parser/cpdf_security_handler.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" @@ -20,7 +20,6 @@ #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_string.h" #include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h" -#include "core/fpdfapi/fpdf_parser/ipdf_crypto_handler.h" #include "core/fxcrt/include/fx_ext.h" #include "third_party/base/stl_util.h" @@ -479,7 +478,7 @@ class CPDF_Encryptor { public: CPDF_Encryptor(); ~CPDF_Encryptor(); - FX_BOOL Initialize(IPDF_CryptoHandler* pHandler, + FX_BOOL Initialize(CPDF_CryptoHandler* pHandler, int objnum, uint8_t* src_data, uint32_t src_size); @@ -492,7 +491,7 @@ CPDF_Encryptor::CPDF_Encryptor() { m_dwSize = 0; m_bNewBuf = FALSE; } -FX_BOOL CPDF_Encryptor::Initialize(IPDF_CryptoHandler* pHandler, +FX_BOOL CPDF_Encryptor::Initialize(CPDF_CryptoHandler* pHandler, int objnum, uint8_t* src_data, uint32_t src_size) { @@ -549,7 +548,7 @@ FX_FILESIZE CPDF_ObjectStream::End(CPDF_Creator* pCreator) { return 0; } CFX_FileBufferArchive* pFile = &pCreator->m_File; - IPDF_CryptoHandler* pHandler = pCreator->m_pCryptoHandler; + CPDF_CryptoHandler* pHandler = pCreator->m_pCryptoHandler; FX_FILESIZE ObjOffset = pCreator->m_Offset; if (!m_dwObjNum) { m_dwObjNum = ++pCreator->m_dwLastObjNum; @@ -1025,7 +1024,7 @@ int32_t CPDF_Creator::AppendObjectNumberToXRef(uint32_t objnum) { } int32_t CPDF_Creator::WriteStream(const CPDF_Object* pStream, uint32_t objnum, - IPDF_CryptoHandler* pCrypto) { + CPDF_CryptoHandler* pCrypto) { CPDF_FlateEncoder encoder; encoder.Initialize(const_cast(pStream->AsStream()), pStream == m_pMetadata ? FALSE : m_bCompress); @@ -1068,7 +1067,7 @@ int32_t CPDF_Creator::WriteIndirectObj(uint32_t objnum, m_Offset += len; if (pObj->IsStream()) { - IPDF_CryptoHandler* pHandler = nullptr; + CPDF_CryptoHandler* pHandler = nullptr; pHandler = (pObj == m_pMetadata && !m_bEncryptMetadata) ? NULL : m_pCryptoHandler; if (WriteStream(pObj, objnum, pHandler) < 0) @@ -1148,7 +1147,7 @@ int32_t CPDF_Creator::WriteDirectObj(uint32_t objnum, encoder.Initialize(const_cast(pObj->AsStream()), m_bCompress); CPDF_Encryptor encryptor; - IPDF_CryptoHandler* pHandler = m_pCryptoHandler; + CPDF_CryptoHandler* pHandler = m_pCryptoHandler; encryptor.Initialize(pHandler, objnum, encoder.m_pData, encoder.m_dwSize); if ((uint32_t)encoder.m_pDict->GetIntegerBy("Length") != encryptor.m_dwSize) { @@ -2008,15 +2007,16 @@ void CPDF_Creator::InitID(FX_BOOL bDefault) { m_pIDArray->Add(m_pIDArray->GetObjectAt(0)->Clone()); if (m_pEncryptDict && !pOldIDArray && m_pParser && bNewId) { if (m_pEncryptDict->GetStringBy("Filter") == "Standard") { - CPDF_StandardSecurityHandler handler; CFX_ByteString user_pass = m_pParser->GetPassword(); uint32_t flag = PDF_ENCRYPT_CONTENT; + + CPDF_SecurityHandler handler; handler.OnCreate(m_pEncryptDict, m_pIDArray, user_pass.raw_str(), user_pass.GetLength(), flag); if (m_bNewCrypto) { delete m_pCryptoHandler; } - m_pCryptoHandler = new CPDF_StandardCryptoHandler; + m_pCryptoHandler = new CPDF_CryptoHandler; m_pCryptoHandler->Init(m_pEncryptDict, &handler); m_bNewCrypto = TRUE; m_bSecurityChanged = TRUE; diff --git a/core/fpdfapi/fpdf_edit/include/cpdf_creator.h b/core/fpdfapi/fpdf_edit/include/cpdf_creator.h index d6a1c1079a..e9490a3be7 100644 --- a/core/fpdfapi/fpdf_edit/include/cpdf_creator.h +++ b/core/fpdfapi/fpdf_edit/include/cpdf_creator.h @@ -10,12 +10,12 @@ #include "core/fxcrt/include/fx_basic.h" class CPDF_Array; +class CPDF_CryptoHandler; class CPDF_Dictionary; class CPDF_Document; class CPDF_Object; class CPDF_Parser; class CPDF_XRefStream; -class IPDF_CryptoHandler; #define FPDFCREATE_INCREMENTAL 1 #define FPDFCREATE_NO_ORIGINAL 2 @@ -69,7 +69,7 @@ class CPDF_Creator { int32_t WriteStream(const CPDF_Object* pStream, uint32_t objnum, - IPDF_CryptoHandler* pCrypto); + CPDF_CryptoHandler* pCrypto); CPDF_Document* m_pDocument; CPDF_Parser* m_pParser; @@ -79,7 +79,7 @@ class CPDF_Creator { uint32_t m_dwEnryptObjNum; FX_BOOL m_bEncryptCloned; FX_BOOL m_bStandardSecurity; - IPDF_CryptoHandler* m_pCryptoHandler; + CPDF_CryptoHandler* m_pCryptoHandler; FX_BOOL m_bNewCrypto; FX_BOOL m_bEncryptMetadata; CPDF_Object* m_pMetadata; diff --git a/core/fpdfapi/fpdf_parser/cpdf_crypto_handler.cpp b/core/fpdfapi/fpdf_parser/cpdf_crypto_handler.cpp new file mode 100644 index 0000000000..2d845d856a --- /dev/null +++ b/core/fpdfapi/fpdf_parser/cpdf_crypto_handler.cpp @@ -0,0 +1,337 @@ +// 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/fpdfapi/fpdf_parser/cpdf_crypto_handler.h" + +#include + +#include "core/fdrm/crypto/include/fx_crypt.h" +#include "core/fpdfapi/fpdf_parser/cpdf_security_handler.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_parser.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h" + +void CPDF_CryptoHandler::CryptBlock(FX_BOOL bEncrypt, + uint32_t objnum, + uint32_t gennum, + const uint8_t* src_buf, + uint32_t src_size, + uint8_t* dest_buf, + uint32_t& 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]; + uint32_t m_BlockOffset; +}; + +void* CPDF_CryptoHandler::CryptStart(uint32_t objnum, + uint32_t 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_CryptoHandler::CryptStream(void* context, + const uint8_t* src_buf, + uint32_t 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; + } + uint32_t src_off = 0; + uint32_t src_left = src_size; + while (1) { + uint32_t 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_CryptoHandler::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_CryptoHandler::Decrypt(uint32_t objnum, + uint32_t gennum, + CFX_ByteString& str) { + CFX_BinaryBuf dest_buf; + void* context = DecryptStart(objnum, gennum); + DecryptStream(context, str.raw_str(), str.GetLength(), dest_buf); + DecryptFinish(context, dest_buf); + str = CFX_ByteString(dest_buf.GetBuffer(), dest_buf.GetSize()); +} + +void* CPDF_CryptoHandler::DecryptStart(uint32_t objnum, uint32_t gennum) { + return CryptStart(objnum, gennum, FALSE); +} +uint32_t CPDF_CryptoHandler::DecryptGetSize(uint32_t src_size) { + return m_Cipher == FXCIPHER_AES ? src_size - 16 : src_size; +} + +FX_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) { + FXSYS_memcpy(m_EncryptKey, key, m_KeyLen); + } + if (m_Cipher == FXCIPHER_AES) { + m_pAESContext = FX_Alloc(uint8_t, 2048); + } + return TRUE; +} + +FX_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; + FXSYS_memcpy(m_EncryptKey, key, keylen); + if (m_Cipher == FXCIPHER_AES) { + m_pAESContext = FX_Alloc(uint8_t, 2048); + } + return TRUE; +} +FX_BOOL CPDF_CryptoHandler::DecryptStream(void* context, + const uint8_t* src_buf, + uint32_t src_size, + CFX_BinaryBuf& dest_buf) { + return CryptStream(context, src_buf, src_size, dest_buf, FALSE); +} +FX_BOOL CPDF_CryptoHandler::DecryptFinish(void* context, + CFX_BinaryBuf& dest_buf) { + return CryptFinish(context, dest_buf, FALSE); +} +uint32_t CPDF_CryptoHandler::EncryptGetSize(uint32_t objnum, + uint32_t version, + const uint8_t* src_buf, + uint32_t src_size) { + if (m_Cipher == FXCIPHER_AES) { + return src_size + 32; + } + return src_size; +} +FX_BOOL CPDF_CryptoHandler::EncryptContent(uint32_t objnum, + uint32_t gennum, + const uint8_t* src_buf, + uint32_t src_size, + uint8_t* dest_buf, + uint32_t& dest_size) { + CryptBlock(TRUE, objnum, gennum, src_buf, src_size, dest_buf, dest_size); + return TRUE; +} +CPDF_CryptoHandler::CPDF_CryptoHandler() { + m_pAESContext = NULL; + m_Cipher = FXCIPHER_NONE; + m_KeyLen = 0; +} +CPDF_CryptoHandler::~CPDF_CryptoHandler() { + FX_Free(m_pAESContext); +} diff --git a/core/fpdfapi/fpdf_parser/cpdf_crypto_handler.h b/core/fpdfapi/fpdf_parser/cpdf_crypto_handler.h new file mode 100644 index 0000000000..3edc47b7b0 --- /dev/null +++ b/core/fpdfapi/fpdf_parser/cpdf_crypto_handler.h @@ -0,0 +1,67 @@ +// 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_FPDFAPI_FPDF_PARSER_CPDF_CRYPTO_HANDLER_H_ +#define CORE_FPDFAPI_FPDF_PARSER_CPDF_CRYPTO_HANDLER_H_ + +#include "core/fxcrt/include/fx_basic.h" +#include "core/fxcrt/include/fx_string.h" +#include "core/fxcrt/include/fx_system.h" + +class CPDF_Dictionary; +class CPDF_SecurityHandler; + +class CPDF_CryptoHandler { + public: + CPDF_CryptoHandler(); + ~CPDF_CryptoHandler(); + + FX_BOOL Init(CPDF_Dictionary* pEncryptDict, + CPDF_SecurityHandler* pSecurityHandler); + uint32_t DecryptGetSize(uint32_t src_size); + void* DecryptStart(uint32_t objnum, uint32_t gennum); + void Decrypt(uint32_t objnum, uint32_t gennum, CFX_ByteString& str); + FX_BOOL DecryptStream(void* context, + const uint8_t* src_buf, + uint32_t src_size, + CFX_BinaryBuf& dest_buf); + FX_BOOL DecryptFinish(void* context, CFX_BinaryBuf& dest_buf); + uint32_t EncryptGetSize(uint32_t objnum, + uint32_t version, + const uint8_t* src_buf, + uint32_t src_size); + FX_BOOL EncryptContent(uint32_t objnum, + uint32_t version, + const uint8_t* src_buf, + uint32_t src_size, + uint8_t* dest_buf, + uint32_t& dest_size); + + FX_BOOL Init(int cipher, const uint8_t* key, int keylen); + + protected: + void CryptBlock(FX_BOOL bEncrypt, + uint32_t objnum, + uint32_t gennum, + const uint8_t* src_buf, + uint32_t src_size, + uint8_t* dest_buf, + uint32_t& dest_size); + void* CryptStart(uint32_t objnum, uint32_t gennum, FX_BOOL bEncrypt); + FX_BOOL CryptStream(void* context, + const uint8_t* src_buf, + uint32_t src_size, + CFX_BinaryBuf& dest_buf, + FX_BOOL bEncrypt); + 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_FPDFAPI_FPDF_PARSER_CPDF_CRYPTO_HANDLER_H_ diff --git a/core/fpdfapi/fpdf_parser/cpdf_parser.cpp b/core/fpdfapi/fpdf_parser/cpdf_parser.cpp index 7fed6a380c..1ec912ebee 100644 --- a/core/fpdfapi/fpdf_parser/cpdf_parser.cpp +++ b/core/fpdfapi/fpdf_parser/cpdf_parser.cpp @@ -8,7 +8,8 @@ #include -#include "core/fpdfapi/fpdf_parser/cpdf_standard_security_handler.h" +#include "core/fpdfapi/fpdf_parser/cpdf_crypto_handler.h" +#include "core/fpdfapi/fpdf_parser/cpdf_security_handler.h" #include "core/fpdfapi/fpdf_parser/cpdf_syntax_parser.h" #include "core/fpdfapi/fpdf_parser/fpdf_parser_utility.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" @@ -18,7 +19,6 @@ #include "core/fpdfapi/fpdf_parser/include/cpdf_reference.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h" -#include "core/fpdfapi/fpdf_parser/ipdf_crypto_handler.h" #include "core/fxcrt/include/fx_ext.h" #include "core/fxcrt/include/fx_safe_types.h" #include "third_party/base/stl_util.h" @@ -101,7 +101,7 @@ void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict) { m_pEncryptDict = pDict; } -IPDF_CryptoHandler* CPDF_Parser::GetCryptoHandler() { +CPDF_CryptoHandler* CPDF_Parser::GetCryptoHandler() { return m_pSyntax->m_pCryptoHandler.get(); } @@ -275,10 +275,10 @@ CPDF_Parser::Error CPDF_Parser::SetEncryptHandler() { if (m_pEncryptDict) { CFX_ByteString filter = m_pEncryptDict->GetStringBy("Filter"); - std::unique_ptr pSecurityHandler; + std::unique_ptr pSecurityHandler; Error err = HANDLER_ERROR; if (filter == "Standard") { - pSecurityHandler.reset(new CPDF_StandardSecurityHandler); + pSecurityHandler.reset(new CPDF_SecurityHandler); err = PASSWORD_ERROR; } if (!pSecurityHandler) @@ -288,7 +288,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/fpdfapi/fpdf_parser/cpdf_security_handler.cpp b/core/fpdfapi/fpdf_parser/cpdf_security_handler.cpp new file mode 100644 index 0000000000..38099e0328 --- /dev/null +++ b/core/fpdfapi/fpdf_parser/cpdf_security_handler.cpp @@ -0,0 +1,707 @@ +// 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/fpdfapi/fpdf_parser/cpdf_security_handler.h" + +#include + +#include "core/fdrm/crypto/include/fx_crypt.h" +#include "core/fpdfapi/fpdf_parser/cpdf_crypto_handler.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_object.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_parser.h" + +namespace { + +const uint8_t defpasscode[32] = { + 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, + 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, + 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a}; + +void CalcEncryptKey(CPDF_Dictionary* pEncrypt, + const uint8_t* password, + uint32_t pass_size, + uint8_t* key, + int keylen, + FX_BOOL bIgnoreMeta, + CPDF_Array* pIdArray) { + int revision = pEncrypt->GetIntegerBy("R"); + uint8_t passcode[32]; + for (uint32_t i = 0; i < 32; i++) { + passcode[i] = i < pass_size ? password[i] : defpasscode[i - pass_size]; + } + uint8_t md5[100]; + CRYPT_MD5Start(md5); + CRYPT_MD5Update(md5, passcode, 32); + CFX_ByteString okey = pEncrypt->GetStringBy("O"); + CRYPT_MD5Update(md5, (uint8_t*)okey.c_str(), okey.GetLength()); + uint32_t perm = pEncrypt->GetIntegerBy("P"); + CRYPT_MD5Update(md5, (uint8_t*)&perm, 4); + if (pIdArray) { + CFX_ByteString id = pIdArray->GetStringAt(0); + CRYPT_MD5Update(md5, (uint8_t*)id.c_str(), id.GetLength()); + } + if (!bIgnoreMeta && revision >= 3 && + !pEncrypt->GetIntegerBy("EncryptMetadata", 1)) { + uint32_t tag = (uint32_t)-1; + CRYPT_MD5Update(md5, (uint8_t*)&tag, 4); + } + uint8_t digest[16]; + CRYPT_MD5Finish(md5, digest); + uint32_t copy_len = keylen; + if (copy_len > sizeof(digest)) { + copy_len = sizeof(digest); + } + if (revision >= 3) { + for (int i = 0; i < 50; i++) { + CRYPT_MD5Generate(digest, copy_len, digest); + } + } + FXSYS_memset(key, 0, keylen); + FXSYS_memcpy(key, digest, copy_len); +} + +} // namespace + +CPDF_SecurityHandler::CPDF_SecurityHandler() { + m_Version = 0; + m_Revision = 0; + m_pParser = NULL; + m_pEncryptDict = NULL; + m_Permissions = 0; + m_Cipher = FXCIPHER_NONE; + m_KeyLen = 0; +} + +CPDF_SecurityHandler::~CPDF_SecurityHandler() {} + +CPDF_CryptoHandler* CPDF_SecurityHandler::CreateCryptoHandler() { + return new CPDF_CryptoHandler; +} + +FX_BOOL CPDF_SecurityHandler::OnInit(CPDF_Parser* pParser, + CPDF_Dictionary* pEncryptDict) { + m_pParser = pParser; + if (!LoadDict(pEncryptDict)) { + return FALSE; + } + if (m_Cipher == FXCIPHER_NONE) { + return TRUE; + } + return CheckSecurity(m_KeyLen); +} +FX_BOOL CPDF_SecurityHandler::CheckSecurity(int32_t key_len) { + CFX_ByteString password = m_pParser->GetPassword(); + if (CheckPassword(password.raw_str(), password.GetLength(), TRUE, + m_EncryptKey, key_len)) { + if (password.IsEmpty()) { + if (!CheckPassword(password.raw_str(), password.GetLength(), FALSE, + m_EncryptKey, key_len)) { + return FALSE; + } + } + return TRUE; + } + return CheckPassword(password.raw_str(), password.GetLength(), FALSE, + m_EncryptKey, key_len); +} +uint32_t CPDF_SecurityHandler::GetPermissions() { + return m_Permissions; +} +static FX_BOOL _LoadCryptInfo(CPDF_Dictionary* pEncryptDict, + const CFX_ByteStringC& name, + int& cipher, + int& keylen) { + int Version = pEncryptDict->GetIntegerBy("V"); + cipher = FXCIPHER_RC4; + keylen = 0; + if (Version >= 4) { + CPDF_Dictionary* pCryptFilters = pEncryptDict->GetDictBy("CF"); + if (!pCryptFilters) { + return FALSE; + } + if (name == "Identity") { + cipher = FXCIPHER_NONE; + } else { + CPDF_Dictionary* pDefFilter = pCryptFilters->GetDictBy(name); + if (!pDefFilter) { + return FALSE; + } + int nKeyBits = 0; + if (Version == 4) { + nKeyBits = pDefFilter->GetIntegerBy("Length", 0); + if (nKeyBits == 0) { + nKeyBits = pEncryptDict->GetIntegerBy("Length", 128); + } + } else { + nKeyBits = pEncryptDict->GetIntegerBy("Length", 256); + } + if (nKeyBits < 40) { + nKeyBits *= 8; + } + keylen = nKeyBits / 8; + CFX_ByteString cipher_name = pDefFilter->GetStringBy("CFM"); + if (cipher_name == "AESV2" || cipher_name == "AESV3") { + cipher = FXCIPHER_AES; + } + } + } else { + keylen = Version > 1 ? pEncryptDict->GetIntegerBy("Length", 40) / 8 : 5; + } + if (keylen > 32 || keylen < 0) { + return FALSE; + } + return TRUE; +} + +FX_BOOL CPDF_SecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict) { + m_pEncryptDict = pEncryptDict; + m_Version = pEncryptDict->GetIntegerBy("V"); + m_Revision = pEncryptDict->GetIntegerBy("R"); + m_Permissions = pEncryptDict->GetIntegerBy("P", -1); + if (m_Version < 4) { + return _LoadCryptInfo(pEncryptDict, CFX_ByteStringC(), m_Cipher, m_KeyLen); + } + CFX_ByteString stmf_name = pEncryptDict->GetStringBy("StmF"); + CFX_ByteString strf_name = pEncryptDict->GetStringBy("StrF"); + if (stmf_name != strf_name) { + return FALSE; + } + if (!_LoadCryptInfo(pEncryptDict, strf_name.AsStringC(), m_Cipher, + m_KeyLen)) { + return FALSE; + } + return TRUE; +} + +FX_BOOL CPDF_SecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict, + uint32_t type, + int& cipher, + int& key_len) { + m_pEncryptDict = pEncryptDict; + m_Version = pEncryptDict->GetIntegerBy("V"); + m_Revision = pEncryptDict->GetIntegerBy("R"); + m_Permissions = pEncryptDict->GetIntegerBy("P", -1); + CFX_ByteString strf_name, stmf_name; + if (m_Version >= 4) { + stmf_name = pEncryptDict->GetStringBy("StmF"); + strf_name = pEncryptDict->GetStringBy("StrF"); + if (stmf_name != strf_name) { + return FALSE; + } + } + if (!_LoadCryptInfo(pEncryptDict, strf_name.AsStringC(), cipher, key_len)) { + return FALSE; + } + m_Cipher = cipher; + m_KeyLen = key_len; + return TRUE; +} + +FX_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)( \ + ((uint64_t)(b)[(i)] << 24) | ((uint64_t)(b)[(i) + 1] << 16) | \ + ((uint64_t)(b)[(i) + 2] << 8) | ((uint64_t)(b)[(i) + 3])); \ + } +int BigOrder64BitsMod3(uint8_t* data) { + uint64_t ret = 0; + for (int i = 0; i < 4; ++i) { + uint32_t value; + FX_GET_32WORD(value, data, 4 * i); + ret <<= 32; + ret |= value; + ret %= 3; + } + return (int)ret; +} +void Revision6_Hash(const uint8_t* password, + uint32_t size, + const uint8_t* salt, + const uint8_t* vector, + uint8_t* hash) { + int iBlockSize = 32; + uint8_t sha[128]; + CRYPT_SHA256Start(sha); + CRYPT_SHA256Update(sha, password, size); + CRYPT_SHA256Update(sha, salt, 8); + if (vector) { + CRYPT_SHA256Update(sha, vector, 48); + } + uint8_t digest[32]; + CRYPT_SHA256Finish(sha, digest); + CFX_ByteTextBuf buf; + uint8_t* input = digest; + uint8_t* key = input; + uint8_t* iv = input + 16; + uint8_t* E = buf.GetBuffer(); + int iBufLen = buf.GetLength(); + CFX_ByteTextBuf interDigest; + int i = 0; + uint8_t* aes = FX_Alloc(uint8_t, 2048); + while (i < 64 || i < E[iBufLen - 1] + 32) { + int iRoundSize = size + iBlockSize; + if (vector) { + iRoundSize += 48; + } + iBufLen = iRoundSize * 64; + buf.EstimateSize(iBufLen); + E = buf.GetBuffer(); + CFX_ByteTextBuf content; + for (int j = 0; j < 64; ++j) { + content.AppendBlock(password, size); + content.AppendBlock(input, iBlockSize); + if (vector) { + content.AppendBlock(vector, 48); + } + } + CRYPT_AESSetKey(aes, 16, key, 16, TRUE); + CRYPT_AESSetIV(aes, iv); + CRYPT_AESEncrypt(aes, E, content.GetBuffer(), iBufLen); + int iHash = 0; + switch (BigOrder64BitsMod3(E)) { + case 0: + iHash = 0; + iBlockSize = 32; + break; + case 1: + iHash = 1; + iBlockSize = 48; + break; + default: + iHash = 2; + iBlockSize = 64; + break; + } + interDigest.EstimateSize(iBlockSize); + input = interDigest.GetBuffer(); + if (iHash == 0) { + CRYPT_SHA256Generate(E, iBufLen, input); + } else if (iHash == 1) { + CRYPT_SHA384Generate(E, iBufLen, input); + } else if (iHash == 2) { + CRYPT_SHA512Generate(E, iBufLen, input); + } + key = input; + iv = input + 16; + ++i; + } + FX_Free(aes); + if (hash) { + FXSYS_memcpy(hash, input, 32); + } +} +FX_BOOL CPDF_SecurityHandler::AES256_CheckPassword(const uint8_t* password, + uint32_t size, + FX_BOOL bOwner, + uint8_t* key) { + CFX_ByteString okey = + m_pEncryptDict ? m_pEncryptDict->GetStringBy("O") : CFX_ByteString(); + if (okey.GetLength() < 48) { + return FALSE; + } + CFX_ByteString ukey = + m_pEncryptDict ? m_pEncryptDict->GetStringBy("U") : CFX_ByteString(); + if (ukey.GetLength() < 48) { + return FALSE; + } + const uint8_t* pkey = (bOwner ? okey : ukey).raw_str(); + uint8_t sha[128]; + uint8_t digest[32]; + if (m_Revision >= 6) { + Revision6_Hash(password, size, (const uint8_t*)pkey + 32, + bOwner ? ukey.raw_str() : nullptr, digest); + } else { + CRYPT_SHA256Start(sha); + CRYPT_SHA256Update(sha, password, size); + CRYPT_SHA256Update(sha, pkey + 32, 8); + if (bOwner) { + CRYPT_SHA256Update(sha, ukey.raw_str(), 48); + } + CRYPT_SHA256Finish(sha, digest); + } + if (FXSYS_memcmp(digest, pkey, 32) != 0) { + return FALSE; + } + if (!key) { + return TRUE; + } + if (m_Revision >= 6) { + Revision6_Hash(password, size, (const uint8_t*)pkey + 40, + bOwner ? ukey.raw_str() : nullptr, digest); + } else { + CRYPT_SHA256Start(sha); + CRYPT_SHA256Update(sha, password, size); + CRYPT_SHA256Update(sha, pkey + 40, 8); + if (bOwner) { + CRYPT_SHA256Update(sha, ukey.raw_str(), 48); + } + CRYPT_SHA256Finish(sha, digest); + } + CFX_ByteString ekey = m_pEncryptDict + ? m_pEncryptDict->GetStringBy(bOwner ? "OE" : "UE") + : CFX_ByteString(); + if (ekey.GetLength() < 32) { + return FALSE; + } + uint8_t* aes = FX_Alloc(uint8_t, 2048); + CRYPT_AESSetKey(aes, 16, digest, 32, FALSE); + uint8_t iv[16]; + FXSYS_memset(iv, 0, 16); + CRYPT_AESSetIV(aes, iv); + CRYPT_AESDecrypt(aes, key, ekey.raw_str(), 32); + CRYPT_AESSetKey(aes, 16, key, 32, FALSE); + CRYPT_AESSetIV(aes, iv); + CFX_ByteString perms = m_pEncryptDict->GetStringBy("Perms"); + if (perms.IsEmpty()) { + return FALSE; + } + uint8_t perms_buf[16]; + FXSYS_memset(perms_buf, 0, sizeof(perms_buf)); + uint32_t copy_len = sizeof(perms_buf); + if (copy_len > (uint32_t)perms.GetLength()) { + copy_len = perms.GetLength(); + } + FXSYS_memcpy(perms_buf, perms.raw_str(), copy_len); + uint8_t buf[16]; + CRYPT_AESDecrypt(aes, buf, perms_buf, 16); + FX_Free(aes); + if (buf[9] != 'a' || buf[10] != 'd' || buf[11] != 'b') { + return FALSE; + } + if (FXDWORD_GET_LSBFIRST(buf) != m_Permissions) { + return FALSE; + } + if ((buf[8] == 'T' && !IsMetadataEncrypted()) || + (buf[8] == 'F' && IsMetadataEncrypted())) { + return FALSE; + } + return TRUE; +} + +int CPDF_SecurityHandler::CheckPassword(const uint8_t* password, + uint32_t size, + FX_BOOL bOwner, + uint8_t* key, + int32_t key_len) { + if (m_Revision >= 5) { + return AES256_CheckPassword(password, size, bOwner, key); + } + uint8_t keybuf[32]; + if (!key) { + key = keybuf; + } + if (bOwner) { + return CheckOwnerPassword(password, size, key, key_len); + } + return CheckUserPassword(password, size, FALSE, key, key_len) || + CheckUserPassword(password, size, TRUE, key, key_len); +} +FX_BOOL CPDF_SecurityHandler::CheckUserPassword(const uint8_t* password, + uint32_t pass_size, + FX_BOOL bIgnoreEncryptMeta, + uint8_t* key, + int32_t key_len) { + CalcEncryptKey(m_pEncryptDict, password, pass_size, key, key_len, + bIgnoreEncryptMeta, m_pParser->GetIDArray()); + CFX_ByteString ukey = + m_pEncryptDict ? m_pEncryptDict->GetStringBy("U") : CFX_ByteString(); + if (ukey.GetLength() < 16) { + return FALSE; + } + uint8_t ukeybuf[32]; + if (m_Revision == 2) { + FXSYS_memcpy(ukeybuf, defpasscode, 32); + CRYPT_ArcFourCryptBlock(ukeybuf, 32, key, key_len); + } else { + uint8_t test[32], tmpkey[32]; + uint32_t copy_len = sizeof(test); + if (copy_len > (uint32_t)ukey.GetLength()) { + copy_len = ukey.GetLength(); + } + FXSYS_memset(test, 0, sizeof(test)); + FXSYS_memset(tmpkey, 0, sizeof(tmpkey)); + FXSYS_memcpy(test, ukey.c_str(), copy_len); + for (int i = 19; i >= 0; i--) { + for (int j = 0; j < key_len; j++) { + tmpkey[j] = key[j] ^ i; + } + CRYPT_ArcFourCryptBlock(test, 32, tmpkey, key_len); + } + uint8_t md5[100]; + CRYPT_MD5Start(md5); + CRYPT_MD5Update(md5, defpasscode, 32); + CPDF_Array* pIdArray = m_pParser->GetIDArray(); + if (pIdArray) { + CFX_ByteString id = pIdArray->GetStringAt(0); + CRYPT_MD5Update(md5, (uint8_t*)id.c_str(), id.GetLength()); + } + CRYPT_MD5Finish(md5, ukeybuf); + return FXSYS_memcmp(test, ukeybuf, 16) == 0; + } + if (FXSYS_memcmp((void*)ukey.c_str(), ukeybuf, 16) == 0) { + return TRUE; + } + return FALSE; +} +CFX_ByteString CPDF_SecurityHandler::GetUserPassword(const uint8_t* owner_pass, + uint32_t pass_size, + int32_t key_len) { + CFX_ByteString okey = m_pEncryptDict->GetStringBy("O"); + uint8_t passcode[32]; + uint32_t i; + for (i = 0; i < 32; i++) { + passcode[i] = i < pass_size ? owner_pass[i] : defpasscode[i - pass_size]; + } + uint8_t digest[16]; + CRYPT_MD5Generate(passcode, 32, digest); + if (m_Revision >= 3) { + for (int i = 0; i < 50; i++) { + CRYPT_MD5Generate(digest, 16, digest); + } + } + uint8_t enckey[32]; + FXSYS_memset(enckey, 0, sizeof(enckey)); + uint32_t copy_len = key_len; + if (copy_len > sizeof(digest)) { + copy_len = sizeof(digest); + } + FXSYS_memcpy(enckey, digest, copy_len); + int okeylen = okey.GetLength(); + if (okeylen > 32) { + okeylen = 32; + } + uint8_t okeybuf[64]; + FXSYS_memset(okeybuf, 0, sizeof(okeybuf)); + FXSYS_memcpy(okeybuf, okey.c_str(), okeylen); + if (m_Revision == 2) { + CRYPT_ArcFourCryptBlock(okeybuf, okeylen, enckey, key_len); + } else { + for (int i = 19; i >= 0; i--) { + uint8_t tempkey[32]; + FXSYS_memset(tempkey, 0, sizeof(tempkey)); + for (int j = 0; j < m_KeyLen; j++) { + tempkey[j] = enckey[j] ^ i; + } + CRYPT_ArcFourCryptBlock(okeybuf, okeylen, tempkey, key_len); + } + } + int len = 32; + while (len && defpasscode[len - 1] == okeybuf[len - 1]) { + len--; + } + return CFX_ByteString(okeybuf, len); +} +FX_BOOL CPDF_SecurityHandler::CheckOwnerPassword(const uint8_t* password, + uint32_t pass_size, + uint8_t* key, + int32_t key_len) { + CFX_ByteString user_pass = GetUserPassword(password, pass_size, key_len); + if (CheckUserPassword(user_pass.raw_str(), user_pass.GetLength(), FALSE, key, + key_len)) { + return TRUE; + } + return CheckUserPassword(user_pass.raw_str(), user_pass.GetLength(), TRUE, + key, key_len); +} +FX_BOOL CPDF_SecurityHandler::IsMetadataEncrypted() { + return m_pEncryptDict->GetBooleanBy("EncryptMetadata", TRUE); +} + +void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, + CPDF_Array* pIdArray, + const uint8_t* user_pass, + uint32_t user_size, + const uint8_t* owner_pass, + uint32_t owner_size, + FX_BOOL bDefault, + uint32_t type) { + int cipher = 0, key_len = 0; + if (!LoadDict(pEncryptDict, type, cipher, key_len)) { + return; + } + if (bDefault && (!owner_pass || owner_size == 0)) { + owner_pass = user_pass; + owner_size = user_size; + } + if (m_Revision >= 5) { + int t = (int)time(NULL); + uint8_t sha[128]; + CRYPT_SHA256Start(sha); + CRYPT_SHA256Update(sha, (uint8_t*)&t, sizeof t); + CRYPT_SHA256Update(sha, m_EncryptKey, 32); + CRYPT_SHA256Update(sha, (uint8_t*)"there", 5); + CRYPT_SHA256Finish(sha, m_EncryptKey); + AES256_SetPassword(pEncryptDict, user_pass, user_size, FALSE, m_EncryptKey); + if (bDefault) { + AES256_SetPassword(pEncryptDict, owner_pass, owner_size, TRUE, + m_EncryptKey); + AES256_SetPerms(pEncryptDict, m_Permissions, + pEncryptDict->GetBooleanBy("EncryptMetadata", TRUE), + m_EncryptKey); + } + return; + } + if (bDefault) { + uint8_t passcode[32]; + uint32_t i; + for (i = 0; i < 32; i++) { + passcode[i] = + i < owner_size ? owner_pass[i] : defpasscode[i - owner_size]; + } + uint8_t digest[16]; + CRYPT_MD5Generate(passcode, 32, digest); + if (m_Revision >= 3) { + for (int i = 0; i < 50; i++) { + CRYPT_MD5Generate(digest, 16, digest); + } + } + uint8_t enckey[32]; + FXSYS_memcpy(enckey, digest, key_len); + for (i = 0; i < 32; i++) { + passcode[i] = i < user_size ? user_pass[i] : defpasscode[i - user_size]; + } + CRYPT_ArcFourCryptBlock(passcode, 32, enckey, key_len); + uint8_t tempkey[32]; + if (m_Revision >= 3) { + for (i = 1; i <= 19; i++) { + for (int j = 0; j < key_len; j++) { + tempkey[j] = enckey[j] ^ (uint8_t)i; + } + CRYPT_ArcFourCryptBlock(passcode, 32, tempkey, key_len); + } + } + pEncryptDict->SetAtString("O", CFX_ByteString(passcode, 32)); + } + CalcEncryptKey(m_pEncryptDict, (uint8_t*)user_pass, user_size, m_EncryptKey, + key_len, FALSE, pIdArray); + if (m_Revision < 3) { + uint8_t tempbuf[32]; + FXSYS_memcpy(tempbuf, defpasscode, 32); + CRYPT_ArcFourCryptBlock(tempbuf, 32, m_EncryptKey, key_len); + pEncryptDict->SetAtString("U", CFX_ByteString(tempbuf, 32)); + } else { + uint8_t md5[100]; + CRYPT_MD5Start(md5); + CRYPT_MD5Update(md5, defpasscode, 32); + if (pIdArray) { + CFX_ByteString id = pIdArray->GetStringAt(0); + CRYPT_MD5Update(md5, (uint8_t*)id.c_str(), id.GetLength()); + } + uint8_t digest[32]; + CRYPT_MD5Finish(md5, digest); + CRYPT_ArcFourCryptBlock(digest, 16, m_EncryptKey, key_len); + uint8_t tempkey[32]; + for (int i = 1; i <= 19; i++) { + for (int j = 0; j < key_len; j++) { + tempkey[j] = m_EncryptKey[j] ^ (uint8_t)i; + } + CRYPT_ArcFourCryptBlock(digest, 16, tempkey, key_len); + } + CRYPT_MD5Generate(digest, 16, digest + 16); + pEncryptDict->SetAtString("U", CFX_ByteString(digest, 32)); + } +} +void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, + CPDF_Array* pIdArray, + const uint8_t* user_pass, + uint32_t user_size, + const uint8_t* owner_pass, + uint32_t owner_size, + uint32_t type) { + OnCreate(pEncryptDict, pIdArray, user_pass, user_size, owner_pass, owner_size, + TRUE, type); +} +void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, + CPDF_Array* pIdArray, + const uint8_t* user_pass, + uint32_t user_size, + uint32_t type) { + OnCreate(pEncryptDict, pIdArray, user_pass, user_size, NULL, 0, FALSE, type); +} +void CPDF_SecurityHandler::AES256_SetPassword(CPDF_Dictionary* pEncryptDict, + const uint8_t* password, + uint32_t size, + FX_BOOL bOwner, + const uint8_t* key) { + uint8_t sha[128]; + CRYPT_SHA1Start(sha); + CRYPT_SHA1Update(sha, key, 32); + CRYPT_SHA1Update(sha, (uint8_t*)"hello", 5); + uint8_t digest[20]; + CRYPT_SHA1Finish(sha, digest); + CFX_ByteString ukey = pEncryptDict->GetStringBy("U"); + uint8_t digest1[48]; + if (m_Revision >= 6) { + Revision6_Hash(password, size, digest, bOwner ? ukey.raw_str() : nullptr, + digest1); + } else { + CRYPT_SHA256Start(sha); + CRYPT_SHA256Update(sha, password, size); + CRYPT_SHA256Update(sha, digest, 8); + if (bOwner) { + CRYPT_SHA256Update(sha, ukey.raw_str(), ukey.GetLength()); + } + CRYPT_SHA256Finish(sha, digest1); + } + FXSYS_memcpy(digest1 + 32, digest, 16); + pEncryptDict->SetAtString(bOwner ? "O" : "U", CFX_ByteString(digest1, 48)); + if (m_Revision >= 6) { + Revision6_Hash(password, size, digest + 8, + bOwner ? ukey.raw_str() : nullptr, digest1); + } else { + CRYPT_SHA256Start(sha); + CRYPT_SHA256Update(sha, password, size); + CRYPT_SHA256Update(sha, digest + 8, 8); + if (bOwner) { + CRYPT_SHA256Update(sha, ukey.raw_str(), ukey.GetLength()); + } + CRYPT_SHA256Finish(sha, digest1); + } + uint8_t* aes = FX_Alloc(uint8_t, 2048); + CRYPT_AESSetKey(aes, 16, digest1, 32, TRUE); + uint8_t iv[16]; + FXSYS_memset(iv, 0, 16); + CRYPT_AESSetIV(aes, iv); + CRYPT_AESEncrypt(aes, digest1, key, 32); + FX_Free(aes); + pEncryptDict->SetAtString(bOwner ? "OE" : "UE", CFX_ByteString(digest1, 32)); +} +void CPDF_SecurityHandler::AES256_SetPerms(CPDF_Dictionary* pEncryptDict, + uint32_t permissions, + FX_BOOL bEncryptMetadata, + const uint8_t* key) { + uint8_t buf[16]; + buf[0] = (uint8_t)permissions; + buf[1] = (uint8_t)(permissions >> 8); + buf[2] = (uint8_t)(permissions >> 16); + buf[3] = (uint8_t)(permissions >> 24); + buf[4] = 0xff; + buf[5] = 0xff; + buf[6] = 0xff; + buf[7] = 0xff; + buf[8] = bEncryptMetadata ? 'T' : 'F'; + buf[9] = 'a'; + buf[10] = 'd'; + buf[11] = 'b'; + uint8_t* aes = FX_Alloc(uint8_t, 2048); + CRYPT_AESSetKey(aes, 16, key, 32, TRUE); + uint8_t iv[16], buf1[16]; + FXSYS_memset(iv, 0, 16); + CRYPT_AESSetIV(aes, iv); + CRYPT_AESEncrypt(aes, buf1, buf, 16); + FX_Free(aes); + pEncryptDict->SetAtString("Perms", CFX_ByteString(buf1, 16)); +} diff --git a/core/fpdfapi/fpdf_parser/cpdf_security_handler.h b/core/fpdfapi/fpdf_parser/cpdf_security_handler.h new file mode 100644 index 0000000000..645c97698a --- /dev/null +++ b/core/fpdfapi/fpdf_parser/cpdf_security_handler.h @@ -0,0 +1,109 @@ +// 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_FPDFAPI_FPDF_PARSER_CPDF_SECURITY_HANDLER_H_ +#define CORE_FPDFAPI_FPDF_PARSER_CPDF_SECURITY_HANDLER_H_ + +#include "core/fxcrt/include/fx_string.h" +#include "core/fxcrt/include/fx_system.h" + +#define FXCIPHER_NONE 0 +#define FXCIPHER_RC4 1 +#define FXCIPHER_AES 2 +#define FXCIPHER_AES2 3 + +#define PDF_ENCRYPT_CONTENT 0 + +class CPDF_Array; +class CPDF_CryptoHandler; +class CPDF_Dictionary; +class CPDF_Parser; + +class CPDF_SecurityHandler { + public: + CPDF_SecurityHandler(); + ~CPDF_SecurityHandler(); + + FX_BOOL OnInit(CPDF_Parser* pParser, CPDF_Dictionary* pEncryptDict); + uint32_t GetPermissions(); + FX_BOOL GetCryptInfo(int& cipher, const uint8_t*& buffer, int& keylen); + FX_BOOL IsMetadataEncrypted(); + CPDF_CryptoHandler* CreateCryptoHandler(); + + void OnCreate(CPDF_Dictionary* pEncryptDict, + CPDF_Array* pIdArray, + const uint8_t* user_pass, + uint32_t user_size, + const uint8_t* owner_pass, + uint32_t owner_size, + uint32_t type = PDF_ENCRYPT_CONTENT); + + void OnCreate(CPDF_Dictionary* pEncryptDict, + CPDF_Array* pIdArray, + const uint8_t* user_pass, + uint32_t user_size, + uint32_t type = PDF_ENCRYPT_CONTENT); + + CFX_ByteString GetUserPassword(const uint8_t* owner_pass, + uint32_t pass_size, + int32_t key_len); + int CheckPassword(const uint8_t* password, + uint32_t pass_size, + FX_BOOL bOwner, + uint8_t* key, + int key_len); + + private: + FX_BOOL LoadDict(CPDF_Dictionary* pEncryptDict); + FX_BOOL LoadDict(CPDF_Dictionary* pEncryptDict, + uint32_t type, + int& cipher, + int& key_len); + + FX_BOOL CheckUserPassword(const uint8_t* password, + uint32_t pass_size, + FX_BOOL bIgnoreEncryptMeta, + uint8_t* key, + int32_t key_len); + + FX_BOOL CheckOwnerPassword(const uint8_t* password, + uint32_t pass_size, + uint8_t* key, + int32_t key_len); + FX_BOOL AES256_CheckPassword(const uint8_t* password, + uint32_t size, + FX_BOOL bOwner, + uint8_t* key); + void AES256_SetPassword(CPDF_Dictionary* pEncryptDict, + const uint8_t* password, + uint32_t size, + FX_BOOL bOwner, + const uint8_t* key); + void AES256_SetPerms(CPDF_Dictionary* pEncryptDict, + uint32_t permission, + FX_BOOL bEncryptMetadata, + const uint8_t* key); + void OnCreate(CPDF_Dictionary* pEncryptDict, + CPDF_Array* pIdArray, + const uint8_t* user_pass, + uint32_t user_size, + const uint8_t* owner_pass, + uint32_t owner_size, + FX_BOOL bDefault, + uint32_t type); + FX_BOOL CheckSecurity(int32_t key_len); + + int m_Version; + int m_Revision; + CPDF_Parser* m_pParser; + CPDF_Dictionary* m_pEncryptDict; + uint32_t m_Permissions; + int m_Cipher; + uint8_t m_EncryptKey[32]; + int m_KeyLen; +}; + +#endif // CORE_FPDFAPI_FPDF_PARSER_CPDF_SECURITY_HANDLER_H_ diff --git a/core/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.cpp b/core/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.cpp deleted file mode 100644 index 6bfe1b60b3..0000000000 --- a/core/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.cpp +++ /dev/null @@ -1,342 +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/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.h" - -#include - -#include "core/fdrm/crypto/include/fx_crypt.h" -#include "core/fpdfapi/fpdf_parser/include/cpdf_parser.h" -#include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h" -#include "core/fpdfapi/fpdf_parser/ipdf_security_handler.h" - -IPDF_CryptoHandler::~IPDF_CryptoHandler() {} - -void IPDF_CryptoHandler::Decrypt(uint32_t objnum, - uint32_t gennum, - CFX_ByteString& str) { - CFX_BinaryBuf dest_buf; - void* context = DecryptStart(objnum, gennum); - DecryptStream(context, str.raw_str(), str.GetLength(), dest_buf); - DecryptFinish(context, dest_buf); - str = CFX_ByteString(dest_buf.GetBuffer(), dest_buf.GetSize()); -} - -void CPDF_StandardCryptoHandler::CryptBlock(FX_BOOL bEncrypt, - uint32_t objnum, - uint32_t gennum, - const uint8_t* src_buf, - uint32_t src_size, - uint8_t* dest_buf, - uint32_t& 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]; - uint32_t m_BlockOffset; -}; - -void* CPDF_StandardCryptoHandler::CryptStart(uint32_t objnum, - uint32_t 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, - uint32_t 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; - } - uint32_t src_off = 0; - uint32_t src_left = src_size; - while (1) { - uint32_t 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(uint32_t objnum, - uint32_t gennum) { - return CryptStart(objnum, gennum, FALSE); -} -uint32_t CPDF_StandardCryptoHandler::DecryptGetSize(uint32_t 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, - uint32_t 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); -} -uint32_t CPDF_StandardCryptoHandler::EncryptGetSize(uint32_t objnum, - uint32_t version, - const uint8_t* src_buf, - uint32_t src_size) { - if (m_Cipher == FXCIPHER_AES) { - return src_size + 32; - } - return src_size; -} -FX_BOOL CPDF_StandardCryptoHandler::EncryptContent(uint32_t objnum, - uint32_t gennum, - const uint8_t* src_buf, - uint32_t src_size, - uint8_t* dest_buf, - uint32_t& 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/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.h b/core/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.h deleted file mode 100644 index 689d44b81b..0000000000 --- a/core/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.h +++ /dev/null @@ -1,64 +0,0 @@ -// 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_FPDFAPI_FPDF_PARSER_CPDF_STANDARD_CRYPTO_HANDLER_H_ -#define CORE_FPDFAPI_FPDF_PARSER_CPDF_STANDARD_CRYPTO_HANDLER_H_ - -#include "core/fpdfapi/fpdf_parser/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; - uint32_t DecryptGetSize(uint32_t src_size) override; - void* DecryptStart(uint32_t objnum, uint32_t gennum) override; - FX_BOOL DecryptStream(void* context, - const uint8_t* src_buf, - uint32_t src_size, - CFX_BinaryBuf& dest_buf) override; - FX_BOOL DecryptFinish(void* context, CFX_BinaryBuf& dest_buf) override; - uint32_t EncryptGetSize(uint32_t objnum, - uint32_t version, - const uint8_t* src_buf, - uint32_t src_size) override; - FX_BOOL EncryptContent(uint32_t objnum, - uint32_t version, - const uint8_t* src_buf, - uint32_t src_size, - uint8_t* dest_buf, - uint32_t& dest_size) override; - - FX_BOOL Init(int cipher, const uint8_t* key, int keylen); - - protected: - virtual void CryptBlock(FX_BOOL bEncrypt, - uint32_t objnum, - uint32_t gennum, - const uint8_t* src_buf, - uint32_t src_size, - uint8_t* dest_buf, - uint32_t& dest_size); - virtual void* CryptStart(uint32_t objnum, uint32_t gennum, FX_BOOL bEncrypt); - virtual FX_BOOL CryptStream(void* context, - const uint8_t* src_buf, - uint32_t 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_FPDFAPI_FPDF_PARSER_CPDF_STANDARD_CRYPTO_HANDLER_H_ diff --git a/core/fpdfapi/fpdf_parser/cpdf_standard_security_handler.cpp b/core/fpdfapi/fpdf_parser/cpdf_standard_security_handler.cpp deleted file mode 100644 index 627ff5263f..0000000000 --- a/core/fpdfapi/fpdf_parser/cpdf_standard_security_handler.cpp +++ /dev/null @@ -1,715 +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/fpdfapi/fpdf_parser/cpdf_standard_security_handler.h" - -#include - -#include "core/fdrm/crypto/include/fx_crypt.h" -#include "core/fpdfapi/fpdf_parser/cpdf_standard_crypto_handler.h" -#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" -#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" -#include "core/fpdfapi/fpdf_parser/include/cpdf_object.h" -#include "core/fpdfapi/fpdf_parser/include/cpdf_parser.h" - -namespace { - -const uint8_t defpasscode[32] = { - 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, - 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, - 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a}; - -void CalcEncryptKey(CPDF_Dictionary* pEncrypt, - const uint8_t* password, - uint32_t pass_size, - uint8_t* key, - int keylen, - FX_BOOL bIgnoreMeta, - CPDF_Array* pIdArray) { - int revision = pEncrypt->GetIntegerBy("R"); - uint8_t passcode[32]; - for (uint32_t i = 0; i < 32; i++) { - passcode[i] = i < pass_size ? password[i] : defpasscode[i - pass_size]; - } - uint8_t md5[100]; - CRYPT_MD5Start(md5); - CRYPT_MD5Update(md5, passcode, 32); - CFX_ByteString okey = pEncrypt->GetStringBy("O"); - CRYPT_MD5Update(md5, (uint8_t*)okey.c_str(), okey.GetLength()); - uint32_t perm = pEncrypt->GetIntegerBy("P"); - CRYPT_MD5Update(md5, (uint8_t*)&perm, 4); - if (pIdArray) { - CFX_ByteString id = pIdArray->GetStringAt(0); - CRYPT_MD5Update(md5, (uint8_t*)id.c_str(), id.GetLength()); - } - if (!bIgnoreMeta && revision >= 3 && - !pEncrypt->GetIntegerBy("EncryptMetadata", 1)) { - uint32_t tag = (uint32_t)-1; - CRYPT_MD5Update(md5, (uint8_t*)&tag, 4); - } - uint8_t digest[16]; - CRYPT_MD5Finish(md5, digest); - uint32_t copy_len = keylen; - if (copy_len > sizeof(digest)) { - copy_len = sizeof(digest); - } - if (revision >= 3) { - for (int i = 0; i < 50; i++) { - CRYPT_MD5Generate(digest, copy_len, digest); - } - } - FXSYS_memset(key, 0, keylen); - FXSYS_memcpy(key, digest, copy_len); -} - -} // namespace - -IPDF_SecurityHandler::~IPDF_SecurityHandler() {} - -CPDF_StandardSecurityHandler::CPDF_StandardSecurityHandler() { - m_Version = 0; - m_Revision = 0; - m_pParser = NULL; - m_pEncryptDict = NULL; - m_Permissions = 0; - m_Cipher = FXCIPHER_NONE; - m_KeyLen = 0; -} - -CPDF_StandardSecurityHandler::~CPDF_StandardSecurityHandler() {} - -IPDF_CryptoHandler* CPDF_StandardSecurityHandler::CreateCryptoHandler() { - return new CPDF_StandardCryptoHandler; -} - -FX_BOOL CPDF_StandardSecurityHandler::OnInit(CPDF_Parser* pParser, - CPDF_Dictionary* pEncryptDict) { - m_pParser = pParser; - if (!LoadDict(pEncryptDict)) { - return FALSE; - } - if (m_Cipher == FXCIPHER_NONE) { - return TRUE; - } - return CheckSecurity(m_KeyLen); -} -FX_BOOL CPDF_StandardSecurityHandler::CheckSecurity(int32_t key_len) { - CFX_ByteString password = m_pParser->GetPassword(); - if (CheckPassword(password.raw_str(), password.GetLength(), TRUE, - m_EncryptKey, key_len)) { - if (password.IsEmpty()) { - if (!CheckPassword(password.raw_str(), password.GetLength(), FALSE, - m_EncryptKey, key_len)) { - return FALSE; - } - } - return TRUE; - } - return CheckPassword(password.raw_str(), password.GetLength(), FALSE, - m_EncryptKey, key_len); -} -uint32_t CPDF_StandardSecurityHandler::GetPermissions() { - return m_Permissions; -} -static FX_BOOL _LoadCryptInfo(CPDF_Dictionary* pEncryptDict, - const CFX_ByteStringC& name, - int& cipher, - int& keylen) { - int Version = pEncryptDict->GetIntegerBy("V"); - cipher = FXCIPHER_RC4; - keylen = 0; - if (Version >= 4) { - CPDF_Dictionary* pCryptFilters = pEncryptDict->GetDictBy("CF"); - if (!pCryptFilters) { - return FALSE; - } - if (name == "Identity") { - cipher = FXCIPHER_NONE; - } else { - CPDF_Dictionary* pDefFilter = pCryptFilters->GetDictBy(name); - if (!pDefFilter) { - return FALSE; - } - int nKeyBits = 0; - if (Version == 4) { - nKeyBits = pDefFilter->GetIntegerBy("Length", 0); - if (nKeyBits == 0) { - nKeyBits = pEncryptDict->GetIntegerBy("Length", 128); - } - } else { - nKeyBits = pEncryptDict->GetIntegerBy("Length", 256); - } - if (nKeyBits < 40) { - nKeyBits *= 8; - } - keylen = nKeyBits / 8; - CFX_ByteString cipher_name = pDefFilter->GetStringBy("CFM"); - if (cipher_name == "AESV2" || cipher_name == "AESV3") { - cipher = FXCIPHER_AES; - } - } - } else { - keylen = Version > 1 ? pEncryptDict->GetIntegerBy("Length", 40) / 8 : 5; - } - if (keylen > 32 || keylen < 0) { - return FALSE; - } - return TRUE; -} - -FX_BOOL CPDF_StandardSecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict) { - m_pEncryptDict = pEncryptDict; - m_Version = pEncryptDict->GetIntegerBy("V"); - m_Revision = pEncryptDict->GetIntegerBy("R"); - m_Permissions = pEncryptDict->GetIntegerBy("P", -1); - if (m_Version < 4) { - return _LoadCryptInfo(pEncryptDict, CFX_ByteStringC(), m_Cipher, m_KeyLen); - } - CFX_ByteString stmf_name = pEncryptDict->GetStringBy("StmF"); - CFX_ByteString strf_name = pEncryptDict->GetStringBy("StrF"); - if (stmf_name != strf_name) { - return FALSE; - } - if (!_LoadCryptInfo(pEncryptDict, strf_name.AsStringC(), m_Cipher, - m_KeyLen)) { - return FALSE; - } - return TRUE; -} - -FX_BOOL CPDF_StandardSecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict, - uint32_t type, - int& cipher, - int& key_len) { - m_pEncryptDict = pEncryptDict; - m_Version = pEncryptDict->GetIntegerBy("V"); - m_Revision = pEncryptDict->GetIntegerBy("R"); - m_Permissions = pEncryptDict->GetIntegerBy("P", -1); - CFX_ByteString strf_name, stmf_name; - if (m_Version >= 4) { - stmf_name = pEncryptDict->GetStringBy("StmF"); - strf_name = pEncryptDict->GetStringBy("StrF"); - if (stmf_name != strf_name) { - return FALSE; - } - } - if (!_LoadCryptInfo(pEncryptDict, strf_name.AsStringC(), cipher, key_len)) { - return FALSE; - } - m_Cipher = cipher; - m_KeyLen = key_len; - return TRUE; -} - -FX_BOOL CPDF_StandardSecurityHandler::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)( \ - ((uint64_t)(b)[(i)] << 24) | ((uint64_t)(b)[(i) + 1] << 16) | \ - ((uint64_t)(b)[(i) + 2] << 8) | ((uint64_t)(b)[(i) + 3])); \ - } -int BigOrder64BitsMod3(uint8_t* data) { - uint64_t ret = 0; - for (int i = 0; i < 4; ++i) { - uint32_t value; - FX_GET_32WORD(value, data, 4 * i); - ret <<= 32; - ret |= value; - ret %= 3; - } - return (int)ret; -} -void Revision6_Hash(const uint8_t* password, - uint32_t size, - const uint8_t* salt, - const uint8_t* vector, - uint8_t* hash) { - int iBlockSize = 32; - uint8_t sha[128]; - CRYPT_SHA256Start(sha); - CRYPT_SHA256Update(sha, password, size); - CRYPT_SHA256Update(sha, salt, 8); - if (vector) { - CRYPT_SHA256Update(sha, vector, 48); - } - uint8_t digest[32]; - CRYPT_SHA256Finish(sha, digest); - CFX_ByteTextBuf buf; - uint8_t* input = digest; - uint8_t* key = input; - uint8_t* iv = input + 16; - uint8_t* E = buf.GetBuffer(); - int iBufLen = buf.GetLength(); - CFX_ByteTextBuf interDigest; - int i = 0; - uint8_t* aes = FX_Alloc(uint8_t, 2048); - while (i < 64 || i < E[iBufLen - 1] + 32) { - int iRoundSize = size + iBlockSize; - if (vector) { - iRoundSize += 48; - } - iBufLen = iRoundSize * 64; - buf.EstimateSize(iBufLen); - E = buf.GetBuffer(); - CFX_ByteTextBuf content; - for (int j = 0; j < 64; ++j) { - content.AppendBlock(password, size); - content.AppendBlock(input, iBlockSize); - if (vector) { - content.AppendBlock(vector, 48); - } - } - CRYPT_AESSetKey(aes, 16, key, 16, TRUE); - CRYPT_AESSetIV(aes, iv); - CRYPT_AESEncrypt(aes, E, content.GetBuffer(), iBufLen); - int iHash = 0; - switch (BigOrder64BitsMod3(E)) { - case 0: - iHash = 0; - iBlockSize = 32; - break; - case 1: - iHash = 1; - iBlockSize = 48; - break; - default: - iHash = 2; - iBlockSize = 64; - break; - } - interDigest.EstimateSize(iBlockSize); - input = interDigest.GetBuffer(); - if (iHash == 0) { - CRYPT_SHA256Generate(E, iBufLen, input); - } else if (iHash == 1) { - CRYPT_SHA384Generate(E, iBufLen, input); - } else if (iHash == 2) { - CRYPT_SHA512Generate(E, iBufLen, input); - } - key = input; - iv = input + 16; - ++i; - } - FX_Free(aes); - if (hash) { - FXSYS_memcpy(hash, input, 32); - } -} -FX_BOOL CPDF_StandardSecurityHandler::AES256_CheckPassword( - const uint8_t* password, - uint32_t size, - FX_BOOL bOwner, - uint8_t* key) { - CFX_ByteString okey = - m_pEncryptDict ? m_pEncryptDict->GetStringBy("O") : CFX_ByteString(); - if (okey.GetLength() < 48) { - return FALSE; - } - CFX_ByteString ukey = - m_pEncryptDict ? m_pEncryptDict->GetStringBy("U") : CFX_ByteString(); - if (ukey.GetLength() < 48) { - return FALSE; - } - const uint8_t* pkey = (bOwner ? okey : ukey).raw_str(); - uint8_t sha[128]; - uint8_t digest[32]; - if (m_Revision >= 6) { - Revision6_Hash(password, size, (const uint8_t*)pkey + 32, - bOwner ? ukey.raw_str() : nullptr, digest); - } else { - CRYPT_SHA256Start(sha); - CRYPT_SHA256Update(sha, password, size); - CRYPT_SHA256Update(sha, pkey + 32, 8); - if (bOwner) { - CRYPT_SHA256Update(sha, ukey.raw_str(), 48); - } - CRYPT_SHA256Finish(sha, digest); - } - if (FXSYS_memcmp(digest, pkey, 32) != 0) { - return FALSE; - } - if (!key) { - return TRUE; - } - if (m_Revision >= 6) { - Revision6_Hash(password, size, (const uint8_t*)pkey + 40, - bOwner ? ukey.raw_str() : nullptr, digest); - } else { - CRYPT_SHA256Start(sha); - CRYPT_SHA256Update(sha, password, size); - CRYPT_SHA256Update(sha, pkey + 40, 8); - if (bOwner) { - CRYPT_SHA256Update(sha, ukey.raw_str(), 48); - } - CRYPT_SHA256Finish(sha, digest); - } - CFX_ByteString ekey = m_pEncryptDict - ? m_pEncryptDict->GetStringBy(bOwner ? "OE" : "UE") - : CFX_ByteString(); - if (ekey.GetLength() < 32) { - return FALSE; - } - uint8_t* aes = FX_Alloc(uint8_t, 2048); - CRYPT_AESSetKey(aes, 16, digest, 32, FALSE); - uint8_t iv[16]; - FXSYS_memset(iv, 0, 16); - CRYPT_AESSetIV(aes, iv); - CRYPT_AESDecrypt(aes, key, ekey.raw_str(), 32); - CRYPT_AESSetKey(aes, 16, key, 32, FALSE); - CRYPT_AESSetIV(aes, iv); - CFX_ByteString perms = m_pEncryptDict->GetStringBy("Perms"); - if (perms.IsEmpty()) { - return FALSE; - } - uint8_t perms_buf[16]; - FXSYS_memset(perms_buf, 0, sizeof(perms_buf)); - uint32_t copy_len = sizeof(perms_buf); - if (copy_len > (uint32_t)perms.GetLength()) { - copy_len = perms.GetLength(); - } - FXSYS_memcpy(perms_buf, perms.raw_str(), copy_len); - uint8_t buf[16]; - CRYPT_AESDecrypt(aes, buf, perms_buf, 16); - FX_Free(aes); - if (buf[9] != 'a' || buf[10] != 'd' || buf[11] != 'b') { - return FALSE; - } - if (FXDWORD_GET_LSBFIRST(buf) != m_Permissions) { - return FALSE; - } - if ((buf[8] == 'T' && !IsMetadataEncrypted()) || - (buf[8] == 'F' && IsMetadataEncrypted())) { - return FALSE; - } - return TRUE; -} - -int CPDF_StandardSecurityHandler::CheckPassword(const uint8_t* password, - uint32_t size, - FX_BOOL bOwner, - uint8_t* key, - int32_t key_len) { - if (m_Revision >= 5) { - return AES256_CheckPassword(password, size, bOwner, key); - } - uint8_t keybuf[32]; - if (!key) { - key = keybuf; - } - if (bOwner) { - return CheckOwnerPassword(password, size, key, key_len); - } - return CheckUserPassword(password, size, FALSE, key, key_len) || - CheckUserPassword(password, size, TRUE, key, key_len); -} -FX_BOOL CPDF_StandardSecurityHandler::CheckUserPassword( - const uint8_t* password, - uint32_t pass_size, - FX_BOOL bIgnoreEncryptMeta, - uint8_t* key, - int32_t key_len) { - CalcEncryptKey(m_pEncryptDict, password, pass_size, key, key_len, - bIgnoreEncryptMeta, m_pParser->GetIDArray()); - CFX_ByteString ukey = - m_pEncryptDict ? m_pEncryptDict->GetStringBy("U") : CFX_ByteString(); - if (ukey.GetLength() < 16) { - return FALSE; - } - uint8_t ukeybuf[32]; - if (m_Revision == 2) { - FXSYS_memcpy(ukeybuf, defpasscode, 32); - CRYPT_ArcFourCryptBlock(ukeybuf, 32, key, key_len); - } else { - uint8_t test[32], tmpkey[32]; - uint32_t copy_len = sizeof(test); - if (copy_len > (uint32_t)ukey.GetLength()) { - copy_len = ukey.GetLength(); - } - FXSYS_memset(test, 0, sizeof(test)); - FXSYS_memset(tmpkey, 0, sizeof(tmpkey)); - FXSYS_memcpy(test, ukey.c_str(), copy_len); - for (int i = 19; i >= 0; i--) { - for (int j = 0; j < key_len; j++) { - tmpkey[j] = key[j] ^ i; - } - CRYPT_ArcFourCryptBlock(test, 32, tmpkey, key_len); - } - uint8_t md5[100]; - CRYPT_MD5Start(md5); - CRYPT_MD5Update(md5, defpasscode, 32); - CPDF_Array* pIdArray = m_pParser->GetIDArray(); - if (pIdArray) { - CFX_ByteString id = pIdArray->GetStringAt(0); - CRYPT_MD5Update(md5, (uint8_t*)id.c_str(), id.GetLength()); - } - CRYPT_MD5Finish(md5, ukeybuf); - return FXSYS_memcmp(test, ukeybuf, 16) == 0; - } - if (FXSYS_memcmp((void*)ukey.c_str(), ukeybuf, 16) == 0) { - return TRUE; - } - return FALSE; -} -CFX_ByteString CPDF_StandardSecurityHandler::GetUserPassword( - const uint8_t* owner_pass, - uint32_t pass_size, - int32_t key_len) { - CFX_ByteString okey = m_pEncryptDict->GetStringBy("O"); - uint8_t passcode[32]; - uint32_t i; - for (i = 0; i < 32; i++) { - passcode[i] = i < pass_size ? owner_pass[i] : defpasscode[i - pass_size]; - } - uint8_t digest[16]; - CRYPT_MD5Generate(passcode, 32, digest); - if (m_Revision >= 3) { - for (int i = 0; i < 50; i++) { - CRYPT_MD5Generate(digest, 16, digest); - } - } - uint8_t enckey[32]; - FXSYS_memset(enckey, 0, sizeof(enckey)); - uint32_t copy_len = key_len; - if (copy_len > sizeof(digest)) { - copy_len = sizeof(digest); - } - FXSYS_memcpy(enckey, digest, copy_len); - int okeylen = okey.GetLength(); - if (okeylen > 32) { - okeylen = 32; - } - uint8_t okeybuf[64]; - FXSYS_memset(okeybuf, 0, sizeof(okeybuf)); - FXSYS_memcpy(okeybuf, okey.c_str(), okeylen); - if (m_Revision == 2) { - CRYPT_ArcFourCryptBlock(okeybuf, okeylen, enckey, key_len); - } else { - for (int i = 19; i >= 0; i--) { - uint8_t tempkey[32]; - FXSYS_memset(tempkey, 0, sizeof(tempkey)); - for (int j = 0; j < m_KeyLen; j++) { - tempkey[j] = enckey[j] ^ i; - } - CRYPT_ArcFourCryptBlock(okeybuf, okeylen, tempkey, key_len); - } - } - int len = 32; - while (len && defpasscode[len - 1] == okeybuf[len - 1]) { - len--; - } - return CFX_ByteString(okeybuf, len); -} -FX_BOOL CPDF_StandardSecurityHandler::CheckOwnerPassword( - const uint8_t* password, - uint32_t pass_size, - uint8_t* key, - int32_t key_len) { - CFX_ByteString user_pass = GetUserPassword(password, pass_size, key_len); - if (CheckUserPassword(user_pass.raw_str(), user_pass.GetLength(), FALSE, key, - key_len)) { - return TRUE; - } - return CheckUserPassword(user_pass.raw_str(), user_pass.GetLength(), TRUE, - key, key_len); -} -FX_BOOL CPDF_StandardSecurityHandler::IsMetadataEncrypted() { - return m_pEncryptDict->GetBooleanBy("EncryptMetadata", TRUE); -} - -void CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, - CPDF_Array* pIdArray, - const uint8_t* user_pass, - uint32_t user_size, - const uint8_t* owner_pass, - uint32_t owner_size, - FX_BOOL bDefault, - uint32_t type) { - int cipher = 0, key_len = 0; - if (!LoadDict(pEncryptDict, type, cipher, key_len)) { - return; - } - if (bDefault && (!owner_pass || owner_size == 0)) { - owner_pass = user_pass; - owner_size = user_size; - } - if (m_Revision >= 5) { - int t = (int)time(NULL); - uint8_t sha[128]; - CRYPT_SHA256Start(sha); - CRYPT_SHA256Update(sha, (uint8_t*)&t, sizeof t); - CRYPT_SHA256Update(sha, m_EncryptKey, 32); - CRYPT_SHA256Update(sha, (uint8_t*)"there", 5); - CRYPT_SHA256Finish(sha, m_EncryptKey); - AES256_SetPassword(pEncryptDict, user_pass, user_size, FALSE, m_EncryptKey); - if (bDefault) { - AES256_SetPassword(pEncryptDict, owner_pass, owner_size, TRUE, - m_EncryptKey); - AES256_SetPerms(pEncryptDict, m_Permissions, - pEncryptDict->GetBooleanBy("EncryptMetadata", TRUE), - m_EncryptKey); - } - return; - } - if (bDefault) { - uint8_t passcode[32]; - uint32_t i; - for (i = 0; i < 32; i++) { - passcode[i] = - i < owner_size ? owner_pass[i] : defpasscode[i - owner_size]; - } - uint8_t digest[16]; - CRYPT_MD5Generate(passcode, 32, digest); - if (m_Revision >= 3) { - for (int i = 0; i < 50; i++) { - CRYPT_MD5Generate(digest, 16, digest); - } - } - uint8_t enckey[32]; - FXSYS_memcpy(enckey, digest, key_len); - for (i = 0; i < 32; i++) { - passcode[i] = i < user_size ? user_pass[i] : defpasscode[i - user_size]; - } - CRYPT_ArcFourCryptBlock(passcode, 32, enckey, key_len); - uint8_t tempkey[32]; - if (m_Revision >= 3) { - for (i = 1; i <= 19; i++) { - for (int j = 0; j < key_len; j++) { - tempkey[j] = enckey[j] ^ (uint8_t)i; - } - CRYPT_ArcFourCryptBlock(passcode, 32, tempkey, key_len); - } - } - pEncryptDict->SetAtString("O", CFX_ByteString(passcode, 32)); - } - CalcEncryptKey(m_pEncryptDict, (uint8_t*)user_pass, user_size, m_EncryptKey, - key_len, FALSE, pIdArray); - if (m_Revision < 3) { - uint8_t tempbuf[32]; - FXSYS_memcpy(tempbuf, defpasscode, 32); - CRYPT_ArcFourCryptBlock(tempbuf, 32, m_EncryptKey, key_len); - pEncryptDict->SetAtString("U", CFX_ByteString(tempbuf, 32)); - } else { - uint8_t md5[100]; - CRYPT_MD5Start(md5); - CRYPT_MD5Update(md5, defpasscode, 32); - if (pIdArray) { - CFX_ByteString id = pIdArray->GetStringAt(0); - CRYPT_MD5Update(md5, (uint8_t*)id.c_str(), id.GetLength()); - } - uint8_t digest[32]; - CRYPT_MD5Finish(md5, digest); - CRYPT_ArcFourCryptBlock(digest, 16, m_EncryptKey, key_len); - uint8_t tempkey[32]; - for (int i = 1; i <= 19; i++) { - for (int j = 0; j < key_len; j++) { - tempkey[j] = m_EncryptKey[j] ^ (uint8_t)i; - } - CRYPT_ArcFourCryptBlock(digest, 16, tempkey, key_len); - } - CRYPT_MD5Generate(digest, 16, digest + 16); - pEncryptDict->SetAtString("U", CFX_ByteString(digest, 32)); - } -} -void CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, - CPDF_Array* pIdArray, - const uint8_t* user_pass, - uint32_t user_size, - const uint8_t* owner_pass, - uint32_t owner_size, - uint32_t type) { - OnCreate(pEncryptDict, pIdArray, user_pass, user_size, owner_pass, owner_size, - TRUE, type); -} -void CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, - CPDF_Array* pIdArray, - const uint8_t* user_pass, - uint32_t user_size, - uint32_t type) { - OnCreate(pEncryptDict, pIdArray, user_pass, user_size, NULL, 0, FALSE, type); -} -void CPDF_StandardSecurityHandler::AES256_SetPassword( - CPDF_Dictionary* pEncryptDict, - const uint8_t* password, - uint32_t size, - FX_BOOL bOwner, - const uint8_t* key) { - uint8_t sha[128]; - CRYPT_SHA1Start(sha); - CRYPT_SHA1Update(sha, key, 32); - CRYPT_SHA1Update(sha, (uint8_t*)"hello", 5); - uint8_t digest[20]; - CRYPT_SHA1Finish(sha, digest); - CFX_ByteString ukey = pEncryptDict->GetStringBy("U"); - uint8_t digest1[48]; - if (m_Revision >= 6) { - Revision6_Hash(password, size, digest, bOwner ? ukey.raw_str() : nullptr, - digest1); - } else { - CRYPT_SHA256Start(sha); - CRYPT_SHA256Update(sha, password, size); - CRYPT_SHA256Update(sha, digest, 8); - if (bOwner) { - CRYPT_SHA256Update(sha, ukey.raw_str(), ukey.GetLength()); - } - CRYPT_SHA256Finish(sha, digest1); - } - FXSYS_memcpy(digest1 + 32, digest, 16); - pEncryptDict->SetAtString(bOwner ? "O" : "U", CFX_ByteString(digest1, 48)); - if (m_Revision >= 6) { - Revision6_Hash(password, size, digest + 8, - bOwner ? ukey.raw_str() : nullptr, digest1); - } else { - CRYPT_SHA256Start(sha); - CRYPT_SHA256Update(sha, password, size); - CRYPT_SHA256Update(sha, digest + 8, 8); - if (bOwner) { - CRYPT_SHA256Update(sha, ukey.raw_str(), ukey.GetLength()); - } - CRYPT_SHA256Finish(sha, digest1); - } - uint8_t* aes = FX_Alloc(uint8_t, 2048); - CRYPT_AESSetKey(aes, 16, digest1, 32, TRUE); - uint8_t iv[16]; - FXSYS_memset(iv, 0, 16); - CRYPT_AESSetIV(aes, iv); - CRYPT_AESEncrypt(aes, digest1, key, 32); - FX_Free(aes); - pEncryptDict->SetAtString(bOwner ? "OE" : "UE", CFX_ByteString(digest1, 32)); -} -void CPDF_StandardSecurityHandler::AES256_SetPerms( - CPDF_Dictionary* pEncryptDict, - uint32_t permissions, - FX_BOOL bEncryptMetadata, - const uint8_t* key) { - uint8_t buf[16]; - buf[0] = (uint8_t)permissions; - buf[1] = (uint8_t)(permissions >> 8); - buf[2] = (uint8_t)(permissions >> 16); - buf[3] = (uint8_t)(permissions >> 24); - buf[4] = 0xff; - buf[5] = 0xff; - buf[6] = 0xff; - buf[7] = 0xff; - buf[8] = bEncryptMetadata ? 'T' : 'F'; - buf[9] = 'a'; - buf[10] = 'd'; - buf[11] = 'b'; - uint8_t* aes = FX_Alloc(uint8_t, 2048); - CRYPT_AESSetKey(aes, 16, key, 32, TRUE); - uint8_t iv[16], buf1[16]; - FXSYS_memset(iv, 0, 16); - CRYPT_AESSetIV(aes, iv); - CRYPT_AESEncrypt(aes, buf1, buf, 16); - FX_Free(aes); - pEncryptDict->SetAtString("Perms", CFX_ByteString(buf1, 16)); -} diff --git a/core/fpdfapi/fpdf_parser/cpdf_standard_security_handler.h b/core/fpdfapi/fpdf_parser/cpdf_standard_security_handler.h deleted file mode 100644 index dfbf6a34f9..0000000000 --- a/core/fpdfapi/fpdf_parser/cpdf_standard_security_handler.h +++ /dev/null @@ -1,105 +0,0 @@ -// 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_FPDFAPI_FPDF_PARSER_CPDF_STANDARD_SECURITY_HANDLER_H_ -#define CORE_FPDFAPI_FPDF_PARSER_CPDF_STANDARD_SECURITY_HANDLER_H_ - -#include "core/fpdfapi/fpdf_parser/ipdf_security_handler.h" -#include "core/fxcrt/include/fx_string.h" -#include "core/fxcrt/include/fx_system.h" - -class CPDF_Array; - -#define PDF_ENCRYPT_CONTENT 0 - -class CPDF_StandardSecurityHandler : public IPDF_SecurityHandler { - public: - CPDF_StandardSecurityHandler(); - ~CPDF_StandardSecurityHandler() override; - - // IPDF_SecurityHandler: - FX_BOOL OnInit(CPDF_Parser* pParser, CPDF_Dictionary* pEncryptDict) override; - uint32_t GetPermissions() override; - FX_BOOL GetCryptInfo(int& cipher, - const uint8_t*& buffer, - int& keylen) override; - FX_BOOL IsMetadataEncrypted() override; - IPDF_CryptoHandler* CreateCryptoHandler() override; - - void OnCreate(CPDF_Dictionary* pEncryptDict, - CPDF_Array* pIdArray, - const uint8_t* user_pass, - uint32_t user_size, - const uint8_t* owner_pass, - uint32_t owner_size, - uint32_t type = PDF_ENCRYPT_CONTENT); - - void OnCreate(CPDF_Dictionary* pEncryptDict, - CPDF_Array* pIdArray, - const uint8_t* user_pass, - uint32_t user_size, - uint32_t type = PDF_ENCRYPT_CONTENT); - - CFX_ByteString GetUserPassword(const uint8_t* owner_pass, - uint32_t pass_size, - int32_t key_len); - int CheckPassword(const uint8_t* password, - uint32_t pass_size, - FX_BOOL bOwner, - uint8_t* key, - int key_len); - - private: - FX_BOOL LoadDict(CPDF_Dictionary* pEncryptDict); - FX_BOOL LoadDict(CPDF_Dictionary* pEncryptDict, - uint32_t type, - int& cipher, - int& key_len); - - FX_BOOL CheckUserPassword(const uint8_t* password, - uint32_t pass_size, - FX_BOOL bIgnoreEncryptMeta, - uint8_t* key, - int32_t key_len); - - FX_BOOL CheckOwnerPassword(const uint8_t* password, - uint32_t pass_size, - uint8_t* key, - int32_t key_len); - FX_BOOL AES256_CheckPassword(const uint8_t* password, - uint32_t size, - FX_BOOL bOwner, - uint8_t* key); - void AES256_SetPassword(CPDF_Dictionary* pEncryptDict, - const uint8_t* password, - uint32_t size, - FX_BOOL bOwner, - const uint8_t* key); - void AES256_SetPerms(CPDF_Dictionary* pEncryptDict, - uint32_t permission, - FX_BOOL bEncryptMetadata, - const uint8_t* key); - void OnCreate(CPDF_Dictionary* pEncryptDict, - CPDF_Array* pIdArray, - const uint8_t* user_pass, - uint32_t user_size, - const uint8_t* owner_pass, - uint32_t owner_size, - FX_BOOL bDefault, - uint32_t type); - FX_BOOL CheckSecurity(int32_t key_len); - - int m_Version; - int m_Revision; - CPDF_Parser* m_pParser; - CPDF_Dictionary* m_pEncryptDict; - uint32_t m_Permissions; - int m_Cipher; - uint8_t m_EncryptKey[32]; - int m_KeyLen; -}; - -#endif // CORE_FPDFAPI_FPDF_PARSER_CPDF_STANDARD_SECURITY_HANDLER_H_ diff --git a/core/fpdfapi/fpdf_parser/cpdf_syntax_parser.cpp b/core/fpdfapi/fpdf_parser/cpdf_syntax_parser.cpp index 889b58e928..5e1c05b2a1 100644 --- a/core/fpdfapi/fpdf_parser/cpdf_syntax_parser.cpp +++ b/core/fpdfapi/fpdf_parser/cpdf_syntax_parser.cpp @@ -9,6 +9,7 @@ #include #include "core/fpdfapi/fpdf_parser/cpdf_boolean.h" +#include "core/fpdfapi/fpdf_parser/cpdf_crypto_handler.h" #include "core/fpdfapi/fpdf_parser/cpdf_null.h" #include "core/fpdfapi/fpdf_parser/fpdf_parser_utility.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" @@ -19,7 +20,6 @@ #include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_string.h" #include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h" -#include "core/fpdfapi/fpdf_parser/ipdf_crypto_handler.h" #include "core/fpdfapi/include/cpdf_modulemgr.h" #include "core/fxcrt/include/fx_ext.h" #include "third_party/base/numerics/safe_math.h" @@ -646,7 +646,7 @@ CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict, const CFX_ByteStringC kEndStreamStr("endstream"); const CFX_ByteStringC kEndObjStr("endobj"); - IPDF_CryptoHandler* pCryptoHandler = + CPDF_CryptoHandler* pCryptoHandler = objnum == (uint32_t)m_MetadataObjnum ? nullptr : m_pCryptoHandler.get(); if (!pCryptoHandler) { FX_BOOL bSearchForKeyword = TRUE; @@ -985,6 +985,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/fpdfapi/fpdf_parser/cpdf_syntax_parser.h b/core/fpdfapi/fpdf_parser/cpdf_syntax_parser.h index 04fe6f4fec..63992a85ab 100644 --- a/core/fpdfapi/fpdf_parser/cpdf_syntax_parser.h +++ b/core/fpdfapi/fpdf_parser/cpdf_syntax_parser.h @@ -11,12 +11,12 @@ #include "core/fxcrt/include/fx_basic.h" +class CPDF_CryptoHandler; class CPDF_Dictionary; class CPDF_IndirectObjectHolder; class CPDF_Object; 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, uint32_t size); FX_BOOL GetCharAt(FX_FILESIZE pos, uint8_t& ch); @@ -88,7 +88,7 @@ class CPDF_SyntaxParser { uint8_t* m_pFileBuf; uint32_t m_BufSize; FX_FILESIZE m_BufOffset; - std::unique_ptr m_pCryptoHandler; + std::unique_ptr m_pCryptoHandler; uint8_t m_WordBuffer[257]; uint32_t m_WordSize; }; diff --git a/core/fpdfapi/fpdf_parser/include/cpdf_parser.h b/core/fpdfapi/fpdf_parser/include/cpdf_parser.h index 45aca8f21a..5331ccafb1 100644 --- a/core/fpdfapi/fpdf_parser/include/cpdf_parser.h +++ b/core/fpdfapi/fpdf_parser/include/cpdf_parser.h @@ -14,15 +14,15 @@ #include "core/fxcrt/include/fx_basic.h" class CPDF_Array; +class CPDF_CryptoHandler; class CPDF_Dictionary; class CPDF_Document; class CPDF_IndirectObjectHolder; class CPDF_Object; +class CPDF_SecurityHandler; class CPDF_StreamAcc; class CPDF_SyntaxParser; class IFX_FileRead; -class IPDF_CryptoHandler; -class IPDF_SecurityHandler; class CPDF_Parser { public: @@ -63,7 +63,7 @@ class CPDF_Parser { bool IsVersionUpdated() const { return m_bVersionUpdated; } bool IsObjectFreeOrNull(uint32_t objnum) const; FX_BOOL IsFormStream(uint32_t objnum, FX_BOOL& bForm); - IPDF_CryptoHandler* GetCryptoHandler(); + CPDF_CryptoHandler* GetCryptoHandler(); IFX_FileRead* GetFileAccess() const; FX_FILESIZE GetObjectOffset(uint32_t objnum) const; @@ -123,7 +123,7 @@ class CPDF_Parser { CPDF_Dictionary* m_pEncryptDict; FX_FILESIZE m_LastXRefOffset; FX_BOOL m_bXRefStream; - std::unique_ptr m_pSecurityHandler; + std::unique_ptr m_pSecurityHandler; CFX_ByteString m_bsRecipient; CFX_ByteString m_FilePath; CFX_ByteString m_Password; diff --git a/core/fpdfapi/fpdf_parser/ipdf_crypto_handler.h b/core/fpdfapi/fpdf_parser/ipdf_crypto_handler.h deleted file mode 100644 index ea45a6b9cc..0000000000 --- a/core/fpdfapi/fpdf_parser/ipdf_crypto_handler.h +++ /dev/null @@ -1,45 +0,0 @@ -// 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_FPDFAPI_FPDF_PARSER_IPDF_CRYPTO_HANDLER_H_ -#define CORE_FPDFAPI_FPDF_PARSER_IPDF_CRYPTO_HANDLER_H_ - -#include "core/fxcrt/include/fx_basic.h" - -class CPDF_Dictionary; -class IPDF_SecurityHandler; - -class IPDF_CryptoHandler { - public: - virtual ~IPDF_CryptoHandler(); - - virtual FX_BOOL Init(CPDF_Dictionary* pEncryptDict, - IPDF_SecurityHandler* pSecurityHandler) = 0; - - virtual uint32_t DecryptGetSize(uint32_t src_size) = 0; - virtual void* DecryptStart(uint32_t objnum, uint32_t gennum) = 0; - virtual FX_BOOL DecryptStream(void* context, - const uint8_t* src_buf, - uint32_t src_size, - CFX_BinaryBuf& dest_buf) = 0; - - virtual FX_BOOL DecryptFinish(void* context, CFX_BinaryBuf& dest_buf) = 0; - virtual uint32_t EncryptGetSize(uint32_t objnum, - uint32_t version, - const uint8_t* src_buf, - uint32_t src_size) = 0; - - virtual FX_BOOL EncryptContent(uint32_t objnum, - uint32_t version, - const uint8_t* src_buf, - uint32_t src_size, - uint8_t* dest_buf, - uint32_t& dest_size) = 0; - - void Decrypt(uint32_t objnum, uint32_t version, CFX_ByteString& str); -}; - -#endif // CORE_FPDFAPI_FPDF_PARSER_IPDF_CRYPTO_HANDLER_H_ diff --git a/core/fpdfapi/fpdf_parser/ipdf_security_handler.h b/core/fpdfapi/fpdf_parser/ipdf_security_handler.h deleted file mode 100644 index e7eb822a83..0000000000 --- a/core/fpdfapi/fpdf_parser/ipdf_security_handler.h +++ /dev/null @@ -1,36 +0,0 @@ -// 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_FPDFAPI_FPDF_PARSER_IPDF_SECURITY_HANDLER_H_ -#define CORE_FPDFAPI_FPDF_PARSER_IPDF_SECURITY_HANDLER_H_ - -#include "core/fxcrt/include/fx_system.h" - -class CPDF_Parser; -class CPDF_Dictionary; -class IPDF_CryptoHandler; - -#define FXCIPHER_NONE 0 -#define FXCIPHER_RC4 1 -#define FXCIPHER_AES 2 -#define FXCIPHER_AES2 3 - -class IPDF_SecurityHandler { - public: - virtual ~IPDF_SecurityHandler(); - virtual FX_BOOL OnInit(CPDF_Parser* pParser, - CPDF_Dictionary* pEncryptDict) = 0; - - virtual uint32_t GetPermissions() = 0; - virtual FX_BOOL GetCryptInfo(int& cipher, - const uint8_t*& buffer, - int& keylen) = 0; - - virtual FX_BOOL IsMetadataEncrypted() = 0; - virtual IPDF_CryptoHandler* CreateCryptoHandler() = 0; -}; - -#endif // CORE_FPDFAPI_FPDF_PARSER_IPDF_SECURITY_HANDLER_H_ -- cgit v1.2.3