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 {
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(S256KeyType id, u64 field1 = 0, u64 field2 = 0) const;
@ -257,6 +263,8 @@ public:
bool AddTicketPersonalized(Ticket raw);
private:
KeyManager();
std::map<KeyIndex<S128KeyType>, Key128> s128_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 {
Core::Crypto::KeyManager keys;
Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::instance();
Core::Crypto::PartitionDataManager pdm{
Core::System::GetInstance().GetFilesystem()->OpenDirectory(
FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir), Mode::Read)};

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -21,7 +21,7 @@
namespace FileSys {
namespace {
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) {
if (ticket_file == nullptr) {
@ -285,7 +285,7 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
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) {
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::vector<VirtualFile> ticket_files;
Core::Crypto::KeyManager keys;
Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::instance();
VirtualFile romfs;
VirtualDir exefs;

View file

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

View file

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

View file

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