Home | History | Annotate | Download | only in parser
      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