From fbfe0c95fa30ab9def9e33fd9fb97dd4bd9851dd Mon Sep 17 00:00:00 2001 From: PavelBARABANOV Date: Sun, 1 Nov 2026 07:40:26 +0300 Subject: [PATCH] [fyle_sys] Fall back to RightsId as TitleKey for direct dumps --- src/core/file_sys/content_archive.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 1ba7bd3de3..dceed30d49 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -60,20 +60,17 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca, bool allow_missing_base) auto titlekey = keys.GetKey(Core::Crypto::S128KeyType::Titlekey, rights_id_u128[1], rights_id_u128[0]); if (titlekey == Core::Crypto::Key128{}) { - status = Loader::ResultStatus::ErrorMissingTitlekey; - return; + // Fallback: use rights_id as TitleKey for direct dumps without tickets/keys. + std::memcpy(titlekey.data(), rights_id.data(), rights_id.size()); + LOG_DEBUG(Loader, "TitleKey not found for {}, falling back to RightsId.", + file->GetName()); + } else if (keys.HasKey(Core::Crypto::S128KeyType::Titlekek, master_key_id)) { + auto titlekek = keys.GetKey(Core::Crypto::S128KeyType::Titlekek, master_key_id); + Core::Crypto::AESCipher cipher(titlekek, Core::Crypto::Mode::ECB); + cipher.Transcode(titlekey.data(), titlekey.size(), titlekey.data(), + Core::Crypto::Op::Decrypt); } - if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, master_key_id)) { - status = Loader::ResultStatus::ErrorMissingTitlekek; - return; - } - - auto titlekek = keys.GetKey(Core::Crypto::S128KeyType::Titlekek, master_key_id); - Core::Crypto::AESCipher cipher(titlekek, Core::Crypto::Mode::ECB); - cipher.Transcode(titlekey.data(), titlekey.size(), titlekey.data(), - Core::Crypto::Op::Decrypt); - reader->SetExternalDecryptionKey(titlekey.data(), titlekey.size()); }