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