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