blob: 43ae781b6c8695fc8dd042c9e4aabe498820269d [file] [log] [blame]
K. Moon832a6942022-10-31 20:11:31 +00001// Copyright 2014 The PDFium Authors
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Lei Zhang95e854f2015-06-13 00:58:06 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
dsinclair488b7ad2016-10-04 11:55:50 -07007#include "core/fpdfapi/parser/cpdf_crypto_handler.h"
Lei Zhanga9fa50f2015-11-10 09:45:32 -08008
Tom Sepeza1193ae2016-03-09 17:42:18 -08009#include <time.h>
10
Artem Strygina0819312017-10-03 21:51:18 +030011#include <algorithm>
Artem Strygind8169d72017-10-02 19:19:28 +030012#include <stack>
13#include <utility>
14
Lei Zhang865ffb12019-02-26 20:18:19 +000015#include "constants/form_fields.h"
Lei Zhangd145e4b2018-10-12 18:54:31 +000016#include "core/fdrm/fx_crypt.h"
Artem Strygind8169d72017-10-02 19:19:28 +030017#include "core/fpdfapi/parser/cpdf_dictionary.h"
18#include "core/fpdfapi/parser/cpdf_number.h"
19#include "core/fpdfapi/parser/cpdf_object_walker.h"
dsinclair488b7ad2016-10-04 11:55:50 -070020#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"
Artem Strygind8169d72017-10-02 19:19:28 +030023#include "core/fpdfapi/parser/cpdf_stream.h"
24#include "core/fpdfapi/parser/cpdf_stream_acc.h"
25#include "core/fpdfapi/parser/cpdf_string.h"
Tom Sepeza60e6a22021-01-27 01:21:59 +000026#include "third_party/base/check.h"
Lei Zhang45829202021-04-16 16:42:11 +000027#include "third_party/base/check_op.h"
Artem Strygind8169d72017-10-02 19:19:28 +030028
29namespace {
30
31constexpr char kContentsKey[] = "Contents";
32constexpr char kTypeKey[] = "Type";
Artem Strygind8169d72017-10-02 19:19:28 +030033
34} // namespace
35
36// static
37bool CPDF_CryptoHandler::IsSignatureDictionary(
38 const CPDF_Dictionary* dictionary) {
39 if (!dictionary)
40 return false;
Tom Sepeze0dcb6b2022-09-08 00:29:53 +000041 RetainPtr<const CPDF_Object> type_obj =
42 dictionary->GetDirectObjectFor(kTypeKey);
Artem Strygind8169d72017-10-02 19:19:28 +030043 if (!type_obj)
Lei Zhang865ffb12019-02-26 20:18:19 +000044 type_obj = dictionary->GetDirectObjectFor(pdfium::form_fields::kFT);
Lei Zhangf496e252019-02-26 20:20:19 +000045 return type_obj && type_obj->GetString() == pdfium::form_fields::kSig;
Artem Strygind8169d72017-10-02 19:19:28 +030046}
Lei Zhanga9fa50f2015-11-10 09:45:32 -080047
Tom Sepez652c1892022-04-05 15:41:49 +000048void CPDF_CryptoHandler::EncryptContent(uint32_t objnum,
49 uint32_t gennum,
50 pdfium::span<const uint8_t> source,
51 uint8_t* dest_buf,
52 size_t& dest_size) const {
Tom Sepez12d343e2021-05-19 01:50:24 +000053 if (m_Cipher == Cipher::kNone) {
Tom Sepezdebd2d22018-05-16 18:32:43 +000054 memcpy(dest_buf, source.data(), source.size());
Nico Weber9d8ec5a2015-08-04 13:00:21 -070055 return;
56 }
57 uint8_t realkey[16];
Lei Zhang5cedaeb2019-12-05 00:23:13 +000058 size_t realkeylen = sizeof(realkey);
Tom Sepez12d343e2021-05-19 01:50:24 +000059 if (m_Cipher != Cipher::kAES || m_KeyLen != 32) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070060 uint8_t key1[32];
dsinclair0690c352016-08-02 10:48:28 -070061 PopulateKey(objnum, gennum, key1);
62
Tom Sepez12d343e2021-05-19 01:50:24 +000063 if (m_Cipher == Cipher::kAES)
Dan Sinclair1c5d0b42017-04-03 15:05:11 -040064 memcpy(key1 + m_KeyLen + 5, "sAlT", 4);
Tom Sepez12d343e2021-05-19 01:50:24 +000065 size_t len = m_Cipher == Cipher::kAES ? m_KeyLen + 9 : m_KeyLen + 5;
Lei Zhangea208512019-12-18 00:42:11 +000066 CRYPT_MD5Generate({key1, len}, realkey);
Lei Zhangb92ff3c2019-12-05 22:25:28 +000067 realkeylen = std::min(m_KeyLen + 5, sizeof(realkey));
Nico Weber9d8ec5a2015-08-04 13:00:21 -070068 }
Tom Sepez12d343e2021-05-19 01:50:24 +000069 if (m_Cipher == Cipher::kAES) {
Tom Sepezbd8855b2018-10-03 19:53:38 +000070 CRYPT_AESSetKey(m_pAESContext.get(),
Tom Sepezcf832952021-05-24 18:36:55 +000071 m_KeyLen == 32 ? m_EncryptKey : realkey, m_KeyLen);
Tom Sepez652c1892022-04-05 15:41:49 +000072 uint8_t iv[16];
73 for (int i = 0; i < 16; i++) {
74 iv[i] = (uint8_t)rand();
Nico Weber9d8ec5a2015-08-04 13:00:21 -070075 }
Tom Sepez652c1892022-04-05 15:41:49 +000076 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(),
80 nblocks * 16);
81 uint8_t padding[16];
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,
86 16);
87 dest_size = 32 + nblocks * 16;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070088 } else {
Lei Zhang45829202021-04-16 16:42:11 +000089 DCHECK_EQ(dest_size, source.size());
Lei Zhang5cedaeb2019-12-05 00:23:13 +000090 if (dest_buf != source.data())
Tom Sepezdebd2d22018-05-16 18:32:43 +000091 memcpy(dest_buf, source.data(), source.size());
Lei Zhang2e0549b2019-12-05 21:59:34 +000092 CRYPT_ArcFourCryptBlock({dest_buf, dest_size}, {realkey, realkeylen});
Nico Weber9d8ec5a2015-08-04 13:00:21 -070093 }
94}
Tom Sepezd21cdda2016-02-23 10:11:11 -080095
96struct AESCryptContext {
tsepez12f3e4a2016-11-02 15:17:29 -070097 bool m_bIV;
tsepezb5e8f142016-03-25 15:18:35 -070098 uint32_t m_BlockOffset;
Tom Sepez332ef542017-05-05 17:08:07 -070099 CRYPT_aes_context m_Context;
Tom Sepez232b9182018-04-03 16:32:19 +0000100 uint8_t m_Block[16];
Tom Sepezd21cdda2016-02-23 10:11:11 -0800101};
102
Tom Sepez97197f42021-10-22 00:50:04 +0000103void* CPDF_CryptoHandler::DecryptStart(uint32_t objnum, uint32_t gennum) {
104 if (m_Cipher == Cipher::kNone)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700105 return this;
Tom Sepez97197f42021-10-22 00:50:04 +0000106
Tom Sepez12d343e2021-05-19 01:50:24 +0000107 if (m_Cipher == Cipher::kAES && m_KeyLen == 32) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700108 AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1);
tsepez12f3e4a2016-11-02 15:17:29 -0700109 pContext->m_bIV = true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700110 pContext->m_BlockOffset = 0;
Tom Sepezcf832952021-05-24 18:36:55 +0000111 CRYPT_AESSetKey(&pContext->m_Context, m_EncryptKey, 32);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700112 return pContext;
113 }
114 uint8_t key1[48];
dsinclair0690c352016-08-02 10:48:28 -0700115 PopulateKey(objnum, gennum, key1);
116
Tom Sepez12d343e2021-05-19 01:50:24 +0000117 if (m_Cipher == Cipher::kAES)
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400118 memcpy(key1 + m_KeyLen + 5, "sAlT", 4);
Lei Zhangb92ff3c2019-12-05 22:25:28 +0000119
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700120 uint8_t realkey[16];
Tom Sepez12d343e2021-05-19 01:50:24 +0000121 size_t len = m_Cipher == Cipher::kAES ? m_KeyLen + 9 : m_KeyLen + 5;
Lei Zhangea208512019-12-18 00:42:11 +0000122 CRYPT_MD5Generate({key1, len}, realkey);
Lei Zhangb92ff3c2019-12-05 22:25:28 +0000123 size_t realkeylen = std::min(m_KeyLen + 5, sizeof(realkey));
124
Tom Sepez12d343e2021-05-19 01:50:24 +0000125 if (m_Cipher == Cipher::kAES) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700126 AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1);
tsepez12f3e4a2016-11-02 15:17:29 -0700127 pContext->m_bIV = true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700128 pContext->m_BlockOffset = 0;
Tom Sepezcf832952021-05-24 18:36:55 +0000129 CRYPT_AESSetKey(&pContext->m_Context, realkey, 16);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700130 return pContext;
131 }
tsepezd88090f2016-11-21 14:29:12 -0800132 CRYPT_rc4_context* pContext = FX_Alloc(CRYPT_rc4_context, 1);
Lei Zhangc4d5acc2019-12-06 16:51:20 +0000133 CRYPT_ArcFourSetup(pContext, {realkey, realkeylen});
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700134 return pContext;
135}
dsinclair0690c352016-08-02 10:48:28 -0700136
Tom Sepez66c68902022-04-05 15:39:29 +0000137bool CPDF_CryptoHandler::DecryptStream(void* context,
138 pdfium::span<const uint8_t> source,
Tom Sepez44a3bf32022-08-02 20:21:39 +0000139 BinaryBuffer& dest_buf) {
Tom Sepezdebd2d22018-05-16 18:32:43 +0000140 if (!context)
tsepez12f3e4a2016-11-02 15:17:29 -0700141 return false;
Tom Sepezdebd2d22018-05-16 18:32:43 +0000142
Tom Sepez12d343e2021-05-19 01:50:24 +0000143 if (m_Cipher == Cipher::kNone) {
Tom Sepez5c18e872022-11-17 20:41:38 +0000144 dest_buf.AppendSpan(source);
tsepez12f3e4a2016-11-02 15:17:29 -0700145 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700146 }
Tom Sepez12d343e2021-05-19 01:50:24 +0000147 if (m_Cipher == Cipher::kRC4) {
Lei Zhanga5747ca2022-08-16 18:53:12 +0000148 size_t old_size = dest_buf.GetSize();
Tom Sepez5c18e872022-11-17 20:41:38 +0000149 dest_buf.AppendSpan(source);
Tom Sepezbd177612022-09-16 21:04:42 +0000150 CRYPT_ArcFourCrypt(
151 static_cast<CRYPT_rc4_context*>(context),
152 dest_buf.GetMutableSpan().subspan(old_size, source.size()));
tsepez12f3e4a2016-11-02 15:17:29 -0700153 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700154 }
Tom Sepez9b8b2172018-04-25 22:12:34 +0000155 AESCryptContext* pContext = static_cast<AESCryptContext*>(context);
tsepezb5e8f142016-03-25 15:18:35 -0700156 uint32_t src_off = 0;
Tom Sepezdebd2d22018-05-16 18:32:43 +0000157 uint32_t src_left = source.size();
Anton Bikineev7ac13342022-01-24 21:25:15 +0000158 while (true) {
tsepezb5e8f142016-03-25 15:18:35 -0700159 uint32_t copy_size = 16 - pContext->m_BlockOffset;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700160 if (copy_size > src_left) {
161 copy_size = src_left;
162 }
Tom Sepezdebd2d22018-05-16 18:32:43 +0000163 memcpy(pContext->m_Block + pContext->m_BlockOffset, source.data() + src_off,
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400164 copy_size);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700165 src_off += copy_size;
166 src_left -= copy_size;
167 pContext->m_BlockOffset += copy_size;
168 if (pContext->m_BlockOffset == 16) {
Tom Sepez66c68902022-04-05 15:39:29 +0000169 if (pContext->m_bIV) {
Tom Sepez332ef542017-05-05 17:08:07 -0700170 CRYPT_AESSetIV(&pContext->m_Context, pContext->m_Block);
tsepez12f3e4a2016-11-02 15:17:29 -0700171 pContext->m_bIV = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700172 pContext->m_BlockOffset = 0;
Tom Sepezdebd2d22018-05-16 18:32:43 +0000173 } else if (src_off < source.size()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700174 uint8_t block_buf[16];
Tom Sepez66c68902022-04-05 15:39:29 +0000175 CRYPT_AESDecrypt(&pContext->m_Context, block_buf, pContext->m_Block,
176 16);
Tom Sepez5c18e872022-11-17 20:41:38 +0000177 dest_buf.AppendSpan(block_buf);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700178 pContext->m_BlockOffset = 0;
179 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700180 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700181 if (!src_left) {
182 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700183 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700184 }
tsepez12f3e4a2016-11-02 15:17:29 -0700185 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700186}
Tom Sepez652c1892022-04-05 15:41:49 +0000187
Tom Sepez44a3bf32022-08-02 20:21:39 +0000188bool CPDF_CryptoHandler::DecryptFinish(void* context, BinaryBuffer& dest_buf) {
Tom Sepez652c1892022-04-05 15:41:49 +0000189 if (!context)
tsepez12f3e4a2016-11-02 15:17:29 -0700190 return false;
Tom Sepez652c1892022-04-05 15:41:49 +0000191
192 if (m_Cipher == Cipher::kNone)
tsepez12f3e4a2016-11-02 15:17:29 -0700193 return true;
Tom Sepez652c1892022-04-05 15:41:49 +0000194
Tom Sepez12d343e2021-05-19 01:50:24 +0000195 if (m_Cipher == Cipher::kRC4) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700196 FX_Free(context);
tsepez12f3e4a2016-11-02 15:17:29 -0700197 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700198 }
Tom Sepezea3a2522018-04-26 18:33:58 +0000199 auto* pContext = static_cast<AESCryptContext*>(context);
Tom Sepez652c1892022-04-05 15:41:49 +0000200 if (pContext->m_BlockOffset == 16) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700201 uint8_t block_buf[16];
Tom Sepez332ef542017-05-05 17:08:07 -0700202 CRYPT_AESDecrypt(&pContext->m_Context, block_buf, pContext->m_Block, 16);
Tom Sepez5c18e872022-11-17 20:41:38 +0000203 if (block_buf[15] < 16) {
204 dest_buf.AppendSpan(
205 pdfium::make_span(block_buf).first(16 - block_buf[15]));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700206 }
207 }
208 FX_Free(pContext);
tsepez12f3e4a2016-11-02 15:17:29 -0700209 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700210}
dsinclair2fa0e132016-04-19 10:32:45 -0700211
Ryan Harrison275e2602017-09-18 14:23:18 -0400212ByteString CPDF_CryptoHandler::Decrypt(uint32_t objnum,
213 uint32_t gennum,
214 const ByteString& str) {
Tom Sepez44a3bf32022-08-02 20:21:39 +0000215 BinaryBuffer dest_buf;
dsinclair2fa0e132016-04-19 10:32:45 -0700216 void* context = DecryptStart(objnum, gennum);
Tom Sepez24b3a202019-07-22 17:47:48 +0000217 DecryptStream(context, str.raw_span(), dest_buf);
dsinclair2fa0e132016-04-19 10:32:45 -0700218 DecryptFinish(context, dest_buf);
Tom Sepez5adae6d2021-12-16 23:16:35 +0000219 return ByteString(dest_buf.GetSpan());
dsinclair2fa0e132016-04-19 10:32:45 -0700220}
221
Tom Sepezc73f9712021-11-09 17:04:29 +0000222size_t CPDF_CryptoHandler::DecryptGetSize(size_t src_size) {
Tom Sepez12d343e2021-05-19 01:50:24 +0000223 return m_Cipher == Cipher::kAES ? src_size - 16 : src_size;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700224}
Lei Zhangaa23e702016-01-29 18:03:40 -0800225
Ryan Harrison5b2092a2017-09-12 15:30:55 -0400226bool CPDF_CryptoHandler::IsCipherAES() const {
Tom Sepez12d343e2021-05-19 01:50:24 +0000227 return m_Cipher == Cipher::kAES;
Ryan Harrison5b2092a2017-09-12 15:30:55 -0400228}
229
Tom Sepeza3097da2019-05-01 16:42:36 +0000230bool CPDF_CryptoHandler::DecryptObjectTree(RetainPtr<CPDF_Object> object) {
Artem Strygind8169d72017-10-02 19:19:28 +0300231 if (!object)
Tom Sepeza3097da2019-05-01 16:42:36 +0000232 return false;
Artem Strygind8169d72017-10-02 19:19:28 +0300233
234 struct MayBeSignature {
Tom Sepeza8e77a12023-05-05 23:40:52 +0000235 RetainPtr<const CPDF_Dictionary> parent;
Tom Sepez65f7bed2022-09-06 18:22:02 +0000236 RetainPtr<CPDF_Object> contents;
Artem Strygind8169d72017-10-02 19:19:28 +0300237 };
238
239 std::stack<MayBeSignature> may_be_sign_dictionaries;
240 const uint32_t obj_num = object->GetObjNum();
241 const uint32_t gen_num = object->GetGenNum();
242
Tom Sepez65f7bed2022-09-06 18:22:02 +0000243 RetainPtr<CPDF_Object> object_to_decrypt = object;
Artem Strygind8169d72017-10-02 19:19:28 +0300244 while (object_to_decrypt) {
Tom Sepezc3ff4182022-09-06 19:06:02 +0000245 CPDF_NonConstObjectWalker walker(std::move(object_to_decrypt));
Tom Sepez65f7bed2022-09-06 18:22:02 +0000246 while (RetainPtr<CPDF_Object> child = walker.GetNext()) {
Tom Sepeza416d842022-09-16 22:24:24 +0000247 RetainPtr<const CPDF_Dictionary> parent_dict =
Artem Strygind8169d72017-10-02 19:19:28 +0300248 walker.GetParent() ? walker.GetParent()->GetDict() : nullptr;
249 if (walker.dictionary_key() == kContentsKey &&
Lei Zhang865ffb12019-02-26 20:18:19 +0000250 (parent_dict->KeyExist(kTypeKey) ||
251 parent_dict->KeyExist(pdfium::form_fields::kFT))) {
Artem Strygind8169d72017-10-02 19:19:28 +0300252 // This object may be contents of signature dictionary.
253 // But now values of 'Type' and 'FT' of dictionary keys are encrypted,
254 // and we can not check this.
255 // Temporary skip it, to prevent signature corruption.
256 // It will be decrypted on next interations, if this is not contents of
257 // signature dictionary.
Tom Sepeza8e77a12023-05-05 23:40:52 +0000258 may_be_sign_dictionaries.push(
259 {std::move(parent_dict), std::move(child)});
Artem Strygind8169d72017-10-02 19:19:28 +0300260 walker.SkipWalkIntoCurrentObject();
261 continue;
262 }
263 // Strings decryption.
264 if (child->IsString()) {
265 // TODO(art-snake): Move decryption into the CPDF_String class.
Tom Sepezd6daaed2022-09-02 23:58:32 +0000266 CPDF_String* str = child->AsMutableString();
Artem Strygind8169d72017-10-02 19:19:28 +0300267 str->SetString(Decrypt(obj_num, gen_num, str->GetString()));
268 }
269 // Stream decryption.
270 if (child->IsStream()) {
271 // TODO(art-snake): Move decryption into the CPDF_Stream class.
Tom Sepezd6daaed2022-09-02 23:58:32 +0000272 CPDF_Stream* stream = child->AsMutableStream();
Tom Sepez23705d92022-09-13 00:32:26 +0000273 auto stream_access =
274 pdfium::MakeRetain<CPDF_StreamAcc>(pdfium::WrapRetain(stream));
Lei Zhang07401ba2017-12-11 22:12:08 +0000275 stream_access->LoadAllDataRaw();
Artem Strygind8169d72017-10-02 19:19:28 +0300276
277 if (IsCipherAES() && stream_access->GetSize() < 16) {
Tom Sepez367ed462018-08-23 23:52:53 +0000278 stream->SetData({});
Artem Strygind8169d72017-10-02 19:19:28 +0300279 continue;
280 }
281
Tom Sepez44a3bf32022-08-02 20:21:39 +0000282 BinaryBuffer decrypted_buf;
Artem Strygind8169d72017-10-02 19:19:28 +0300283 decrypted_buf.EstimateSize(DecryptGetSize(stream_access->GetSize()));
284
285 void* context = DecryptStart(obj_num, gen_num);
286 bool decrypt_result =
Lei Zhangdd4e75a2019-12-05 22:00:04 +0000287 DecryptStream(context, stream_access->GetSpan(), decrypted_buf);
Artem Strygind8169d72017-10-02 19:19:28 +0300288 decrypt_result &= DecryptFinish(context, decrypted_buf);
289 if (decrypt_result) {
Lei Zhangd8db3042022-09-07 08:46:13 +0000290 stream->TakeData(decrypted_buf.DetachBuffer());
Artem Strygind8169d72017-10-02 19:19:28 +0300291 } else {
292 // Decryption failed, set the stream to empty
Tom Sepez367ed462018-08-23 23:52:53 +0000293 stream->SetData({});
Artem Strygind8169d72017-10-02 19:19:28 +0300294 }
295 }
296 }
297 // Signature dictionaries check.
298 while (!may_be_sign_dictionaries.empty()) {
asweintraub84cf0b22019-06-07 16:36:20 +0000299 auto dict_and_contents = may_be_sign_dictionaries.top();
Artem Strygind8169d72017-10-02 19:19:28 +0300300 may_be_sign_dictionaries.pop();
301 if (!IsSignatureDictionary(dict_and_contents.parent)) {
302 // This is not signature dictionary. Do decrypt its contents.
303 object_to_decrypt = dict_and_contents.contents;
304 break;
305 }
306 }
307 }
Tom Sepeza3097da2019-05-01 16:42:36 +0000308 return true;
Artem Strygind8169d72017-10-02 19:19:28 +0300309}
310
Tom Sepezdebd2d22018-05-16 18:32:43 +0000311size_t CPDF_CryptoHandler::EncryptGetSize(
Tom Sepez6facd152018-05-16 17:07:02 +0000312 pdfium::span<const uint8_t> source) const {
Tom Sepez12d343e2021-05-19 01:50:24 +0000313 return m_Cipher == Cipher::kAES ? source.size() + 32 : source.size();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700314}
Tom Sepez332ef542017-05-05 17:08:07 -0700315
Tom Sepez12d343e2021-05-19 01:50:24 +0000316CPDF_CryptoHandler::CPDF_CryptoHandler(Cipher cipher,
Artem Strygina0819312017-10-03 21:51:18 +0300317 const uint8_t* key,
Lei Zhangb92ff3c2019-12-05 22:25:28 +0000318 size_t keylen)
319 : m_KeyLen(std::min<size_t>(keylen, 32)), m_Cipher(cipher) {
Tom Sepez12d343e2021-05-19 01:50:24 +0000320 DCHECK(cipher != Cipher::kAES || keylen == 16 || keylen == 24 ||
Artem Strygina0819312017-10-03 21:51:18 +0300321 keylen == 32);
Tom Sepez12d343e2021-05-19 01:50:24 +0000322 DCHECK(cipher != Cipher::kAES2 || keylen == 32);
323 DCHECK(cipher != Cipher::kRC4 || (keylen >= 5 && keylen <= 16));
Artem Strygina0819312017-10-03 21:51:18 +0300324
Tom Sepez12d343e2021-05-19 01:50:24 +0000325 if (m_Cipher != Cipher::kNone)
Artem Strygina0819312017-10-03 21:51:18 +0300326 memcpy(m_EncryptKey, key, m_KeyLen);
327
Tom Sepez12d343e2021-05-19 01:50:24 +0000328 if (m_Cipher == Cipher::kAES)
Artem Strygina0819312017-10-03 21:51:18 +0300329 m_pAESContext.reset(FX_Alloc(CRYPT_aes_context, 1));
330}
Tom Sepez332ef542017-05-05 17:08:07 -0700331
Lei Zhangb92ff3c2019-12-05 22:25:28 +0000332CPDF_CryptoHandler::~CPDF_CryptoHandler() = default;
dsinclair0690c352016-08-02 10:48:28 -0700333
334void CPDF_CryptoHandler::PopulateKey(uint32_t objnum,
335 uint32_t gennum,
Tom Sepezfe7dcb02021-04-22 16:53:45 +0000336 uint8_t* key) const {
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400337 memcpy(key, m_EncryptKey, m_KeyLen);
dsinclair0690c352016-08-02 10:48:28 -0700338 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);
343}