From 8755d2bad429c393d693f4b703c1d7e05b1d0770 Mon Sep 17 00:00:00 2001 From: Levi Akatsuki Date: Sat, 16 Mar 2024 15:57:32 +0000 Subject: [PATCH] Require both keys to use the emulator --- src/core/crypto/key_manager.cpp | 24 +++++++++++++++++++++++- src/core/loader/nax.cpp | 4 ++++ src/core/loader/nsp.cpp | 4 ++++ src/core/loader/xci.cpp | 4 ++++ src/suyu/main.cpp | 21 +++++++++++++++------ 5 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index 9ca4655c49..e1b520333d 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp @@ -643,7 +643,7 @@ void KeyManager::ReloadKeys() { const auto suyu_keys_dir = Common::FS::GetSuyuPath(Common::FS::SuyuPath::KeysDir); if (!Common::FS::CreateDir(suyu_keys_dir)) { - LOG_ERROR(Core, "Failed to create the keys directory."); + LOG_ERROR(Crypto, "Failed to create the keys directory."); } if (Settings::values.use_dev_keys) { @@ -668,6 +668,8 @@ static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_ void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_title_keys) { if (!Common::FS::Exists(file_path)) { + LOG_ERROR(Crypto, "Failed to load key file at '{}': File not found", + file_path.generic_string()); return; } @@ -675,9 +677,12 @@ void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_ti Common::FS::OpenFileStream(file, file_path, std::ios_base::in); if (!file.is_open()) { + LOG_ERROR(Crypto, "Failed to load key file at '{}': Can't open file", + file_path.generic_string()); return; } + LOG_INFO(Crypto, "Loading key file at '{}'", file_path.generic_string()); std::string line; while (std::getline(file, line)) { std::vector out; @@ -703,6 +708,8 @@ void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_ti u128 rights_id{}; std::memcpy(rights_id.data(), rights_id_raw.data(), rights_id_raw.size()); Key128 key = Common::HexStringToArray<16>(out[1]); + + LOG_INFO(Crypto, "Successfully loaded title key"); s128_keys[{S128KeyType::Titlekey, rights_id[1], rights_id[0]}] = key; } else { out[0] = Common::ToLower(out[0]); @@ -785,6 +792,21 @@ bool KeyManager::BaseDeriveNecessary() const { return !HasKey(key_type, index1, index2); }; + // Ensure the files exists + const auto suyu_keys_dir = Common::FS::GetSuyuPath(Common::FS::SuyuPath::KeysDir); + + if (!Common::FS::Exists(suyu_keys_dir / + (Settings::values.use_dev_keys ? "dev.keys" : "prod.keys"))) { + LOG_ERROR(Crypto, "No {} found", + (Settings::values.use_dev_keys ? "dev.keys" : "prod.keys")); + return true; + } + + if (!Common::FS::Exists(suyu_keys_dir / "title.keys")) { + LOG_ERROR(Crypto, "No title.keys found"); + return true; + } + if (check_key_existence(S256KeyType::Header)) { return true; } diff --git a/src/core/loader/nax.cpp b/src/core/loader/nax.cpp index 3b7b005ff4..725cb228d0 100644 --- a/src/core/loader/nax.cpp +++ b/src/core/loader/nax.cpp @@ -55,6 +55,10 @@ AppLoader_NAX::LoadResult AppLoader_NAX::Load(Kernel::KProcess& process, Core::S return {ResultStatus::ErrorMissingProductionKeyFile, {}}; } + if (!Core::Crypto::KeyManager::KeyFileExists(true)) { + return {ResultStatus::ErrorMissingProductionKeyFile, {}}; + } + return {ResultStatus::ErrorNAXInconvertibleToNCA, {}}; } diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp index 3016d5f25f..39198c9b66 100644 --- a/src/core/loader/nsp.cpp +++ b/src/core/loader/nsp.cpp @@ -102,6 +102,10 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::KProcess& process, Core::S return {ResultStatus::ErrorMissingProductionKeyFile, {}}; } + if (!Core::Crypto::KeyManager::KeyFileExists(true)) { + return {ResultStatus::ErrorMissingProductionKeyFile, {}}; + } + return {ResultStatus::ErrorNSPMissingProgramNCA, {}}; } diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp index e9abb199a1..d4722ac4c0 100644 --- a/src/core/loader/xci.cpp +++ b/src/core/loader/xci.cpp @@ -71,6 +71,10 @@ AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::KProcess& process, Core::S return {ResultStatus::ErrorMissingProductionKeyFile, {}}; } + if (!xci->HasProgramNCA() && !Core::Crypto::KeyManager::KeyFileExists(true)) { + return {ResultStatus::ErrorMissingProductionKeyFile, {}}; + } + const auto result = nca_loader->Load(process, system); if (result.first != ResultStatus::Success) { return result; diff --git a/src/suyu/main.cpp b/src/suyu/main.cpp index 8952b324df..4b9265febf 100644 --- a/src/suyu/main.cpp +++ b/src/suyu/main.cpp @@ -1752,6 +1752,15 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa return false; } + if (!ContentManager::AreKeysPresent()) { + QMessageBox::warning(this, tr("Derivation Components Missing"), + tr("Encryption keys are missing. " + "You need to provide both your own title.keys " + "and your own prod.keys " + "in order to play games")); + return false; + } + // Shutdown previous session if the emu thread is still active... if (emu_thread != nullptr) { ShutdownGame(); @@ -4619,13 +4628,13 @@ void GMainWindow::OnMouseActivity() { void GMainWindow::OnCheckFirmwareDecryption() { system->GetFileSystemController().CreateFactories(*vfs); if (!ContentManager::AreKeysPresent()) { - QMessageBox::warning( - this, tr("Derivation Components Missing"), - tr("Encryption keys are missing. " - "
Please follow the suyu " - "quickstart guide to get all your keys, firmware and " - "games.")); + QMessageBox::warning(this, tr("Derivation Components Missing"), + tr("Encryption keys are missing. " + "You need to provide both your own title.keys " + "and your own prod.keys " + "in order to play games")); } + SetFirmwareVersion(); UpdateMenuState(); }