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_security_handler.h"
      8 
      9 #include <time.h>
     10 
     11 #include <algorithm>
     12 #include <utility>
     13 #include <vector>
     14 
     15 #include "core/fdrm/crypto/fx_crypt.h"
     16 #include "core/fpdfapi/parser/cpdf_array.h"
     17 #include "core/fpdfapi/parser/cpdf_crypto_handler.h"
     18 #include "core/fpdfapi/parser/cpdf_dictionary.h"
     19 #include "core/fpdfapi/parser/cpdf_object.h"
     20 #include "core/fpdfapi/parser/cpdf_parser.h"
     21 #include "core/fpdfapi/parser/cpdf_string.h"
     22 
     23 namespace {
     24 
     25 const uint8_t defpasscode[32] = {
     26     0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e,
     27     0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68,
     28     0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a};
     29 
     30 void CalcEncryptKey(CPDF_Dictionary* pEncrypt,
     31                     const uint8_t* password,
     32                     uint32_t pass_size,
     33                     uint8_t* key,
     34                     int keylen,
     35                     bool bIgnoreMeta,
     36                     CPDF_Array* pIdArray) {
     37   int revision = pEncrypt->GetIntegerFor("R");
     38   uint8_t passcode[32];
     39   for (uint32_t i = 0; i < 32; i++) {
     40     passcode[i] = i < pass_size ? password[i] : defpasscode[i - pass_size];
     41   }
     42   CRYPT_md5_context md5;
     43   CRYPT_MD5Start(&md5);
     44   CRYPT_MD5Update(&md5, passcode, 32);
     45   CFX_ByteString okey = pEncrypt->GetStringFor("O");
     46   CRYPT_MD5Update(&md5, (uint8_t*)okey.c_str(), okey.GetLength());
     47   uint32_t perm = pEncrypt->GetIntegerFor("P");
     48   CRYPT_MD5Update(&md5, (uint8_t*)&perm, 4);
     49   if (pIdArray) {
     50     CFX_ByteString id = pIdArray->GetStringAt(0);
     51     CRYPT_MD5Update(&md5, (uint8_t*)id.c_str(), id.GetLength());
     52   }
     53   if (!bIgnoreMeta && revision >= 3 &&
     54       !pEncrypt->GetIntegerFor("EncryptMetadata", 1)) {
     55     uint32_t tag = (uint32_t)-1;
     56     CRYPT_MD5Update(&md5, (uint8_t*)&tag, 4);
     57   }
     58   uint8_t digest[16];
     59   CRYPT_MD5Finish(&md5, digest);
     60   uint32_t copy_len = keylen;
     61   if (copy_len > sizeof(digest)) {
     62     copy_len = sizeof(digest);
     63   }
     64   if (revision >= 3) {
     65     for (int i = 0; i < 50; i++) {
     66       CRYPT_MD5Generate(digest, copy_len, digest);
     67     }
     68   }
     69   FXSYS_memset(key, 0, keylen);
     70   FXSYS_memcpy(key, digest, copy_len);
     71 }
     72 
     73 }  // namespace
     74 
     75 CPDF_SecurityHandler::CPDF_SecurityHandler()
     76     : m_Version(0),
     77       m_Revision(0),
     78       m_pParser(nullptr),
     79       m_pEncryptDict(nullptr),
     80       m_Permissions(0),
     81       m_Cipher(FXCIPHER_NONE),
     82       m_KeyLen(0),
     83       m_bOwnerUnlocked(false) {}
     84 
     85 CPDF_SecurityHandler::~CPDF_SecurityHandler() {}
     86 
     87 CPDF_CryptoHandler* CPDF_SecurityHandler::CreateCryptoHandler() {
     88   return new CPDF_CryptoHandler;
     89 }
     90 
     91 bool CPDF_SecurityHandler::OnInit(CPDF_Parser* pParser,
     92                                   CPDF_Dictionary* pEncryptDict) {
     93   m_pParser = pParser;
     94   if (!LoadDict(pEncryptDict)) {
     95     return false;
     96   }
     97   if (m_Cipher == FXCIPHER_NONE) {
     98     return true;
     99   }
    100   return CheckSecurity(m_KeyLen);
    101 }
    102 
    103 bool CPDF_SecurityHandler::CheckSecurity(int32_t key_len) {
    104   CFX_ByteString password = m_pParser->GetPassword();
    105   if (!password.IsEmpty() &&
    106       CheckPassword(password.raw_str(), password.GetLength(), true,
    107                     m_EncryptKey, key_len)) {
    108     m_bOwnerUnlocked = true;
    109     return true;
    110   }
    111   return CheckPassword(password.raw_str(), password.GetLength(), false,
    112                        m_EncryptKey, key_len);
    113 }
    114 
    115 uint32_t CPDF_SecurityHandler::GetPermissions() {
    116   return m_bOwnerUnlocked ? 0xFFFFFFFF : m_Permissions;
    117 }
    118 
    119 static bool LoadCryptInfo(CPDF_Dictionary* pEncryptDict,
    120                           const CFX_ByteString& name,
    121                           int& cipher,
    122                           int& keylen) {
    123   int Version = pEncryptDict->GetIntegerFor("V");
    124   cipher = FXCIPHER_RC4;
    125   keylen = 0;
    126   if (Version >= 4) {
    127     CPDF_Dictionary* pCryptFilters = pEncryptDict->GetDictFor("CF");
    128     if (!pCryptFilters) {
    129       return false;
    130     }
    131     if (name == "Identity") {
    132       cipher = FXCIPHER_NONE;
    133     } else {
    134       CPDF_Dictionary* pDefFilter = pCryptFilters->GetDictFor(name);
    135       if (!pDefFilter) {
    136         return false;
    137       }
    138       int nKeyBits = 0;
    139       if (Version == 4) {
    140         nKeyBits = pDefFilter->GetIntegerFor("Length", 0);
    141         if (nKeyBits == 0) {
    142           nKeyBits = pEncryptDict->GetIntegerFor("Length", 128);
    143         }
    144       } else {
    145         nKeyBits = pEncryptDict->GetIntegerFor("Length", 256);
    146       }
    147       if (nKeyBits < 40) {
    148         nKeyBits *= 8;
    149       }
    150       keylen = nKeyBits / 8;
    151       CFX_ByteString cipher_name = pDefFilter->GetStringFor("CFM");
    152       if (cipher_name == "AESV2" || cipher_name == "AESV3") {
    153         cipher = FXCIPHER_AES;
    154       }
    155     }
    156   } else {
    157     keylen = Version > 1 ? pEncryptDict->GetIntegerFor("Length", 40) / 8 : 5;
    158   }
    159   if (keylen > 32 || keylen < 0) {
    160     return false;
    161   }
    162   return true;
    163 }
    164 
    165 bool CPDF_SecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict) {
    166   m_pEncryptDict = pEncryptDict;
    167   m_Version = pEncryptDict->GetIntegerFor("V");
    168   m_Revision = pEncryptDict->GetIntegerFor("R");
    169   m_Permissions = pEncryptDict->GetIntegerFor("P", -1);
    170   if (m_Version < 4)
    171     return LoadCryptInfo(pEncryptDict, CFX_ByteString(), m_Cipher, m_KeyLen);
    172 
    173   CFX_ByteString stmf_name = pEncryptDict->GetStringFor("StmF");
    174   CFX_ByteString strf_name = pEncryptDict->GetStringFor("StrF");
    175   if (stmf_name != strf_name)
    176     return false;
    177 
    178   return LoadCryptInfo(pEncryptDict, strf_name, m_Cipher, m_KeyLen);
    179 }
    180 
    181 bool CPDF_SecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict,
    182                                     uint32_t type,
    183                                     int& cipher,
    184                                     int& key_len) {
    185   m_pEncryptDict = pEncryptDict;
    186   m_Version = pEncryptDict->GetIntegerFor("V");
    187   m_Revision = pEncryptDict->GetIntegerFor("R");
    188   m_Permissions = pEncryptDict->GetIntegerFor("P", -1);
    189 
    190   CFX_ByteString strf_name;
    191   CFX_ByteString stmf_name;
    192   if (m_Version >= 4) {
    193     stmf_name = pEncryptDict->GetStringFor("StmF");
    194     strf_name = pEncryptDict->GetStringFor("StrF");
    195     if (stmf_name != strf_name)
    196       return false;
    197   }
    198   if (!LoadCryptInfo(pEncryptDict, strf_name, cipher, key_len))
    199     return false;
    200 
    201   m_Cipher = cipher;
    202   m_KeyLen = key_len;
    203   return true;
    204 }
    205 
    206 bool CPDF_SecurityHandler::GetCryptInfo(int& cipher,
    207                                         const uint8_t*& buffer,
    208                                         int& keylen) {
    209   cipher = m_Cipher;
    210   buffer = m_EncryptKey;
    211   keylen = m_KeyLen;
    212   return true;
    213 }
    214 #define FX_GET_32WORD(n, b, i)                                        \
    215   {                                                                   \
    216     (n) = (uint32_t)(                                                 \
    217         ((uint64_t)(b)[(i)] << 24) | ((uint64_t)(b)[(i) + 1] << 16) | \
    218         ((uint64_t)(b)[(i) + 2] << 8) | ((uint64_t)(b)[(i) + 3]));    \
    219   }
    220 int BigOrder64BitsMod3(uint8_t* data) {
    221   uint64_t ret = 0;
    222   for (int i = 0; i < 4; ++i) {
    223     uint32_t value;
    224     FX_GET_32WORD(value, data, 4 * i);
    225     ret <<= 32;
    226     ret |= value;
    227     ret %= 3;
    228   }
    229   return (int)ret;
    230 }
    231 
    232 void Revision6_Hash(const uint8_t* password,
    233                     uint32_t size,
    234                     const uint8_t* salt,
    235                     const uint8_t* vector,
    236                     uint8_t* hash) {
    237   CRYPT_sha256_context sha;
    238   CRYPT_SHA256Start(&sha);
    239   CRYPT_SHA256Update(&sha, password, size);
    240   CRYPT_SHA256Update(&sha, salt, 8);
    241   if (vector)
    242     CRYPT_SHA256Update(&sha, vector, 48);
    243 
    244   uint8_t digest[32];
    245   CRYPT_SHA256Finish(&sha, digest);
    246 
    247   CFX_ByteTextBuf buf;
    248   uint8_t* input = digest;
    249   uint8_t* key = input;
    250   uint8_t* iv = input + 16;
    251   uint8_t* E = buf.GetBuffer();
    252   int iBufLen = buf.GetLength();
    253   CFX_ByteTextBuf interDigest;
    254   int i = 0;
    255   int iBlockSize = 32;
    256   uint8_t* aes = FX_Alloc(uint8_t, 2048);
    257   while (i < 64 || i < E[iBufLen - 1] + 32) {
    258     int iRoundSize = size + iBlockSize;
    259     if (vector) {
    260       iRoundSize += 48;
    261     }
    262     iBufLen = iRoundSize * 64;
    263     buf.EstimateSize(iBufLen);
    264     E = buf.GetBuffer();
    265     CFX_ByteTextBuf content;
    266     for (int j = 0; j < 64; ++j) {
    267       content.AppendBlock(password, size);
    268       content.AppendBlock(input, iBlockSize);
    269       if (vector) {
    270         content.AppendBlock(vector, 48);
    271       }
    272     }
    273     CRYPT_AESSetKey(aes, 16, key, 16, true);
    274     CRYPT_AESSetIV(aes, iv);
    275     CRYPT_AESEncrypt(aes, E, content.GetBuffer(), iBufLen);
    276     int iHash = 0;
    277     switch (BigOrder64BitsMod3(E)) {
    278       case 0:
    279         iHash = 0;
    280         iBlockSize = 32;
    281         break;
    282       case 1:
    283         iHash = 1;
    284         iBlockSize = 48;
    285         break;
    286       default:
    287         iHash = 2;
    288         iBlockSize = 64;
    289         break;
    290     }
    291     interDigest.EstimateSize(iBlockSize);
    292     input = interDigest.GetBuffer();
    293     if (iHash == 0) {
    294       CRYPT_SHA256Generate(E, iBufLen, input);
    295     } else if (iHash == 1) {
    296       CRYPT_SHA384Generate(E, iBufLen, input);
    297     } else if (iHash == 2) {
    298       CRYPT_SHA512Generate(E, iBufLen, input);
    299     }
    300     key = input;
    301     iv = input + 16;
    302     ++i;
    303   }
    304   FX_Free(aes);
    305   if (hash) {
    306     FXSYS_memcpy(hash, input, 32);
    307   }
    308 }
    309 
    310 bool CPDF_SecurityHandler::AES256_CheckPassword(const uint8_t* password,
    311                                                 uint32_t size,
    312                                                 bool bOwner,
    313                                                 uint8_t* key) {
    314   if (!m_pEncryptDict)
    315     return false;
    316 
    317   CFX_ByteString okey = m_pEncryptDict->GetStringFor("O");
    318   if (okey.GetLength() < 48)
    319     return false;
    320 
    321   CFX_ByteString ukey = m_pEncryptDict->GetStringFor("U");
    322   if (ukey.GetLength() < 48)
    323     return false;
    324 
    325   const uint8_t* pkey = bOwner ? okey.raw_str() : ukey.raw_str();
    326   CRYPT_sha256_context sha;
    327   uint8_t digest[32];
    328   if (m_Revision >= 6) {
    329     Revision6_Hash(password, size, (const uint8_t*)pkey + 32,
    330                    bOwner ? ukey.raw_str() : nullptr, digest);
    331   } else {
    332     CRYPT_SHA256Start(&sha);
    333     CRYPT_SHA256Update(&sha, password, size);
    334     CRYPT_SHA256Update(&sha, pkey + 32, 8);
    335     if (bOwner)
    336       CRYPT_SHA256Update(&sha, ukey.raw_str(), 48);
    337 
    338     CRYPT_SHA256Finish(&sha, digest);
    339   }
    340   if (FXSYS_memcmp(digest, pkey, 32) != 0)
    341     return false;
    342 
    343   if (!key)
    344     return true;
    345 
    346   if (m_Revision >= 6) {
    347     Revision6_Hash(password, size, (const uint8_t*)pkey + 40,
    348                    bOwner ? ukey.raw_str() : nullptr, digest);
    349   } else {
    350     CRYPT_SHA256Start(&sha);
    351     CRYPT_SHA256Update(&sha, password, size);
    352     CRYPT_SHA256Update(&sha, pkey + 40, 8);
    353     if (bOwner)
    354       CRYPT_SHA256Update(&sha, ukey.raw_str(), 48);
    355 
    356     CRYPT_SHA256Finish(&sha, digest);
    357   }
    358   CFX_ByteString ekey = m_pEncryptDict
    359                             ? m_pEncryptDict->GetStringFor(bOwner ? "OE" : "UE")
    360                             : CFX_ByteString();
    361   if (ekey.GetLength() < 32)
    362     return false;
    363 
    364   std::vector<uint8_t> aes(2048);
    365   CRYPT_AESSetKey(aes.data(), 16, digest, 32, false);
    366   uint8_t iv[16];
    367   FXSYS_memset(iv, 0, 16);
    368   CRYPT_AESSetIV(aes.data(), iv);
    369   CRYPT_AESDecrypt(aes.data(), key, ekey.raw_str(), 32);
    370   CRYPT_AESSetKey(aes.data(), 16, key, 32, false);
    371   CRYPT_AESSetIV(aes.data(), iv);
    372   CFX_ByteString perms = m_pEncryptDict->GetStringFor("Perms");
    373   if (perms.IsEmpty())
    374     return false;
    375 
    376   uint8_t perms_buf[16];
    377   FXSYS_memset(perms_buf, 0, sizeof(perms_buf));
    378   size_t copy_len =
    379       std::min(sizeof(perms_buf), static_cast<size_t>(perms.GetLength()));
    380   FXSYS_memcpy(perms_buf, perms.raw_str(), copy_len);
    381   uint8_t buf[16];
    382   CRYPT_AESDecrypt(aes.data(), buf, perms_buf, 16);
    383   if (buf[9] != 'a' || buf[10] != 'd' || buf[11] != 'b')
    384     return false;
    385 
    386   if (FXDWORD_GET_LSBFIRST(buf) != m_Permissions)
    387     return false;
    388 
    389   // Relax this check as there appear to be some non-conforming documents
    390   // in the wild. The value in the buffer is the truth; if it requires us
    391   // to encrypt metadata, but the dictionary says otherwise, then we may
    392   // have a tampered doc.  Otherwise, give it a pass.
    393   return buf[8] == 'F' || IsMetadataEncrypted();
    394 }
    395 
    396 bool CPDF_SecurityHandler::CheckPassword(const uint8_t* password,
    397                                          uint32_t size,
    398                                          bool bOwner,
    399                                          uint8_t* key,
    400                                          int32_t key_len) {
    401   if (m_Revision >= 5)
    402     return AES256_CheckPassword(password, size, bOwner, key);
    403 
    404   uint8_t keybuf[32];
    405   if (!key)
    406     key = keybuf;
    407 
    408   if (bOwner)
    409     return CheckOwnerPassword(password, size, key, key_len);
    410 
    411   return CheckUserPassword(password, size, false, key, key_len) ||
    412          CheckUserPassword(password, size, true, key, key_len);
    413 }
    414 bool CPDF_SecurityHandler::CheckUserPassword(const uint8_t* password,
    415                                              uint32_t pass_size,
    416                                              bool bIgnoreEncryptMeta,
    417                                              uint8_t* key,
    418                                              int32_t key_len) {
    419   CalcEncryptKey(m_pEncryptDict, password, pass_size, key, key_len,
    420                  bIgnoreEncryptMeta, m_pParser->GetIDArray());
    421   CFX_ByteString ukey =
    422       m_pEncryptDict ? m_pEncryptDict->GetStringFor("U") : CFX_ByteString();
    423   if (ukey.GetLength() < 16) {
    424     return false;
    425   }
    426   uint8_t ukeybuf[32];
    427   if (m_Revision == 2) {
    428     FXSYS_memcpy(ukeybuf, defpasscode, 32);
    429     CRYPT_ArcFourCryptBlock(ukeybuf, 32, key, key_len);
    430   } else {
    431     uint8_t test[32], tmpkey[32];
    432     uint32_t copy_len = sizeof(test);
    433     if (copy_len > (uint32_t)ukey.GetLength()) {
    434       copy_len = ukey.GetLength();
    435     }
    436     FXSYS_memset(test, 0, sizeof(test));
    437     FXSYS_memset(tmpkey, 0, sizeof(tmpkey));
    438     FXSYS_memcpy(test, ukey.c_str(), copy_len);
    439     for (int32_t i = 19; i >= 0; i--) {
    440       for (int j = 0; j < key_len; j++)
    441         tmpkey[j] = key[j] ^ static_cast<uint8_t>(i);
    442       CRYPT_ArcFourCryptBlock(test, 32, tmpkey, key_len);
    443     }
    444     CRYPT_md5_context md5;
    445     CRYPT_MD5Start(&md5);
    446     CRYPT_MD5Update(&md5, defpasscode, 32);
    447     CPDF_Array* pIdArray = m_pParser->GetIDArray();
    448     if (pIdArray) {
    449       CFX_ByteString id = pIdArray->GetStringAt(0);
    450       CRYPT_MD5Update(&md5, (uint8_t*)id.c_str(), id.GetLength());
    451     }
    452     CRYPT_MD5Finish(&md5, ukeybuf);
    453     return FXSYS_memcmp(test, ukeybuf, 16) == 0;
    454   }
    455   if (FXSYS_memcmp((void*)ukey.c_str(), ukeybuf, 16) == 0) {
    456     return true;
    457   }
    458   return false;
    459 }
    460 CFX_ByteString CPDF_SecurityHandler::GetUserPassword(const uint8_t* owner_pass,
    461                                                      uint32_t pass_size,
    462                                                      int32_t key_len) {
    463   CFX_ByteString okey = m_pEncryptDict->GetStringFor("O");
    464   uint8_t passcode[32];
    465   for (uint32_t i = 0; i < 32; i++) {
    466     passcode[i] = i < pass_size ? owner_pass[i] : defpasscode[i - pass_size];
    467   }
    468   uint8_t digest[16];
    469   CRYPT_MD5Generate(passcode, 32, digest);
    470   if (m_Revision >= 3) {
    471     for (uint32_t i = 0; i < 50; i++) {
    472       CRYPT_MD5Generate(digest, 16, digest);
    473     }
    474   }
    475   uint8_t enckey[32];
    476   FXSYS_memset(enckey, 0, sizeof(enckey));
    477   uint32_t copy_len = key_len;
    478   if (copy_len > sizeof(digest)) {
    479     copy_len = sizeof(digest);
    480   }
    481   FXSYS_memcpy(enckey, digest, copy_len);
    482   int okeylen = okey.GetLength();
    483   if (okeylen > 32) {
    484     okeylen = 32;
    485   }
    486   uint8_t okeybuf[64];
    487   FXSYS_memset(okeybuf, 0, sizeof(okeybuf));
    488   FXSYS_memcpy(okeybuf, okey.c_str(), okeylen);
    489   if (m_Revision == 2) {
    490     CRYPT_ArcFourCryptBlock(okeybuf, okeylen, enckey, key_len);
    491   } else {
    492     for (int32_t i = 19; i >= 0; i--) {
    493       uint8_t tempkey[32];
    494       FXSYS_memset(tempkey, 0, sizeof(tempkey));
    495       for (int j = 0; j < m_KeyLen; j++)
    496         tempkey[j] = enckey[j] ^ static_cast<uint8_t>(i);
    497       CRYPT_ArcFourCryptBlock(okeybuf, okeylen, tempkey, key_len);
    498     }
    499   }
    500   int len = 32;
    501   while (len && defpasscode[len - 1] == okeybuf[len - 1]) {
    502     len--;
    503   }
    504   return CFX_ByteString(okeybuf, len);
    505 }
    506 bool CPDF_SecurityHandler::CheckOwnerPassword(const uint8_t* password,
    507                                               uint32_t pass_size,
    508                                               uint8_t* key,
    509                                               int32_t key_len) {
    510   CFX_ByteString user_pass = GetUserPassword(password, pass_size, key_len);
    511   if (CheckUserPassword(user_pass.raw_str(), user_pass.GetLength(), false, key,
    512                         key_len)) {
    513     return true;
    514   }
    515   return CheckUserPassword(user_pass.raw_str(), user_pass.GetLength(), true,
    516                            key, key_len);
    517 }
    518 
    519 bool CPDF_SecurityHandler::IsMetadataEncrypted() const {
    520   return m_pEncryptDict->GetBooleanFor("EncryptMetadata", true);
    521 }
    522 
    523 void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict,
    524                                     CPDF_Array* pIdArray,
    525                                     const uint8_t* user_pass,
    526                                     uint32_t user_size,
    527                                     const uint8_t* owner_pass,
    528                                     uint32_t owner_size,
    529                                     bool bDefault,
    530                                     uint32_t type) {
    531   int cipher = 0, key_len = 0;
    532   if (!LoadDict(pEncryptDict, type, cipher, key_len)) {
    533     return;
    534   }
    535   if (bDefault && (!owner_pass || owner_size == 0)) {
    536     owner_pass = user_pass;
    537     owner_size = user_size;
    538   }
    539   if (m_Revision >= 5) {
    540     int t = (int)time(nullptr);
    541     CRYPT_sha256_context sha;
    542     CRYPT_SHA256Start(&sha);
    543     CRYPT_SHA256Update(&sha, (uint8_t*)&t, sizeof t);
    544     CRYPT_SHA256Update(&sha, m_EncryptKey, 32);
    545     CRYPT_SHA256Update(&sha, (uint8_t*)"there", 5);
    546     CRYPT_SHA256Finish(&sha, m_EncryptKey);
    547     AES256_SetPassword(pEncryptDict, user_pass, user_size, false, m_EncryptKey);
    548     if (bDefault) {
    549       AES256_SetPassword(pEncryptDict, owner_pass, owner_size, true,
    550                          m_EncryptKey);
    551       AES256_SetPerms(pEncryptDict, m_Permissions,
    552                       pEncryptDict->GetBooleanFor("EncryptMetadata", true),
    553                       m_EncryptKey);
    554     }
    555     return;
    556   }
    557   if (bDefault) {
    558     uint8_t passcode[32];
    559     for (uint32_t i = 0; i < 32; i++) {
    560       passcode[i] =
    561           i < owner_size ? owner_pass[i] : defpasscode[i - owner_size];
    562     }
    563     uint8_t digest[16];
    564     CRYPT_MD5Generate(passcode, 32, digest);
    565     if (m_Revision >= 3) {
    566       for (uint32_t i = 0; i < 50; i++)
    567         CRYPT_MD5Generate(digest, 16, digest);
    568     }
    569     uint8_t enckey[32];
    570     FXSYS_memcpy(enckey, digest, key_len);
    571     for (uint32_t i = 0; i < 32; i++) {
    572       passcode[i] = i < user_size ? user_pass[i] : defpasscode[i - user_size];
    573     }
    574     CRYPT_ArcFourCryptBlock(passcode, 32, enckey, key_len);
    575     uint8_t tempkey[32];
    576     if (m_Revision >= 3) {
    577       for (uint8_t i = 1; i <= 19; i++) {
    578         for (int j = 0; j < key_len; j++)
    579           tempkey[j] = enckey[j] ^ i;
    580         CRYPT_ArcFourCryptBlock(passcode, 32, tempkey, key_len);
    581       }
    582     }
    583     pEncryptDict->SetNewFor<CPDF_String>("O", CFX_ByteString(passcode, 32),
    584                                          false);
    585   }
    586   CalcEncryptKey(m_pEncryptDict, (uint8_t*)user_pass, user_size, m_EncryptKey,
    587                  key_len, false, pIdArray);
    588   if (m_Revision < 3) {
    589     uint8_t tempbuf[32];
    590     FXSYS_memcpy(tempbuf, defpasscode, 32);
    591     CRYPT_ArcFourCryptBlock(tempbuf, 32, m_EncryptKey, key_len);
    592     pEncryptDict->SetNewFor<CPDF_String>("U", CFX_ByteString(tempbuf, 32),
    593                                          false);
    594   } else {
    595     CRYPT_md5_context md5;
    596     CRYPT_MD5Start(&md5);
    597     CRYPT_MD5Update(&md5, defpasscode, 32);
    598     if (pIdArray) {
    599       CFX_ByteString id = pIdArray->GetStringAt(0);
    600       CRYPT_MD5Update(&md5, (uint8_t*)id.c_str(), id.GetLength());
    601     }
    602     uint8_t digest[32];
    603     CRYPT_MD5Finish(&md5, digest);
    604     CRYPT_ArcFourCryptBlock(digest, 16, m_EncryptKey, key_len);
    605     uint8_t tempkey[32];
    606     for (uint8_t i = 1; i <= 19; i++) {
    607       for (int j = 0; j < key_len; j++) {
    608         tempkey[j] = m_EncryptKey[j] ^ i;
    609       }
    610       CRYPT_ArcFourCryptBlock(digest, 16, tempkey, key_len);
    611     }
    612     CRYPT_MD5Generate(digest, 16, digest + 16);
    613     pEncryptDict->SetNewFor<CPDF_String>("U", CFX_ByteString(digest, 32),
    614                                          false);
    615   }
    616 }
    617 void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict,
    618                                     CPDF_Array* pIdArray,
    619                                     const uint8_t* user_pass,
    620                                     uint32_t user_size,
    621                                     const uint8_t* owner_pass,
    622                                     uint32_t owner_size,
    623                                     uint32_t type) {
    624   OnCreate(pEncryptDict, pIdArray, user_pass, user_size, owner_pass, owner_size,
    625            true, type);
    626 }
    627 void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict,
    628                                     CPDF_Array* pIdArray,
    629                                     const uint8_t* user_pass,
    630                                     uint32_t user_size,
    631                                     uint32_t type) {
    632   OnCreate(pEncryptDict, pIdArray, user_pass, user_size, nullptr, 0, false,
    633            type);
    634 }
    635 void CPDF_SecurityHandler::AES256_SetPassword(CPDF_Dictionary* pEncryptDict,
    636                                               const uint8_t* password,
    637                                               uint32_t size,
    638                                               bool bOwner,
    639                                               const uint8_t* key) {
    640   CRYPT_sha1_context sha;
    641   CRYPT_SHA1Start(&sha);
    642   CRYPT_SHA1Update(&sha, key, 32);
    643   CRYPT_SHA1Update(&sha, (uint8_t*)"hello", 5);
    644 
    645   uint8_t digest[20];
    646   CRYPT_SHA1Finish(&sha, digest);
    647 
    648   CFX_ByteString ukey = pEncryptDict->GetStringFor("U");
    649   CRYPT_sha256_context sha2;
    650   uint8_t digest1[48];
    651   if (m_Revision >= 6) {
    652     Revision6_Hash(password, size, digest, bOwner ? ukey.raw_str() : nullptr,
    653                    digest1);
    654   } else {
    655     CRYPT_SHA256Start(&sha2);
    656     CRYPT_SHA256Update(&sha2, password, size);
    657     CRYPT_SHA256Update(&sha2, digest, 8);
    658     if (bOwner) {
    659       CRYPT_SHA256Update(&sha2, ukey.raw_str(), ukey.GetLength());
    660     }
    661     CRYPT_SHA256Finish(&sha2, digest1);
    662   }
    663   FXSYS_memcpy(digest1 + 32, digest, 16);
    664   pEncryptDict->SetNewFor<CPDF_String>(bOwner ? "O" : "U",
    665                                        CFX_ByteString(digest1, 48), false);
    666   if (m_Revision >= 6) {
    667     Revision6_Hash(password, size, digest + 8,
    668                    bOwner ? ukey.raw_str() : nullptr, digest1);
    669   } else {
    670     CRYPT_SHA256Start(&sha2);
    671     CRYPT_SHA256Update(&sha2, password, size);
    672     CRYPT_SHA256Update(&sha2, digest + 8, 8);
    673     if (bOwner) {
    674       CRYPT_SHA256Update(&sha2, ukey.raw_str(), ukey.GetLength());
    675     }
    676     CRYPT_SHA256Finish(&sha2, digest1);
    677   }
    678   uint8_t* aes = FX_Alloc(uint8_t, 2048);
    679   CRYPT_AESSetKey(aes, 16, digest1, 32, true);
    680   uint8_t iv[16];
    681   FXSYS_memset(iv, 0, 16);
    682   CRYPT_AESSetIV(aes, iv);
    683   CRYPT_AESEncrypt(aes, digest1, key, 32);
    684   FX_Free(aes);
    685   pEncryptDict->SetNewFor<CPDF_String>(bOwner ? "OE" : "UE",
    686                                        CFX_ByteString(digest1, 32), false);
    687 }
    688 
    689 void CPDF_SecurityHandler::AES256_SetPerms(CPDF_Dictionary* pEncryptDict,
    690                                            uint32_t permissions,
    691                                            bool bEncryptMetadata,
    692                                            const uint8_t* key) {
    693   uint8_t buf[16];
    694   buf[0] = (uint8_t)permissions;
    695   buf[1] = (uint8_t)(permissions >> 8);
    696   buf[2] = (uint8_t)(permissions >> 16);
    697   buf[3] = (uint8_t)(permissions >> 24);
    698   buf[4] = 0xff;
    699   buf[5] = 0xff;
    700   buf[6] = 0xff;
    701   buf[7] = 0xff;
    702   buf[8] = bEncryptMetadata ? 'T' : 'F';
    703   buf[9] = 'a';
    704   buf[10] = 'd';
    705   buf[11] = 'b';
    706   uint8_t* aes = FX_Alloc(uint8_t, 2048);
    707   CRYPT_AESSetKey(aes, 16, key, 32, true);
    708   uint8_t iv[16], buf1[16];
    709   FXSYS_memset(iv, 0, 16);
    710   CRYPT_AESSetIV(aes, iv);
    711   CRYPT_AESEncrypt(aes, buf1, buf, 16);
    712   FX_Free(aes);
    713   pEncryptDict->SetNewFor<CPDF_String>("Perms", CFX_ByteString(buf1, 16),
    714                                        false);
    715 }
    716