1 // 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. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "core/fpdfapi/parser/cpdf_crypto_handler.h" 8 9 #include <time.h> 10 11 #include "core/fdrm/crypto/fx_crypt.h" 12 #include "core/fpdfapi/parser/cpdf_parser.h" 13 #include "core/fpdfapi/parser/cpdf_security_handler.h" 14 #include "core/fpdfapi/parser/cpdf_simple_parser.h" 15 16 void CPDF_CryptoHandler::CryptBlock(bool bEncrypt, 17 uint32_t objnum, 18 uint32_t gennum, 19 const uint8_t* src_buf, 20 uint32_t src_size, 21 uint8_t* dest_buf, 22 uint32_t& dest_size) { 23 if (m_Cipher == FXCIPHER_NONE) { 24 FXSYS_memcpy(dest_buf, src_buf, src_size); 25 return; 26 } 27 uint8_t realkey[16]; 28 int realkeylen = 16; 29 if (m_Cipher != FXCIPHER_AES || m_KeyLen != 32) { 30 uint8_t key1[32]; 31 PopulateKey(objnum, gennum, key1); 32 33 if (m_Cipher == FXCIPHER_AES) { 34 FXSYS_memcpy(key1 + m_KeyLen + 5, "sAlT", 4); 35 } 36 CRYPT_MD5Generate( 37 key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey); 38 realkeylen = m_KeyLen + 5; 39 if (realkeylen > 16) { 40 realkeylen = 16; 41 } 42 } 43 if (m_Cipher == FXCIPHER_AES) { 44 CRYPT_AESSetKey(m_pAESContext, 16, m_KeyLen == 32 ? m_EncryptKey : realkey, 45 m_KeyLen, bEncrypt); 46 if (bEncrypt) { 47 uint8_t iv[16]; 48 for (int i = 0; i < 16; i++) { 49 iv[i] = (uint8_t)rand(); 50 } 51 CRYPT_AESSetIV(m_pAESContext, iv); 52 FXSYS_memcpy(dest_buf, iv, 16); 53 int nblocks = src_size / 16; 54 CRYPT_AESEncrypt(m_pAESContext, dest_buf + 16, src_buf, nblocks * 16); 55 uint8_t padding[16]; 56 FXSYS_memcpy(padding, src_buf + nblocks * 16, src_size % 16); 57 FXSYS_memset(padding + src_size % 16, 16 - src_size % 16, 58 16 - src_size % 16); 59 CRYPT_AESEncrypt(m_pAESContext, dest_buf + nblocks * 16 + 16, padding, 60 16); 61 dest_size = 32 + nblocks * 16; 62 } else { 63 CRYPT_AESSetIV(m_pAESContext, src_buf); 64 CRYPT_AESDecrypt(m_pAESContext, dest_buf, src_buf + 16, src_size - 16); 65 dest_size = src_size - 16; 66 dest_size -= dest_buf[dest_size - 1]; 67 } 68 } else { 69 ASSERT(dest_size == src_size); 70 if (dest_buf != src_buf) { 71 FXSYS_memcpy(dest_buf, src_buf, src_size); 72 } 73 CRYPT_ArcFourCryptBlock(dest_buf, dest_size, realkey, realkeylen); 74 } 75 } 76 77 struct AESCryptContext { 78 uint8_t m_Context[2048]; 79 bool m_bIV; 80 uint8_t m_Block[16]; 81 uint32_t m_BlockOffset; 82 }; 83 84 void* CPDF_CryptoHandler::CryptStart(uint32_t objnum, 85 uint32_t gennum, 86 bool bEncrypt) { 87 if (m_Cipher == FXCIPHER_NONE) { 88 return this; 89 } 90 if (m_Cipher == FXCIPHER_AES && m_KeyLen == 32) { 91 AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1); 92 pContext->m_bIV = true; 93 pContext->m_BlockOffset = 0; 94 CRYPT_AESSetKey(pContext->m_Context, 16, m_EncryptKey, 32, bEncrypt); 95 if (bEncrypt) { 96 for (int i = 0; i < 16; i++) { 97 pContext->m_Block[i] = (uint8_t)rand(); 98 } 99 CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); 100 } 101 return pContext; 102 } 103 uint8_t key1[48]; 104 PopulateKey(objnum, gennum, key1); 105 106 if (m_Cipher == FXCIPHER_AES) { 107 FXSYS_memcpy(key1 + m_KeyLen + 5, "sAlT", 4); 108 } 109 uint8_t realkey[16]; 110 CRYPT_MD5Generate( 111 key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey); 112 int realkeylen = m_KeyLen + 5; 113 if (realkeylen > 16) { 114 realkeylen = 16; 115 } 116 if (m_Cipher == FXCIPHER_AES) { 117 AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1); 118 pContext->m_bIV = true; 119 pContext->m_BlockOffset = 0; 120 CRYPT_AESSetKey(pContext->m_Context, 16, realkey, 16, bEncrypt); 121 if (bEncrypt) { 122 for (int i = 0; i < 16; i++) { 123 pContext->m_Block[i] = (uint8_t)rand(); 124 } 125 CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); 126 } 127 return pContext; 128 } 129 CRYPT_rc4_context* pContext = FX_Alloc(CRYPT_rc4_context, 1); 130 CRYPT_ArcFourSetup(pContext, realkey, realkeylen); 131 return pContext; 132 } 133 134 bool CPDF_CryptoHandler::CryptStream(void* context, 135 const uint8_t* src_buf, 136 uint32_t src_size, 137 CFX_BinaryBuf& dest_buf, 138 bool bEncrypt) { 139 if (!context) { 140 return false; 141 } 142 if (m_Cipher == FXCIPHER_NONE) { 143 dest_buf.AppendBlock(src_buf, src_size); 144 return true; 145 } 146 if (m_Cipher == FXCIPHER_RC4) { 147 int old_size = dest_buf.GetSize(); 148 dest_buf.AppendBlock(src_buf, src_size); 149 CRYPT_ArcFourCrypt(reinterpret_cast<CRYPT_rc4_context*>(context), 150 dest_buf.GetBuffer() + old_size, src_size); 151 return true; 152 } 153 AESCryptContext* pContext = reinterpret_cast<AESCryptContext*>(context); 154 if (pContext->m_bIV && bEncrypt) { 155 dest_buf.AppendBlock(pContext->m_Block, 16); 156 pContext->m_bIV = false; 157 } 158 uint32_t src_off = 0; 159 uint32_t src_left = src_size; 160 while (1) { 161 uint32_t copy_size = 16 - pContext->m_BlockOffset; 162 if (copy_size > src_left) { 163 copy_size = src_left; 164 } 165 FXSYS_memcpy(pContext->m_Block + pContext->m_BlockOffset, src_buf + src_off, 166 copy_size); 167 src_off += copy_size; 168 src_left -= copy_size; 169 pContext->m_BlockOffset += copy_size; 170 if (pContext->m_BlockOffset == 16) { 171 if (!bEncrypt && pContext->m_bIV) { 172 CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); 173 pContext->m_bIV = false; 174 pContext->m_BlockOffset = 0; 175 } else if (src_off < src_size) { 176 uint8_t block_buf[16]; 177 if (bEncrypt) { 178 CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 179 16); 180 } else { 181 CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, 182 16); 183 } 184 dest_buf.AppendBlock(block_buf, 16); 185 pContext->m_BlockOffset = 0; 186 } 187 } 188 if (!src_left) { 189 break; 190 } 191 } 192 return true; 193 } 194 bool CPDF_CryptoHandler::CryptFinish(void* context, 195 CFX_BinaryBuf& dest_buf, 196 bool bEncrypt) { 197 if (!context) { 198 return false; 199 } 200 if (m_Cipher == FXCIPHER_NONE) { 201 return true; 202 } 203 if (m_Cipher == FXCIPHER_RC4) { 204 FX_Free(context); 205 return true; 206 } 207 AESCryptContext* pContext = (AESCryptContext*)context; 208 if (bEncrypt) { 209 uint8_t block_buf[16]; 210 if (pContext->m_BlockOffset == 16) { 211 CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); 212 dest_buf.AppendBlock(block_buf, 16); 213 pContext->m_BlockOffset = 0; 214 } 215 FXSYS_memset(pContext->m_Block + pContext->m_BlockOffset, 216 (uint8_t)(16 - pContext->m_BlockOffset), 217 16 - pContext->m_BlockOffset); 218 CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); 219 dest_buf.AppendBlock(block_buf, 16); 220 } else if (pContext->m_BlockOffset == 16) { 221 uint8_t block_buf[16]; 222 CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); 223 if (block_buf[15] <= 16) { 224 dest_buf.AppendBlock(block_buf, 16 - block_buf[15]); 225 } 226 } 227 FX_Free(pContext); 228 return true; 229 } 230 231 void CPDF_CryptoHandler::Decrypt(uint32_t objnum, 232 uint32_t gennum, 233 CFX_ByteString& str) { 234 CFX_BinaryBuf dest_buf; 235 void* context = DecryptStart(objnum, gennum); 236 DecryptStream(context, str.raw_str(), str.GetLength(), dest_buf); 237 DecryptFinish(context, dest_buf); 238 str = CFX_ByteString(dest_buf.GetBuffer(), dest_buf.GetSize()); 239 } 240 241 void* CPDF_CryptoHandler::DecryptStart(uint32_t objnum, uint32_t gennum) { 242 return CryptStart(objnum, gennum, false); 243 } 244 uint32_t CPDF_CryptoHandler::DecryptGetSize(uint32_t src_size) { 245 return m_Cipher == FXCIPHER_AES ? src_size - 16 : src_size; 246 } 247 248 bool CPDF_CryptoHandler::Init(CPDF_Dictionary* pEncryptDict, 249 CPDF_SecurityHandler* pSecurityHandler) { 250 const uint8_t* key; 251 if (!pSecurityHandler->GetCryptInfo(m_Cipher, key, m_KeyLen)) { 252 return false; 253 } 254 if (m_KeyLen > 32 || m_KeyLen < 0) { 255 return false; 256 } 257 if (m_Cipher != FXCIPHER_NONE) { 258 FXSYS_memcpy(m_EncryptKey, key, m_KeyLen); 259 } 260 if (m_Cipher == FXCIPHER_AES) { 261 m_pAESContext = FX_Alloc(uint8_t, 2048); 262 } 263 return true; 264 } 265 266 bool CPDF_CryptoHandler::Init(int cipher, const uint8_t* key, int keylen) { 267 if (cipher == FXCIPHER_AES) { 268 switch (keylen) { 269 case 16: 270 case 24: 271 case 32: 272 break; 273 default: 274 return false; 275 } 276 } else if (cipher == FXCIPHER_AES2) { 277 if (keylen != 32) { 278 return false; 279 } 280 } else if (cipher == FXCIPHER_RC4) { 281 if (keylen < 5 || keylen > 16) { 282 return false; 283 } 284 } else { 285 if (keylen > 32) { 286 keylen = 32; 287 } 288 } 289 m_Cipher = cipher; 290 m_KeyLen = keylen; 291 FXSYS_memcpy(m_EncryptKey, key, keylen); 292 if (m_Cipher == FXCIPHER_AES) { 293 m_pAESContext = FX_Alloc(uint8_t, 2048); 294 } 295 return true; 296 } 297 bool CPDF_CryptoHandler::DecryptStream(void* context, 298 const uint8_t* src_buf, 299 uint32_t src_size, 300 CFX_BinaryBuf& dest_buf) { 301 return CryptStream(context, src_buf, src_size, dest_buf, false); 302 } 303 bool CPDF_CryptoHandler::DecryptFinish(void* context, CFX_BinaryBuf& dest_buf) { 304 return CryptFinish(context, dest_buf, false); 305 } 306 uint32_t CPDF_CryptoHandler::EncryptGetSize(uint32_t objnum, 307 uint32_t version, 308 const uint8_t* src_buf, 309 uint32_t src_size) { 310 if (m_Cipher == FXCIPHER_AES) { 311 return src_size + 32; 312 } 313 return src_size; 314 } 315 bool CPDF_CryptoHandler::EncryptContent(uint32_t objnum, 316 uint32_t gennum, 317 const uint8_t* src_buf, 318 uint32_t src_size, 319 uint8_t* dest_buf, 320 uint32_t& dest_size) { 321 CryptBlock(true, objnum, gennum, src_buf, src_size, dest_buf, dest_size); 322 return true; 323 } 324 CPDF_CryptoHandler::CPDF_CryptoHandler() { 325 m_pAESContext = nullptr; 326 m_Cipher = FXCIPHER_NONE; 327 m_KeyLen = 0; 328 } 329 CPDF_CryptoHandler::~CPDF_CryptoHandler() { 330 FX_Free(m_pAESContext); 331 } 332 333 void CPDF_CryptoHandler::PopulateKey(uint32_t objnum, 334 uint32_t gennum, 335 uint8_t* key) { 336 FXSYS_memcpy(key, m_EncryptKey, m_KeyLen); 337 key[m_KeyLen + 0] = (uint8_t)objnum; 338 key[m_KeyLen + 1] = (uint8_t)(objnum >> 8); 339 key[m_KeyLen + 2] = (uint8_t)(objnum >> 16); 340 key[m_KeyLen + 3] = (uint8_t)gennum; 341 key[m_KeyLen + 4] = (uint8_t)(gennum >> 8); 342 } 343