crypto: Make KeyManager a singleton class

Previously, we were reading the keys everytime a KeyManager object was created, causing yuzu to reread the keys file multiple hundreds of times when loading the game list.
With this change, it is only loaded once.
On my system, this decreased game list loading times by a factor of 20.
This commit is contained in:
FearlessTobi 2020-05-20 21:28:16 +02:00
parent 41682e0888
commit 9f82a9a244
13 changed files with 27 additions and 21 deletions

View file

@ -223,7 +223,13 @@ bool operator<(const KeyIndex<KeyType>& lhs, const KeyIndex<KeyType>& rhs) {
class KeyManager { class KeyManager {
public: public:
KeyManager(); static KeyManager& instance() {
static KeyManager instance;
return instance;
}
KeyManager(KeyManager const&) = delete;
void operator=(KeyManager const&) = delete;
bool HasKey(S128KeyType id, u64 field1 = 0, u64 field2 = 0) const; bool HasKey(S128KeyType id, u64 field1 = 0, u64 field2 = 0) const;
bool HasKey(S256KeyType id, u64 field1 = 0, u64 field2 = 0) const; bool HasKey(S256KeyType id, u64 field1 = 0, u64 field2 = 0) const;
@ -257,6 +263,8 @@ public:
bool AddTicketPersonalized(Ticket raw); bool AddTicketPersonalized(Ticket raw);
private: private:
KeyManager();
std::map<KeyIndex<S128KeyType>, Key128> s128_keys; std::map<KeyIndex<S128KeyType>, Key128> s128_keys;
std::map<KeyIndex<S256KeyType>, Key256> s256_keys; std::map<KeyIndex<S256KeyType>, Key256> s256_keys;

View file

@ -79,7 +79,7 @@ VirtualDir BISFactory::OpenPartition(BisPartitionId id) const {
} }
VirtualFile BISFactory::OpenPartitionStorage(BisPartitionId id) const { VirtualFile BISFactory::OpenPartitionStorage(BisPartitionId id) const {
Core::Crypto::KeyManager keys; Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::instance();
Core::Crypto::PartitionDataManager pdm{ Core::Crypto::PartitionDataManager pdm{
Core::System::GetInstance().GetFilesystem()->OpenDirectory( Core::System::GetInstance().GetFilesystem()->OpenDirectory(
FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir), Mode::Read)}; FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir), Mode::Read)};

View file

@ -178,7 +178,7 @@ u32 XCI::GetSystemUpdateVersion() {
return 0; return 0;
for (const auto& file : update->GetFiles()) { for (const auto& file : update->GetFiles()) {
NCA nca{file, nullptr, 0, keys}; NCA nca{file, nullptr, 0};
if (nca.GetStatus() != Loader::ResultStatus::Success) if (nca.GetStatus() != Loader::ResultStatus::Success)
continue; continue;
@ -286,7 +286,7 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) {
continue; continue;
} }
auto nca = std::make_shared<NCA>(file, nullptr, 0, keys); auto nca = std::make_shared<NCA>(file, nullptr, 0);
if (nca->IsUpdate()) { if (nca->IsUpdate()) {
continue; continue;
} }

View file

@ -140,6 +140,6 @@ private:
u64 update_normal_partition_end; u64 update_normal_partition_end;
Core::Crypto::KeyManager keys; Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::instance();
}; };
} // namespace FileSys } // namespace FileSys

View file

@ -118,9 +118,8 @@ static bool IsValidNCA(const NCAHeader& header) {
return header.magic == Common::MakeMagic('N', 'C', 'A', '3'); return header.magic == Common::MakeMagic('N', 'C', 'A', '3');
} }
NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_offset, NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_offset)
Core::Crypto::KeyManager keys_) : file(std::move(file_)), bktr_base_romfs(std::move(bktr_base_romfs_)) {
: file(std::move(file_)), bktr_base_romfs(std::move(bktr_base_romfs_)), keys(std::move(keys_)) {
if (file == nullptr) { if (file == nullptr) {
status = Loader::ResultStatus::ErrorNullFile; status = Loader::ResultStatus::ErrorNullFile;
return; return;

View file

@ -99,8 +99,7 @@ inline bool IsDirectoryLogoPartition(const VirtualDir& pfs) {
class NCA : public ReadOnlyVfsDirectory { class NCA : public ReadOnlyVfsDirectory {
public: public:
explicit NCA(VirtualFile file, VirtualFile bktr_base_romfs = nullptr, explicit NCA(VirtualFile file, VirtualFile bktr_base_romfs = nullptr,
u64 bktr_base_ivfc_offset = 0, u64 bktr_base_ivfc_offset = 0);
Core::Crypto::KeyManager keys = Core::Crypto::KeyManager());
~NCA() override; ~NCA() override;
Loader::ResultStatus GetStatus() const; Loader::ResultStatus GetStatus() const;
@ -159,7 +158,7 @@ private:
bool encrypted = false; bool encrypted = false;
bool is_update = false; bool is_update = false;
Core::Crypto::KeyManager keys; Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::instance();
}; };
} // namespace FileSys } // namespace FileSys

View file

@ -408,7 +408,7 @@ void RegisteredCache::ProcessFiles(const std::vector<NcaID>& ids) {
if (file == nullptr) if (file == nullptr)
continue; continue;
const auto nca = std::make_shared<NCA>(parser(file, id), nullptr, 0, keys); const auto nca = std::make_shared<NCA>(parser(file, id), nullptr, 0);
if (nca->GetStatus() != Loader::ResultStatus::Success || if (nca->GetStatus() != Loader::ResultStatus::Success ||
nca->GetType() != NCAContentType::Meta) { nca->GetType() != NCAContentType::Meta) {
continue; continue;
@ -486,7 +486,7 @@ std::unique_ptr<NCA> RegisteredCache::GetEntry(u64 title_id, ContentRecordType t
const auto raw = GetEntryRaw(title_id, type); const auto raw = GetEntryRaw(title_id, type);
if (raw == nullptr) if (raw == nullptr)
return nullptr; return nullptr;
return std::make_unique<NCA>(raw, nullptr, 0, keys); return std::make_unique<NCA>(raw, nullptr, 0);
} }
template <typename T> template <typename T>
@ -865,7 +865,7 @@ std::unique_ptr<NCA> ManualContentProvider::GetEntry(u64 title_id, ContentRecord
const auto res = GetEntryRaw(title_id, type); const auto res = GetEntryRaw(title_id, type);
if (res == nullptr) if (res == nullptr)
return nullptr; return nullptr;
return std::make_unique<NCA>(res, nullptr, 0, keys); return std::make_unique<NCA>(res, nullptr, 0);
} }
std::vector<ContentProviderEntry> ManualContentProvider::ListEntriesFilter( std::vector<ContentProviderEntry> ManualContentProvider::ListEntriesFilter(

View file

@ -88,7 +88,7 @@ public:
protected: protected:
// A single instance of KeyManager to be used by GetEntry() // A single instance of KeyManager to be used by GetEntry()
Core::Crypto::KeyManager keys; Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::instance();
}; };
class PlaceholderCache { class PlaceholderCache {

View file

@ -21,7 +21,7 @@
namespace FileSys { namespace FileSys {
namespace { namespace {
void SetTicketKeys(const std::vector<VirtualFile>& files) { void SetTicketKeys(const std::vector<VirtualFile>& files) {
Core::Crypto::KeyManager keys; Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::instance();
for (const auto& ticket_file : files) { for (const auto& ticket_file : files) {
if (ticket_file == nullptr) { if (ticket_file == nullptr) {
@ -285,7 +285,7 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
continue; continue;
} }
auto next_nca = std::make_shared<NCA>(std::move(next_file), nullptr, 0, keys); auto next_nca = std::make_shared<NCA>(std::move(next_file), nullptr, 0);
if (next_nca->GetType() == NCAContentType::Program) { if (next_nca->GetType() == NCAContentType::Program) {
program_status[cnmt.GetTitleID()] = next_nca->GetStatus(); program_status[cnmt.GetTitleID()] = next_nca->GetStatus();
} }

View file

@ -73,7 +73,7 @@ private:
std::map<u64, std::map<std::pair<TitleType, ContentRecordType>, std::shared_ptr<NCA>>> ncas; std::map<u64, std::map<std::pair<TitleType, ContentRecordType>, std::shared_ptr<NCA>>> ncas;
std::vector<VirtualFile> ticket_files; std::vector<VirtualFile> ticket_files;
Core::Crypto::KeyManager keys; Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::instance();
VirtualFile romfs; VirtualFile romfs;
VirtualDir exefs; VirtualDir exefs;

View file

@ -62,6 +62,6 @@ private:
VirtualFile dec_file; VirtualFile dec_file;
Core::Crypto::KeyManager keys; Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::instance();
}; };
} // namespace FileSys } // namespace FileSys

View file

@ -263,7 +263,7 @@ private:
rb.Push<u64>(write_size); rb.Push<u64>(write_size);
} }
Core::Crypto::KeyManager keys; Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::instance();
}; };
void InstallInterfaces(SM::ServiceManager& service_manager) { void InstallInterfaces(SM::ServiceManager& service_manager) {

View file

@ -2116,7 +2116,7 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
"title.keys_autogenerated"); "title.keys_autogenerated");
} }
Core::Crypto::KeyManager keys{}; Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::instance();
if (keys.BaseDeriveNecessary()) { if (keys.BaseDeriveNecessary()) {
Core::Crypto::PartitionDataManager pdm{vfs->OpenDirectory( Core::Crypto::PartitionDataManager pdm{vfs->OpenDirectory(
FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir), FileSys::Mode::Read)}; FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir), FileSys::Mode::Read)};