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