7#include "core/fpdfapi/parser/cpdf_crypto_handler.h"
15#include "constants/form_fields.h"
16#include "core/fdrm/fx_crypt.h"
17#include "core/fpdfapi/parser/cpdf_dictionary.h"
18#include "core/fpdfapi/parser/cpdf_number.h"
19#include "core/fpdfapi/parser/cpdf_object_walker.h"
20#include "core/fpdfapi/parser/cpdf_parser.h"
21#include "core/fpdfapi/parser/cpdf_security_handler.h"
22#include "core/fpdfapi/parser/cpdf_simple_parser.h"
23#include "core/fpdfapi/parser/cpdf_stream.h"
24#include "core/fpdfapi/parser/cpdf_stream_acc.h"
25#include "core/fpdfapi/parser/cpdf_string.h"
26#include "third_party/base/check.h"
27#include "third_party/base/check_op.h"
31constexpr char kContentsKey[] =
"Contents";
32constexpr char kTypeKey[] =
"Type";
38 const CPDF_Dictionary* dictionary) {
42 dictionary->GetDirectObjectFor(kTypeKey);
50 pdfium::span<
const uint8_t> source,
52 size_t& dest_size)
const {
54 memcpy(dest_buf, source.data(), source.size());
58 size_t realkeylen =
sizeof(realkey);
59 if (m_Cipher != Cipher::kAES || m_KeyLen != 32) {
61 PopulateKey(objnum, gennum, key1);
63 if (m_Cipher == Cipher::kAES)
64 memcpy(key1 + m_KeyLen + 5,
"sAlT", 4);
65 size_t len = m_Cipher == Cipher::kAES ? m_KeyLen + 9 : m_KeyLen + 5;
66 CRYPT_MD5Generate({key1, len}, realkey);
67 realkeylen = std::min(m_KeyLen + 5,
sizeof(realkey));
70 CRYPT_AESSetKey(m_pAESContext.get(),
71 m_KeyLen == 32 ? m_EncryptKey : realkey, m_KeyLen);
73 for (
int i = 0; i < 16; i++) {
74 iv[i] = (uint8_t)rand();
76 CRYPT_AESSetIV(m_pAESContext.get(), iv);
77 memcpy(dest_buf, iv, 16);
78 int nblocks = source.size() / 16;
79 CRYPT_AESEncrypt(m_pAESContext.get(), dest_buf + 16, source.data(),
82 memcpy(padding, source.data() + nblocks * 16, source.size() % 16);
83 memset(padding + source.size() % 16, 16 - source.size() % 16,
84 16 - source.size() % 16);
85 CRYPT_AESEncrypt(m_pAESContext.get(), dest_buf + nblocks * 16 + 16, padding,
87 dest_size = 32 + nblocks * 16;
89 DCHECK_EQ(dest_size, source.size());
90 if (dest_buf != source.data())
91 memcpy(dest_buf, source.data(), source.size());
92 CRYPT_ArcFourCryptBlock({dest_buf, dest_size}, {realkey, realkeylen});
107 if (m_Cipher == Cipher::kAES && m_KeyLen == 32) {
115 PopulateKey(objnum, gennum, key1);
117 if (m_Cipher == Cipher::kAES)
118 memcpy(key1 + m_KeyLen + 5,
"sAlT", 4);
121 size_t len = m_Cipher == Cipher::kAES ? m_KeyLen + 9 : m_KeyLen + 5;
122 CRYPT_MD5Generate({key1, len}, realkey);
123 size_t realkeylen = std::min(m_KeyLen + 5,
sizeof(realkey));
133 CRYPT_ArcFourSetup(pContext, {realkey, realkeylen});
138 pdfium::span<
const uint8_t> source,
148 size_t old_size = dest_buf.GetSize();
156 uint32_t src_off = 0;
157 uint32_t src_left = source.size();
160 if (copy_size > src_left) {
161 copy_size = src_left;
165 src_off += copy_size;
166 src_left -= copy_size;
173 }
else if (src_off < source.size()) {
174 uint8_t block_buf[16];
201 uint8_t block_buf[16];
203 if (block_buf[15] < 16) {
205 pdfium::make_span(block_buf).first(16 - block_buf[15])
);
214 const ByteString& str) {
216 void* context = DecryptStart(objnum, gennum);
217 DecryptStream(context, str.raw_span(), dest_buf);
218 DecryptFinish(context, dest_buf);
219 return ByteString(dest_buf
.GetSpan());
223 return m_Cipher ==
Cipher::kAES ? src_size - 16 : src_size;
234 struct MayBeSignature {
239 std::stack<MayBeSignature> may_be_sign_dictionaries;
240 const uint32_t obj_num = object->GetObjNum();
241 const uint32_t gen_num = object->GetGenNum();
244 while (object_to_decrypt) {
245 CPDF_NonConstObjectWalker walker(
std::move(object_to_decrypt));
246 while (RetainPtr<CPDF_Object> child = walker.GetNext()) {
247 RetainPtr<
const CPDF_Dictionary> parent_dict =
248 walker.GetParent() ? walker.GetParent()->GetDict() :
nullptr;
250 (parent_dict->KeyExist(kTypeKey) ||
258 may_be_sign_dictionaries.push(
259 {
std::move(parent_dict),
std::move(child)});
264 if (child->IsString()) {
266 CPDF_String* str = child->AsMutableString();
270 if (child->IsStream()) {
272 CPDF_Stream* stream = child->AsMutableStream();
274 pdfium::MakeRetain<CPDF_StreamAcc>(pdfium::WrapRetain(stream));
275 stream_access->LoadAllDataRaw();
283 decrypted_buf.EstimateSize(DecryptGetSize(stream_access->GetSize()));
285 void* context = DecryptStart(obj_num, gen_num);
286 bool decrypt_result =
287 DecryptStream(context, stream_access->GetSpan(), decrypted_buf);
288 decrypt_result &= DecryptFinish(context, decrypted_buf);
289 if (decrypt_result) {
290 stream->TakeData(decrypted_buf.DetachBuffer());
298 while (!may_be_sign_dictionaries.empty()) {
299 auto dict_and_contents = may_be_sign_dictionaries.top();
300 may_be_sign_dictionaries.pop();
303 object_to_decrypt = dict_and_contents.contents;
312 pdfium::span<
const uint8_t> source)
const {
313 return m_Cipher ==
Cipher::kAES ? source.size() + 32 : source.size();
320 DCHECK(cipher != Cipher::kAES || keylen == 16 || keylen == 24 ||
322 DCHECK(cipher != Cipher::kAES2 || keylen == 32);
323 DCHECK(cipher != Cipher::kRC4 || (keylen >= 5 && keylen <= 16));
325 if (m_Cipher != Cipher::kNone)
326 memcpy(m_EncryptKey, key, m_KeyLen);
328 if (m_Cipher == Cipher::kAES)
329 m_pAESContext.reset(FX_Alloc(CRYPT_aes_context, 1));
336 uint8_t* key)
const {
337 memcpy(key, m_EncryptKey, m_KeyLen);
338 key[m_KeyLen + 0] = (uint8_t)objnum;
339 key[m_KeyLen + 1] = (uint8_t)(objnum >> 8);
340 key[m_KeyLen + 2] = (uint8_t)(objnum >> 16);
341 key[m_KeyLen + 3] = (uint8_t)gennum;
342 key[m_KeyLen + 4] = (uint8_t)(gennum >> 8);
bool DecryptObjectTree(RetainPtr< CPDF_Object > object)
static bool IsSignatureDictionary(const CPDF_Dictionary *dictionary)
CPDF_CryptoHandler(Cipher cipher, const uint8_t *key, size_t keylen)
size_t EncryptGetSize(pdfium::span< const uint8_t > source) const
void EncryptContent(uint32_t objnum, uint32_t gennum, pdfium::span< const uint8_t > source, uint8_t *dest_buf, size_t &dest_size) const
RetainPtr< const CPDF_Object > GetDirectObjectFor(const ByteString &key) const
void SkipWalkIntoCurrentObject()
const ByteString & dictionary_key() const
void SetData(pdfium::span< const uint8_t > pData)
void SetString(const ByteString &str) override
ByteString GetString() const override
void AppendSpan(pdfium::span< const uint8_t > span)
pdfium::span< const uint8_t > GetSpan() const
pdfium::span< uint8_t > GetMutableSpan()
void CRYPT_AESSetIV(CRYPT_aes_context *context, const uint8_t *iv)
void CRYPT_AESSetKey(CRYPT_aes_context *context, const uint8_t *key, uint32_t keylen)
void CRYPT_AESDecrypt(CRYPT_aes_context *context, uint8_t *dest, const uint8_t *src, uint32_t size)
CRYPT_aes_context m_Context