diff options
Diffstat (limited to 'src/core/file_sys')
-rw-r--r-- | src/core/file_sys/content_archive.cpp | 17 | ||||
-rw-r--r-- | src/core/file_sys/nca_metadata.cpp | 4 | ||||
-rw-r--r-- | src/core/file_sys/nca_metadata.h | 1 | ||||
-rw-r--r-- | src/core/file_sys/registered_cache.cpp | 28 | ||||
-rw-r--r-- | src/core/file_sys/registered_cache.h | 5 | ||||
-rw-r--r-- | src/core/file_sys/submission_package.cpp | 35 | ||||
-rw-r--r-- | src/core/file_sys/submission_package.h | 1 |
7 files changed, 53 insertions, 38 deletions
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 44e6852fe..7d2f0abb8 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -22,6 +22,10 @@ namespace FileSys { +static u8 MasterKeyIdForKeyGeneration(u8 key_generation) { + return std::max<u8>(key_generation, 1) - 1; +} + NCA::NCA(VirtualFile file_, const NCA* base_nca) : file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} { if (file == nullptr) { @@ -41,12 +45,17 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca) return; } + // Ensure we have the proper key area keys to continue. + const u8 master_key_id = MasterKeyIdForKeyGeneration(reader->GetKeyGeneration()); + if (!keys.HasKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, reader->GetKeyIndex())) { + status = Loader::ResultStatus::ErrorMissingKeyAreaKey; + return; + } + RightsId rights_id{}; reader->GetRightsId(rights_id.data(), rights_id.size()); if (rights_id != RightsId{}) { // External decryption key required; provide it here. - const auto key_generation = std::max<s32>(reader->GetKeyGeneration(), 1) - 1; - u128 rights_id_u128; std::memcpy(rights_id_u128.data(), rights_id.data(), sizeof(rights_id)); @@ -57,12 +66,12 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca) return; } - if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, key_generation)) { + if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, master_key_id)) { status = Loader::ResultStatus::ErrorMissingTitlekek; return; } - auto titlekek = keys.GetKey(Core::Crypto::S128KeyType::Titlekek, key_generation); + auto titlekek = keys.GetKey(Core::Crypto::S128KeyType::Titlekek, master_key_id); Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(titlekek, Core::Crypto::Mode::ECB); cipher.Transcode(titlekey.data(), titlekey.size(), titlekey.data(), Core::Crypto::Op::Decrypt); diff --git a/src/core/file_sys/nca_metadata.cpp b/src/core/file_sys/nca_metadata.cpp index 52c78020c..f4a774675 100644 --- a/src/core/file_sys/nca_metadata.cpp +++ b/src/core/file_sys/nca_metadata.cpp @@ -45,6 +45,10 @@ CNMT::CNMT(CNMTHeader header_, OptionalHeader opt_header_, CNMT::~CNMT() = default; +const CNMTHeader& CNMT::GetHeader() const { + return header; +} + u64 CNMT::GetTitleID() const { return header.title_id; } diff --git a/src/core/file_sys/nca_metadata.h b/src/core/file_sys/nca_metadata.h index c59ece010..68e463b5f 100644 --- a/src/core/file_sys/nca_metadata.h +++ b/src/core/file_sys/nca_metadata.h @@ -89,6 +89,7 @@ public: std::vector<ContentRecord> content_records_, std::vector<MetaRecord> meta_records_); ~CNMT(); + const CNMTHeader& GetHeader() const; u64 GetTitleID() const; u32 GetTitleVersion() const; TitleType GetType() const; diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index f70adab82..e33b00d89 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -9,6 +9,7 @@ #include "common/fs/path_util.h" #include "common/hex_util.h" #include "common/logging/log.h" +#include "common/scope_exit.h" #include "core/crypto/key_manager.h" #include "core/file_sys/card_image.h" #include "core/file_sys/common_funcs.h" @@ -625,7 +626,7 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex nca->GetTitleId() != title_id) { // Create fake cnmt for patch to multiprogram application const auto sub_nca_result = - InstallEntry(*nca, TitleType::Update, overwrite_if_exists, copy); + InstallEntry(*nca, cnmt.GetHeader(), record, overwrite_if_exists, copy); if (sub_nca_result != InstallResult::Success) { return sub_nca_result; } @@ -672,6 +673,31 @@ InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type, return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id); } +InstallResult RegisteredCache::InstallEntry(const NCA& nca, const CNMTHeader& base_header, + const ContentRecord& base_record, + bool overwrite_if_exists, const VfsCopyFunction& copy) { + const CNMTHeader header{ + .title_id = nca.GetTitleId(), + .title_version = base_header.title_version, + .type = base_header.type, + .reserved = {}, + .table_offset = 0x10, + .number_content_entries = 1, + .number_meta_entries = 0, + .attributes = 0, + .reserved2 = {}, + .is_committed = 0, + .required_download_system_version = 0, + .reserved3 = {}, + }; + const OptionalHeader opt_header{0, 0}; + const CNMT new_cnmt(header, opt_header, {base_record}, {}); + if (!RawInstallYuzuMeta(new_cnmt)) { + return InstallResult::ErrorMetaFailed; + } + return RawInstallNCA(nca, copy, overwrite_if_exists, base_record.nca_id); +} + bool RegisteredCache::RemoveExistingEntry(u64 title_id) const { bool removed_data = false; diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index bd7f53eaf..64815a845 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h @@ -24,6 +24,7 @@ enum class NCAContentType : u8; enum class TitleType : u8; struct ContentRecord; +struct CNMTHeader; struct MetaRecord; class RegisteredCache; @@ -169,6 +170,10 @@ public: InstallResult InstallEntry(const NCA& nca, TitleType type, bool overwrite_if_exists = false, const VfsCopyFunction& copy = &VfsRawCopy); + InstallResult InstallEntry(const NCA& nca, const CNMTHeader& base_header, + const ContentRecord& base_record, bool overwrite_if_exists = false, + const VfsCopyFunction& copy = &VfsRawCopy); + // Removes an existing entry based on title id bool RemoveExistingEntry(u64 title_id) const; diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp index e1e89ce2d..68e8ec22f 100644 --- a/src/core/file_sys/submission_package.cpp +++ b/src/core/file_sys/submission_package.cpp @@ -164,24 +164,6 @@ VirtualFile NSP::GetNCAFile(u64 title_id, ContentRecordType type, TitleType titl return nullptr; } -std::vector<Core::Crypto::Key128> NSP::GetTitlekey() const { - if (extracted) - LOG_WARNING(Service_FS, "called on an NSP that is of type extracted."); - std::vector<Core::Crypto::Key128> out; - for (const auto& ticket_file : ticket_files) { - if (ticket_file == nullptr || - ticket_file->GetSize() < - Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET + sizeof(Core::Crypto::Key128)) { - continue; - } - - out.emplace_back(); - ticket_file->Read(out.back().data(), out.back().size(), - Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET); - } - return out; -} - std::vector<VirtualFile> NSP::GetFiles() const { return pfs->GetFiles(); } @@ -208,22 +190,11 @@ void NSP::SetTicketKeys(const std::vector<VirtualFile>& files) { continue; } - if (ticket_file->GetSize() < - Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET + sizeof(Core::Crypto::Key128)) { + auto ticket = Core::Crypto::Ticket::Read(ticket_file); + if (!keys.AddTicket(ticket)) { + LOG_WARNING(Common_Filesystem, "Could not load NSP ticket {}", ticket_file->GetName()); continue; } - - Core::Crypto::Key128 key{}; - ticket_file->Read(key.data(), key.size(), Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET); - - // We get the name without the extension in order to create the rights ID. - std::string name_only(ticket_file->GetName()); - name_only.erase(name_only.size() - 4); - - const auto rights_id_raw = Common::HexStringToArray<16>(name_only); - u128 rights_id; - std::memcpy(rights_id.data(), rights_id_raw.data(), sizeof(u128)); - keys.SetKey(Core::Crypto::S128KeyType::Titlekey, key, rights_id[1], rights_id[0]); } } diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h index 27f97c725..915bffca9 100644 --- a/src/core/file_sys/submission_package.h +++ b/src/core/file_sys/submission_package.h @@ -53,7 +53,6 @@ public: TitleType title_type = TitleType::Application) const; VirtualFile GetNCAFile(u64 title_id, ContentRecordType type, TitleType title_type = TitleType::Application) const; - std::vector<Core::Crypto::Key128> GetTitlekey() const; std::vector<VirtualFile> GetFiles() const override; |