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