FX_BOOL CPDF_SecurityHandler::CheckSecurity(int32_t key_len) { CFX_ByteString password = m_pParser->GetPassword(); if (!password.IsEmpty() && CheckPassword(password.raw_str(), password.GetLength(), TRUE, m_EncryptKey, key_len)) { m_bOwnerUnlocked = true; return TRUE; } return CheckPassword(password.raw_str(), password.GetLength(), FALSE, m_EncryptKey, key_len); }
void CPDF_SecurityHandler::AES256_SetPassword(CPDF_Dictionary* pEncryptDict, const uint8_t* password, uint32_t size, FX_BOOL bOwner, const uint8_t* key) { uint8_t sha[128]; CRYPT_SHA1Start(sha); CRYPT_SHA1Update(sha, key, 32); CRYPT_SHA1Update(sha, (uint8_t*)"hello", 5); uint8_t digest[20]; CRYPT_SHA1Finish(sha, digest); CFX_ByteString ukey = pEncryptDict->GetStringBy("U"); uint8_t digest1[48]; if (m_Revision >= 6) { Revision6_Hash(password, size, digest, bOwner ? ukey.raw_str() : nullptr, digest1); } else { CRYPT_SHA256Start(sha); CRYPT_SHA256Update(sha, password, size); CRYPT_SHA256Update(sha, digest, 8); if (bOwner) { CRYPT_SHA256Update(sha, ukey.raw_str(), ukey.GetLength()); } CRYPT_SHA256Finish(sha, digest1); } FXSYS_memcpy(digest1 + 32, digest, 16); pEncryptDict->SetAtString(bOwner ? "O" : "U", CFX_ByteString(digest1, 48)); if (m_Revision >= 6) { Revision6_Hash(password, size, digest + 8, bOwner ? ukey.raw_str() : nullptr, digest1); } else { CRYPT_SHA256Start(sha); CRYPT_SHA256Update(sha, password, size); CRYPT_SHA256Update(sha, digest + 8, 8); if (bOwner) { CRYPT_SHA256Update(sha, ukey.raw_str(), ukey.GetLength()); } CRYPT_SHA256Finish(sha, digest1); } uint8_t* aes = FX_Alloc(uint8_t, 2048); CRYPT_AESSetKey(aes, 16, digest1, 32, TRUE); uint8_t iv[16]; FXSYS_memset(iv, 0, 16); CRYPT_AESSetIV(aes, iv); CRYPT_AESEncrypt(aes, digest1, key, 32); FX_Free(aes); pEncryptDict->SetAtString(bOwner ? "OE" : "UE", CFX_ByteString(digest1, 32)); }
void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset) { if (!m_pFontInfo) return; m_FaceArray.push_back({name, static_cast<uint32_t>(charset)}); if (name == m_LastFamily) return; const uint8_t* ptr = name.raw_str(); bool bLocalized = false; for (int i = 0; i < name.GetLength(); i++) { if (ptr[i] > 0x80) { bLocalized = true; break; } } if (bLocalized) { void* hFont = m_pFontInfo->GetFont(name.c_str()); if (!hFont) { int iExact; hFont = m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, name.c_str(), iExact); if (!hFont) return; } CFX_ByteString new_name = GetPSNameFromTT(hFont); if (!new_name.IsEmpty()) m_LocalizedTTFonts.push_back(std::make_pair(new_name, name)); m_pFontInfo->DeleteFont(hFont); } m_InstalledTTFonts.push_back(name); m_LastFamily = name; }
void CPDF_CryptoHandler::Decrypt(uint32_t objnum, uint32_t gennum, CFX_ByteString& str) { CFX_BinaryBuf dest_buf; void* context = DecryptStart(objnum, gennum); DecryptStream(context, str.raw_str(), str.GetLength(), dest_buf); DecryptFinish(context, dest_buf); str = CFX_ByteString(dest_buf.GetBuffer(), dest_buf.GetSize()); }
FX_BOOL CPDF_SecurityHandler::AES256_CheckPassword(const uint8_t* password, uint32_t size, FX_BOOL bOwner, uint8_t* key) { CFX_ByteString okey = m_pEncryptDict ? m_pEncryptDict->GetStringBy("O") : CFX_ByteString(); if (okey.GetLength() < 48) { return FALSE; } CFX_ByteString ukey = m_pEncryptDict ? m_pEncryptDict->GetStringBy("U") : CFX_ByteString(); if (ukey.GetLength() < 48) { return FALSE; } const uint8_t* pkey = (bOwner ? okey : ukey).raw_str(); uint8_t sha[128]; uint8_t digest[32]; if (m_Revision >= 6) { Revision6_Hash(password, size, (const uint8_t*)pkey + 32, bOwner ? ukey.raw_str() : nullptr, digest); } else { CRYPT_SHA256Start(sha); CRYPT_SHA256Update(sha, password, size); CRYPT_SHA256Update(sha, pkey + 32, 8); if (bOwner) { CRYPT_SHA256Update(sha, ukey.raw_str(), 48); } CRYPT_SHA256Finish(sha, digest); } if (FXSYS_memcmp(digest, pkey, 32) != 0) { return FALSE; } if (!key) { return TRUE; } if (m_Revision >= 6) { Revision6_Hash(password, size, (const uint8_t*)pkey + 40, bOwner ? ukey.raw_str() : nullptr, digest); } else { CRYPT_SHA256Start(sha); CRYPT_SHA256Update(sha, password, size); CRYPT_SHA256Update(sha, pkey + 40, 8); if (bOwner) { CRYPT_SHA256Update(sha, ukey.raw_str(), 48); } CRYPT_SHA256Finish(sha, digest); } CFX_ByteString ekey = m_pEncryptDict ? m_pEncryptDict->GetStringBy(bOwner ? "OE" : "UE") : CFX_ByteString(); if (ekey.GetLength() < 32) { return FALSE; } uint8_t* aes = FX_Alloc(uint8_t, 2048); CRYPT_AESSetKey(aes, 16, digest, 32, FALSE); uint8_t iv[16]; FXSYS_memset(iv, 0, 16); CRYPT_AESSetIV(aes, iv); CRYPT_AESDecrypt(aes, key, ekey.raw_str(), 32); CRYPT_AESSetKey(aes, 16, key, 32, FALSE); CRYPT_AESSetIV(aes, iv); CFX_ByteString perms = m_pEncryptDict->GetStringBy("Perms"); if (perms.IsEmpty()) { return FALSE; } uint8_t perms_buf[16]; FXSYS_memset(perms_buf, 0, sizeof(perms_buf)); uint32_t copy_len = sizeof(perms_buf); if (copy_len > (uint32_t)perms.GetLength()) { copy_len = perms.GetLength(); } FXSYS_memcpy(perms_buf, perms.raw_str(), copy_len); uint8_t buf[16]; CRYPT_AESDecrypt(aes, buf, perms_buf, 16); FX_Free(aes); if (buf[9] != 'a' || buf[10] != 'd' || buf[11] != 'b') { return FALSE; } if (FXDWORD_GET_LSBFIRST(buf) != m_Permissions) { return FALSE; } if ((buf[8] == 'T' && !IsMetadataEncrypted()) || (buf[8] == 'F' && IsMetadataEncrypted())) { return FALSE; } return TRUE; }
void SetPageContents(CFX_ByteString key, CPDF_Dictionary* pPage, CPDF_Document* pDocument) { CPDF_Object* pContentsObj = pPage->GetStreamFor("Contents"); if (!pContentsObj) { pContentsObj = pPage->GetArrayFor("Contents"); } if (!pContentsObj) { // Create a new contents dictionary if (!key.IsEmpty()) { CPDF_Stream* pNewContents = new CPDF_Stream( nullptr, 0, new CPDF_Dictionary(pDocument->GetByteStringPool())); CFX_ByteString sStream; sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str()); pNewContents->SetData(sStream.raw_str(), sStream.GetLength()); pPage->SetReferenceFor("Contents", pDocument, pDocument->AddIndirectObject(pNewContents)); } return; } CPDF_Array* pContentsArray = nullptr; switch (pContentsObj->GetType()) { case CPDF_Object::STREAM: { pContentsArray = new CPDF_Array; CPDF_Stream* pContents = pContentsObj->AsStream(); uint32_t dwObjNum = pDocument->AddIndirectObject(pContents); CPDF_StreamAcc acc; acc.LoadAllData(pContents); CFX_ByteString sStream = "q\n"; CFX_ByteString sBody = CFX_ByteString((const FX_CHAR*)acc.GetData(), acc.GetSize()); sStream = sStream + sBody + "\nQ"; pContents->SetData(sStream.raw_str(), sStream.GetLength()); pContentsArray->AddReference(pDocument, dwObjNum); break; } case CPDF_Object::ARRAY: { pContentsArray = pContentsObj->AsArray(); break; } default: break; } if (!pContentsArray) return; pPage->SetReferenceFor("Contents", pDocument, pDocument->AddIndirectObject(pContentsArray)); if (!key.IsEmpty()) { CPDF_Stream* pNewContents = new CPDF_Stream( nullptr, 0, new CPDF_Dictionary(pDocument->GetByteStringPool())); CFX_ByteString sStream; sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str()); pNewContents->SetData(sStream.raw_str(), sStream.GetLength()); pContentsArray->AddReference(pDocument, pDocument->AddIndirectObject(pNewContents)); } }