blob: 441ca8000deba4bc5dad45400f20796690d0309b [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// Copyright 2014 PDFium Authors. All rights reserved.
2// 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 Strygind8169d72017-10-02 19:19:28 +030011#include <stack>
12#include <utility>
13
dsinclairb1469a22016-09-29 10:00:05 -070014#include "core/fdrm/crypto/fx_crypt.h"
Artem Strygind8169d72017-10-02 19:19:28 +030015#include "core/fpdfapi/edit/cpdf_encryptor.h"
16#include "core/fpdfapi/edit/cpdf_flateencoder.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"
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"
26
27namespace {
28
29constexpr char kContentsKey[] = "Contents";
30constexpr char kTypeKey[] = "Type";
31constexpr char kFTKey[] = "FT";
32constexpr char kSignTypeValue[] = "Sig";
33
34} // namespace
35
36// static
37bool CPDF_CryptoHandler::IsSignatureDictionary(
38 const CPDF_Dictionary* dictionary) {
39 if (!dictionary)
40 return false;
41 const CPDF_Object* type_obj = dictionary->GetDirectObjectFor(kTypeKey);
42 if (!type_obj)
43 type_obj = dictionary->GetDirectObjectFor(kFTKey);
44 return type_obj && type_obj->GetString() == kSignTypeValue;
45}
Lei Zhanga9fa50f2015-11-10 09:45:32 -080046
tsepez12f3e4a2016-11-02 15:17:29 -070047void CPDF_CryptoHandler::CryptBlock(bool bEncrypt,
dsinclair2fa0e132016-04-19 10:32:45 -070048 uint32_t objnum,
49 uint32_t gennum,
50 const uint8_t* src_buf,
51 uint32_t src_size,
52 uint8_t* dest_buf,
53 uint32_t& dest_size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070054 if (m_Cipher == FXCIPHER_NONE) {
Dan Sinclair1c5d0b42017-04-03 15:05:11 -040055 memcpy(dest_buf, src_buf, src_size);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070056 return;
57 }
58 uint8_t realkey[16];
59 int realkeylen = 16;
60 if (m_Cipher != FXCIPHER_AES || m_KeyLen != 32) {
61 uint8_t key1[32];
dsinclair0690c352016-08-02 10:48:28 -070062 PopulateKey(objnum, gennum, key1);
63
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070064 if (m_Cipher == FXCIPHER_AES) {
Dan Sinclair1c5d0b42017-04-03 15:05:11 -040065 memcpy(key1 + m_KeyLen + 5, "sAlT", 4);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070066 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070067 CRYPT_MD5Generate(
68 key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey);
69 realkeylen = m_KeyLen + 5;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070070 if (realkeylen > 16) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070071 realkeylen = 16;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070072 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070073 }
74 if (m_Cipher == FXCIPHER_AES) {
Tom Sepez332ef542017-05-05 17:08:07 -070075 CRYPT_AESSetKey(m_pAESContext.get(), 16,
76 m_KeyLen == 32 ? m_EncryptKey : realkey, m_KeyLen,
77 bEncrypt);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070078 if (bEncrypt) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070079 uint8_t iv[16];
80 for (int i = 0; i < 16; i++) {
81 iv[i] = (uint8_t)rand();
82 }
Tom Sepez332ef542017-05-05 17:08:07 -070083 CRYPT_AESSetIV(m_pAESContext.get(), iv);
Dan Sinclair1c5d0b42017-04-03 15:05:11 -040084 memcpy(dest_buf, iv, 16);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070085 int nblocks = src_size / 16;
Tom Sepez332ef542017-05-05 17:08:07 -070086 CRYPT_AESEncrypt(m_pAESContext.get(), dest_buf + 16, src_buf,
87 nblocks * 16);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070088 uint8_t padding[16];
Dan Sinclair1c5d0b42017-04-03 15:05:11 -040089 memcpy(padding, src_buf + nblocks * 16, src_size % 16);
90 memset(padding + src_size % 16, 16 - src_size % 16, 16 - src_size % 16);
Tom Sepez332ef542017-05-05 17:08:07 -070091 CRYPT_AESEncrypt(m_pAESContext.get(), dest_buf + nblocks * 16 + 16,
92 padding, 16);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070093 dest_size = 32 + nblocks * 16;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070094 } else {
Tom Sepez332ef542017-05-05 17:08:07 -070095 CRYPT_AESSetIV(m_pAESContext.get(), src_buf);
96 CRYPT_AESDecrypt(m_pAESContext.get(), dest_buf, src_buf + 16,
97 src_size - 16);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070098 dest_size = src_size - 16;
99 dest_size -= dest_buf[dest_size - 1];
100 }
101 } else {
102 ASSERT(dest_size == src_size);
103 if (dest_buf != src_buf) {
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400104 memcpy(dest_buf, src_buf, src_size);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700105 }
106 CRYPT_ArcFourCryptBlock(dest_buf, dest_size, realkey, realkeylen);
107 }
108}
Tom Sepezd21cdda2016-02-23 10:11:11 -0800109
110struct AESCryptContext {
tsepez12f3e4a2016-11-02 15:17:29 -0700111 bool m_bIV;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700112 uint8_t m_Block[16];
tsepezb5e8f142016-03-25 15:18:35 -0700113 uint32_t m_BlockOffset;
Tom Sepez332ef542017-05-05 17:08:07 -0700114 CRYPT_aes_context m_Context;
Tom Sepezd21cdda2016-02-23 10:11:11 -0800115};
116
dsinclair2fa0e132016-04-19 10:32:45 -0700117void* CPDF_CryptoHandler::CryptStart(uint32_t objnum,
118 uint32_t gennum,
tsepez12f3e4a2016-11-02 15:17:29 -0700119 bool bEncrypt) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700120 if (m_Cipher == FXCIPHER_NONE) {
121 return this;
122 }
123 if (m_Cipher == FXCIPHER_AES && m_KeyLen == 32) {
124 AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1);
tsepez12f3e4a2016-11-02 15:17:29 -0700125 pContext->m_bIV = true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700126 pContext->m_BlockOffset = 0;
Tom Sepez332ef542017-05-05 17:08:07 -0700127 CRYPT_AESSetKey(&pContext->m_Context, 16, m_EncryptKey, 32, bEncrypt);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700128 if (bEncrypt) {
129 for (int i = 0; i < 16; i++) {
130 pContext->m_Block[i] = (uint8_t)rand();
131 }
Tom Sepez332ef542017-05-05 17:08:07 -0700132 CRYPT_AESSetIV(&pContext->m_Context, pContext->m_Block);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700133 }
134 return pContext;
135 }
136 uint8_t key1[48];
dsinclair0690c352016-08-02 10:48:28 -0700137 PopulateKey(objnum, gennum, key1);
138
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700139 if (m_Cipher == FXCIPHER_AES) {
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400140 memcpy(key1 + m_KeyLen + 5, "sAlT", 4);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700141 }
142 uint8_t realkey[16];
143 CRYPT_MD5Generate(
144 key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey);
145 int realkeylen = m_KeyLen + 5;
146 if (realkeylen > 16) {
147 realkeylen = 16;
148 }
149 if (m_Cipher == FXCIPHER_AES) {
150 AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1);
tsepez12f3e4a2016-11-02 15:17:29 -0700151 pContext->m_bIV = true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700152 pContext->m_BlockOffset = 0;
Tom Sepez332ef542017-05-05 17:08:07 -0700153 CRYPT_AESSetKey(&pContext->m_Context, 16, realkey, 16, bEncrypt);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700154 if (bEncrypt) {
155 for (int i = 0; i < 16; i++) {
156 pContext->m_Block[i] = (uint8_t)rand();
157 }
Tom Sepez332ef542017-05-05 17:08:07 -0700158 CRYPT_AESSetIV(&pContext->m_Context, pContext->m_Block);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700159 }
160 return pContext;
161 }
tsepezd88090f2016-11-21 14:29:12 -0800162 CRYPT_rc4_context* pContext = FX_Alloc(CRYPT_rc4_context, 1);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700163 CRYPT_ArcFourSetup(pContext, realkey, realkeylen);
164 return pContext;
165}
dsinclair0690c352016-08-02 10:48:28 -0700166
tsepez12f3e4a2016-11-02 15:17:29 -0700167bool CPDF_CryptoHandler::CryptStream(void* context,
168 const uint8_t* src_buf,
169 uint32_t src_size,
170 CFX_BinaryBuf& dest_buf,
171 bool bEncrypt) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700172 if (!context) {
tsepez12f3e4a2016-11-02 15:17:29 -0700173 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700174 }
175 if (m_Cipher == FXCIPHER_NONE) {
176 dest_buf.AppendBlock(src_buf, src_size);
tsepez12f3e4a2016-11-02 15:17:29 -0700177 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700178 }
179 if (m_Cipher == FXCIPHER_RC4) {
180 int old_size = dest_buf.GetSize();
181 dest_buf.AppendBlock(src_buf, src_size);
tsepezd88090f2016-11-21 14:29:12 -0800182 CRYPT_ArcFourCrypt(reinterpret_cast<CRYPT_rc4_context*>(context),
183 dest_buf.GetBuffer() + old_size, src_size);
tsepez12f3e4a2016-11-02 15:17:29 -0700184 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700185 }
tsepezd88090f2016-11-21 14:29:12 -0800186 AESCryptContext* pContext = reinterpret_cast<AESCryptContext*>(context);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700187 if (pContext->m_bIV && bEncrypt) {
188 dest_buf.AppendBlock(pContext->m_Block, 16);
tsepez12f3e4a2016-11-02 15:17:29 -0700189 pContext->m_bIV = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700190 }
tsepezb5e8f142016-03-25 15:18:35 -0700191 uint32_t src_off = 0;
192 uint32_t src_left = src_size;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700193 while (1) {
tsepezb5e8f142016-03-25 15:18:35 -0700194 uint32_t copy_size = 16 - pContext->m_BlockOffset;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700195 if (copy_size > src_left) {
196 copy_size = src_left;
197 }
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400198 memcpy(pContext->m_Block + pContext->m_BlockOffset, src_buf + src_off,
199 copy_size);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700200 src_off += copy_size;
201 src_left -= copy_size;
202 pContext->m_BlockOffset += copy_size;
203 if (pContext->m_BlockOffset == 16) {
204 if (!bEncrypt && pContext->m_bIV) {
Tom Sepez332ef542017-05-05 17:08:07 -0700205 CRYPT_AESSetIV(&pContext->m_Context, pContext->m_Block);
tsepez12f3e4a2016-11-02 15:17:29 -0700206 pContext->m_bIV = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700207 pContext->m_BlockOffset = 0;
208 } else if (src_off < src_size) {
209 uint8_t block_buf[16];
210 if (bEncrypt) {
Tom Sepez332ef542017-05-05 17:08:07 -0700211 CRYPT_AESEncrypt(&pContext->m_Context, block_buf, pContext->m_Block,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700212 16);
213 } else {
Tom Sepez332ef542017-05-05 17:08:07 -0700214 CRYPT_AESDecrypt(&pContext->m_Context, block_buf, pContext->m_Block,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700215 16);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700216 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700217 dest_buf.AppendBlock(block_buf, 16);
218 pContext->m_BlockOffset = 0;
219 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700220 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700221 if (!src_left) {
222 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700223 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700224 }
tsepez12f3e4a2016-11-02 15:17:29 -0700225 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700226}
tsepez12f3e4a2016-11-02 15:17:29 -0700227bool CPDF_CryptoHandler::CryptFinish(void* context,
228 CFX_BinaryBuf& dest_buf,
229 bool bEncrypt) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700230 if (!context) {
tsepez12f3e4a2016-11-02 15:17:29 -0700231 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700232 }
233 if (m_Cipher == FXCIPHER_NONE) {
tsepez12f3e4a2016-11-02 15:17:29 -0700234 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700235 }
236 if (m_Cipher == FXCIPHER_RC4) {
237 FX_Free(context);
tsepez12f3e4a2016-11-02 15:17:29 -0700238 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700239 }
240 AESCryptContext* pContext = (AESCryptContext*)context;
241 if (bEncrypt) {
242 uint8_t block_buf[16];
243 if (pContext->m_BlockOffset == 16) {
Tom Sepez332ef542017-05-05 17:08:07 -0700244 CRYPT_AESEncrypt(&pContext->m_Context, block_buf, pContext->m_Block, 16);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700245 dest_buf.AppendBlock(block_buf, 16);
246 pContext->m_BlockOffset = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700247 }
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400248 memset(pContext->m_Block + pContext->m_BlockOffset,
249 (uint8_t)(16 - pContext->m_BlockOffset),
250 16 - pContext->m_BlockOffset);
Tom Sepez332ef542017-05-05 17:08:07 -0700251 CRYPT_AESEncrypt(&pContext->m_Context, block_buf, pContext->m_Block, 16);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700252 dest_buf.AppendBlock(block_buf, 16);
253 } else if (pContext->m_BlockOffset == 16) {
254 uint8_t block_buf[16];
Tom Sepez332ef542017-05-05 17:08:07 -0700255 CRYPT_AESDecrypt(&pContext->m_Context, block_buf, pContext->m_Block, 16);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700256 if (block_buf[15] <= 16) {
257 dest_buf.AppendBlock(block_buf, 16 - block_buf[15]);
258 }
259 }
260 FX_Free(pContext);
tsepez12f3e4a2016-11-02 15:17:29 -0700261 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700262}
dsinclair2fa0e132016-04-19 10:32:45 -0700263
Ryan Harrison275e2602017-09-18 14:23:18 -0400264ByteString CPDF_CryptoHandler::Decrypt(uint32_t objnum,
265 uint32_t gennum,
266 const ByteString& str) {
dsinclair2fa0e132016-04-19 10:32:45 -0700267 CFX_BinaryBuf dest_buf;
268 void* context = DecryptStart(objnum, gennum);
269 DecryptStream(context, str.raw_str(), str.GetLength(), dest_buf);
270 DecryptFinish(context, dest_buf);
Ryan Harrison275e2602017-09-18 14:23:18 -0400271 return ByteString(dest_buf.GetBuffer(), dest_buf.GetSize());
dsinclair2fa0e132016-04-19 10:32:45 -0700272}
273
274void* CPDF_CryptoHandler::DecryptStart(uint32_t objnum, uint32_t gennum) {
tsepez12f3e4a2016-11-02 15:17:29 -0700275 return CryptStart(objnum, gennum, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700276}
dsinclair2fa0e132016-04-19 10:32:45 -0700277uint32_t CPDF_CryptoHandler::DecryptGetSize(uint32_t src_size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700278 return m_Cipher == FXCIPHER_AES ? src_size - 16 : src_size;
279}
Lei Zhangaa23e702016-01-29 18:03:40 -0800280
tsepez12f3e4a2016-11-02 15:17:29 -0700281bool CPDF_CryptoHandler::Init(CPDF_Dictionary* pEncryptDict,
282 CPDF_SecurityHandler* pSecurityHandler) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700283 const uint8_t* key;
Tom Sepez332ef542017-05-05 17:08:07 -0700284 if (!pSecurityHandler->GetCryptInfo(m_Cipher, key, m_KeyLen))
tsepez12f3e4a2016-11-02 15:17:29 -0700285 return false;
Tom Sepez332ef542017-05-05 17:08:07 -0700286
287 if (m_KeyLen > 32 || m_KeyLen < 0)
tsepez12f3e4a2016-11-02 15:17:29 -0700288 return false;
Tom Sepez332ef542017-05-05 17:08:07 -0700289
290 if (m_Cipher != FXCIPHER_NONE)
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400291 memcpy(m_EncryptKey, key, m_KeyLen);
Tom Sepez332ef542017-05-05 17:08:07 -0700292
293 if (m_Cipher == FXCIPHER_AES)
294 m_pAESContext.reset(FX_Alloc(CRYPT_aes_context, 1));
295
tsepez12f3e4a2016-11-02 15:17:29 -0700296 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700297}
Lei Zhangaa23e702016-01-29 18:03:40 -0800298
tsepez12f3e4a2016-11-02 15:17:29 -0700299bool CPDF_CryptoHandler::Init(int cipher, const uint8_t* key, int keylen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700300 if (cipher == FXCIPHER_AES) {
301 switch (keylen) {
302 case 16:
303 case 24:
304 case 32:
305 break;
306 default:
tsepez12f3e4a2016-11-02 15:17:29 -0700307 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700308 }
309 } else if (cipher == FXCIPHER_AES2) {
310 if (keylen != 32) {
tsepez12f3e4a2016-11-02 15:17:29 -0700311 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700312 }
313 } else if (cipher == FXCIPHER_RC4) {
314 if (keylen < 5 || keylen > 16) {
tsepez12f3e4a2016-11-02 15:17:29 -0700315 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700316 }
317 } else {
318 if (keylen > 32) {
319 keylen = 32;
320 }
321 }
322 m_Cipher = cipher;
323 m_KeyLen = keylen;
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400324 memcpy(m_EncryptKey, key, keylen);
Tom Sepez332ef542017-05-05 17:08:07 -0700325 if (m_Cipher == FXCIPHER_AES)
326 m_pAESContext.reset(FX_Alloc(CRYPT_aes_context, 1));
327
tsepez12f3e4a2016-11-02 15:17:29 -0700328 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700329}
Tom Sepez332ef542017-05-05 17:08:07 -0700330
Ryan Harrison5b2092a2017-09-12 15:30:55 -0400331bool CPDF_CryptoHandler::IsCipherAES() const {
332 return m_Cipher == FXCIPHER_AES;
333}
334
Artem Strygind8169d72017-10-02 19:19:28 +0300335std::unique_ptr<CPDF_Object> CPDF_CryptoHandler::DecryptObjectTree(
336 std::unique_ptr<CPDF_Object> object) {
337 if (!object)
338 return nullptr;
339
340 struct MayBeSignature {
341 const CPDF_Dictionary* parent;
342 CPDF_Object* contents;
343 };
344
345 std::stack<MayBeSignature> may_be_sign_dictionaries;
346 const uint32_t obj_num = object->GetObjNum();
347 const uint32_t gen_num = object->GetGenNum();
348
349 CPDF_Object* object_to_decrypt = object.get();
350 while (object_to_decrypt) {
351 CPDF_NonConstObjectWalker walker(object_to_decrypt);
352 object_to_decrypt = nullptr;
353 while (CPDF_Object* child = walker.GetNext()) {
354 const CPDF_Dictionary* parent_dict =
355 walker.GetParent() ? walker.GetParent()->GetDict() : nullptr;
356 if (walker.dictionary_key() == kContentsKey &&
357 (parent_dict->KeyExist(kTypeKey) || parent_dict->KeyExist(kFTKey))) {
358 // This object may be contents of signature dictionary.
359 // But now values of 'Type' and 'FT' of dictionary keys are encrypted,
360 // and we can not check this.
361 // Temporary skip it, to prevent signature corruption.
362 // It will be decrypted on next interations, if this is not contents of
363 // signature dictionary.
364 may_be_sign_dictionaries.push(MayBeSignature({parent_dict, child}));
365 walker.SkipWalkIntoCurrentObject();
366 continue;
367 }
368 // Strings decryption.
369 if (child->IsString()) {
370 // TODO(art-snake): Move decryption into the CPDF_String class.
371 CPDF_String* str = child->AsString();
372 str->SetString(Decrypt(obj_num, gen_num, str->GetString()));
373 }
374 // Stream decryption.
375 if (child->IsStream()) {
376 // TODO(art-snake): Move decryption into the CPDF_Stream class.
377 CPDF_Stream* stream = child->AsStream();
378 auto stream_access = pdfium::MakeRetain<CPDF_StreamAcc>(stream);
379 stream_access->LoadAllData(true);
380
381 if (IsCipherAES() && stream_access->GetSize() < 16) {
382 stream->SetData(nullptr, 0);
383 continue;
384 }
385
386 CFX_BinaryBuf decrypted_buf;
387 decrypted_buf.EstimateSize(DecryptGetSize(stream_access->GetSize()));
388
389 void* context = DecryptStart(obj_num, gen_num);
390 bool decrypt_result =
391 DecryptStream(context, stream_access->GetData(),
392 stream_access->GetSize(), decrypted_buf);
393 decrypt_result &= DecryptFinish(context, decrypted_buf);
394 if (decrypt_result) {
395 const uint32_t decrypted_size = decrypted_buf.GetSize();
396 stream->SetData(decrypted_buf.DetachBuffer(), decrypted_size);
397 } else {
398 // Decryption failed, set the stream to empty
399 stream->SetData(nullptr, 0);
400 }
401 }
402 }
403 // Signature dictionaries check.
404 while (!may_be_sign_dictionaries.empty()) {
405 auto dict_and_contents = std::move(may_be_sign_dictionaries.top());
406 may_be_sign_dictionaries.pop();
407 if (!IsSignatureDictionary(dict_and_contents.parent)) {
408 // This is not signature dictionary. Do decrypt its contents.
409 object_to_decrypt = dict_and_contents.contents;
410 break;
411 }
412 }
413 }
414 return object;
415}
416
tsepez12f3e4a2016-11-02 15:17:29 -0700417bool CPDF_CryptoHandler::DecryptStream(void* context,
418 const uint8_t* src_buf,
419 uint32_t src_size,
420 CFX_BinaryBuf& dest_buf) {
421 return CryptStream(context, src_buf, src_size, dest_buf, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700422}
Tom Sepez332ef542017-05-05 17:08:07 -0700423
tsepez12f3e4a2016-11-02 15:17:29 -0700424bool CPDF_CryptoHandler::DecryptFinish(void* context, CFX_BinaryBuf& dest_buf) {
425 return CryptFinish(context, dest_buf, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700426}
dsinclair2fa0e132016-04-19 10:32:45 -0700427uint32_t CPDF_CryptoHandler::EncryptGetSize(uint32_t objnum,
428 uint32_t version,
429 const uint8_t* src_buf,
430 uint32_t src_size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700431 if (m_Cipher == FXCIPHER_AES) {
432 return src_size + 32;
433 }
434 return src_size;
435}
Tom Sepez332ef542017-05-05 17:08:07 -0700436
tsepez12f3e4a2016-11-02 15:17:29 -0700437bool CPDF_CryptoHandler::EncryptContent(uint32_t objnum,
438 uint32_t gennum,
439 const uint8_t* src_buf,
440 uint32_t src_size,
441 uint8_t* dest_buf,
442 uint32_t& dest_size) {
443 CryptBlock(true, objnum, gennum, src_buf, src_size, dest_buf, dest_size);
444 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700445}
Tom Sepez332ef542017-05-05 17:08:07 -0700446
447CPDF_CryptoHandler::CPDF_CryptoHandler()
448 : m_KeyLen(0), m_Cipher(FXCIPHER_NONE) {}
449
450CPDF_CryptoHandler::~CPDF_CryptoHandler() {}
dsinclair0690c352016-08-02 10:48:28 -0700451
452void CPDF_CryptoHandler::PopulateKey(uint32_t objnum,
453 uint32_t gennum,
454 uint8_t* key) {
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400455 memcpy(key, m_EncryptKey, m_KeyLen);
dsinclair0690c352016-08-02 10:48:28 -0700456 key[m_KeyLen + 0] = (uint8_t)objnum;
457 key[m_KeyLen + 1] = (uint8_t)(objnum >> 8);
458 key[m_KeyLen + 2] = (uint8_t)(objnum >> 16);
459 key[m_KeyLen + 3] = (uint8_t)gennum;
460 key[m_KeyLen + 4] = (uint8_t)(gennum >> 8);
461}