From a9dc5a3c1058d22873a201c08bd6d095405789ae Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 16 Aug 2018 16:57:00 -0400 Subject: xci: Fix error masking issue Prevents NCA-related errors from being masked into MissingProgramNCA or MissingKeyFile --- src/core/file_sys/card_image.cpp | 9 +++++++++ src/core/file_sys/card_image.h | 2 ++ 2 files changed, 11 insertions(+) (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index 1d7c7fb10..508f09e56 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp @@ -43,6 +43,8 @@ XCI::XCI(VirtualFile file_) : file(std::move(file_)), partitions(0x4) { partitions[static_cast(partition)] = std::make_shared(raw); } + program_nca_status = Loader::ResultStatus::ErrorXCIMissingProgramNCA; + auto result = AddNCAFromPartition(XCIPartition::Secure); if (result != Loader::ResultStatus::Success) { status = result; @@ -76,6 +78,10 @@ Loader::ResultStatus XCI::GetStatus() const { return status; } +Loader::ResultStatus XCI::GetProgramNCAStatus() const { + return program_nca_status; +} + VirtualDir XCI::GetPartition(XCIPartition partition) const { return partitions[static_cast(partition)]; } @@ -143,6 +149,9 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) { if (file->GetExtension() != "nca") continue; auto nca = std::make_shared(file); + if (nca->GetType() == NCAContentType::Program) { + program_nca_status = nca->GetStatus(); + } if (nca->GetStatus() == Loader::ResultStatus::Success) { ncas.push_back(std::move(nca)); } else { diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h index a03d5264e..54ab828d1 100644 --- a/src/core/file_sys/card_image.h +++ b/src/core/file_sys/card_image.h @@ -59,6 +59,7 @@ public: explicit XCI(VirtualFile file); Loader::ResultStatus GetStatus() const; + Loader::ResultStatus GetProgramNCAStatus() const; u8 GetFormatVersion() const; @@ -90,6 +91,7 @@ private: GamecardHeader header{}; Loader::ResultStatus status; + Loader::ResultStatus program_nca_status; std::vector partitions; std::vector> ncas; -- cgit v1.2.3 From c4845df3d4b9fc3fc19dd936af87090ffb3fbdf2 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 16 Aug 2018 17:01:32 -0400 Subject: xts_encryption_layer: Implement XTSEncryptionLayer --- src/core/file_sys/content_archive.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 47afcad9b..008e11d8c 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -178,7 +178,7 @@ VirtualFile NCA::Decrypt(NCASectionHeader s_header, VirtualFile in, u64 starting return std::static_pointer_cast(out); } case NCASectionCryptoType::XTS: - // TODO(DarkLordZach): Implement XTSEncryptionLayer. + // TODO(DarkLordZach): Find a test case for XTS-encrypted NCAs default: LOG_ERROR(Crypto, "called with unhandled crypto type={:02X}", static_cast(s_header.raw.header.crypto_type)); -- cgit v1.2.3 From bf33f80fae1e97f48a62e16b1e965d7994ac4c45 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 16 Aug 2018 17:05:30 -0400 Subject: vfs: Add GetOrCreateDirectoryRelative method --- src/core/file_sys/bis_factory.cpp | 11 ++--------- src/core/file_sys/vfs.cpp | 7 +++++++ src/core/file_sys/vfs.h | 4 ++++ 3 files changed, 13 insertions(+), 9 deletions(-) (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/bis_factory.cpp b/src/core/file_sys/bis_factory.cpp index ae4e33800..08a7cea5a 100644 --- a/src/core/file_sys/bis_factory.cpp +++ b/src/core/file_sys/bis_factory.cpp @@ -6,19 +6,12 @@ namespace FileSys { -static VirtualDir GetOrCreateDirectory(const VirtualDir& dir, std::string_view path) { - const auto res = dir->GetDirectoryRelative(path); - if (res == nullptr) - return dir->CreateDirectoryRelative(path); - return res; -} - BISFactory::BISFactory(VirtualDir nand_root_) : nand_root(std::move(nand_root_)), sysnand_cache(std::make_shared( - GetOrCreateDirectory(nand_root, "/system/Contents/registered"))), + GetOrCreateDirectoryRelative(nand_root, "/system/Contents/registered"))), usrnand_cache(std::make_shared( - GetOrCreateDirectory(nand_root, "/user/Contents/registered"))) {} + GetOrCreateDirectoryRelative(nand_root, "/user/Contents/registered"))) {} std::shared_ptr BISFactory::GetSystemNANDContents() const { return sysnand_cache; diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp index b915b4c11..146c839f4 100644 --- a/src/core/file_sys/vfs.cpp +++ b/src/core/file_sys/vfs.cpp @@ -462,4 +462,11 @@ bool VfsRawCopy(VirtualFile src, VirtualFile dest) { std::vector data = src->ReadAllBytes(); return dest->WriteBytes(data, 0) == data.size(); } + +VirtualDir GetOrCreateDirectoryRelative(const VirtualDir& rel, std::string_view path) { + const auto res = rel->GetDirectoryRelative(path); + if (res == nullptr) + return rel->CreateDirectoryRelative(path); + return res; +} } // namespace FileSys diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h index 22db08b59..5142a3e86 100644 --- a/src/core/file_sys/vfs.h +++ b/src/core/file_sys/vfs.h @@ -318,4 +318,8 @@ bool DeepEquals(const VirtualFile& file1, const VirtualFile& file2, size_t block // directory of src/dest. bool VfsRawCopy(VirtualFile src, VirtualFile dest); +// Checks if the directory at path relative to rel exists. If it does, returns that. If it does not +// it attempts to create it and returns the new dir or nullptr on failure. +VirtualDir GetOrCreateDirectoryRelative(const VirtualDir& rel, std::string_view path); + } // namespace FileSys -- cgit v1.2.3 From 13524578b602a264a3925c5f4a2ce9607541d2fc Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 16 Aug 2018 17:06:56 -0400 Subject: sdmc_factory: Add SDMC RegisteredCache getter --- src/core/file_sys/sdmc_factory.cpp | 12 +++++++++++- src/core/file_sys/sdmc_factory.h | 3 +++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp index d1acf379f..b14a254c5 100644 --- a/src/core/file_sys/sdmc_factory.cpp +++ b/src/core/file_sys/sdmc_factory.cpp @@ -4,13 +4,23 @@ #include #include "core/file_sys/sdmc_factory.h" +#include "core/file_sys/xts_archive.h" namespace FileSys { -SDMCFactory::SDMCFactory(VirtualDir dir) : dir(std::move(dir)) {} +SDMCFactory::SDMCFactory(VirtualDir dir_) + : dir(std::move(dir_)), contents(std::make_shared( + GetOrCreateDirectoryRelative(dir, "/Nintendo/Contents/registered"), + [](const VirtualFile& file, const NcaID& id) { + return std::make_shared(file, id)->GetDecrypted(); + })) {} ResultVal SDMCFactory::Open() { return MakeResult(dir); } +std::shared_ptr SDMCFactory::GetSDMCContents() const { + return contents; +} + } // namespace FileSys diff --git a/src/core/file_sys/sdmc_factory.h b/src/core/file_sys/sdmc_factory.h index 245060690..bb579472c 100644 --- a/src/core/file_sys/sdmc_factory.h +++ b/src/core/file_sys/sdmc_factory.h @@ -15,9 +15,12 @@ public: explicit SDMCFactory(VirtualDir dir); ResultVal Open(); + std::shared_ptr GetSDMCContents() const; private: VirtualDir dir; + + std::shared_ptr contents; }; } // namespace FileSys -- cgit v1.2.3 From 8b52d6682a00d2d0ac025433f034d9974584c630 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 16 Aug 2018 17:07:37 -0400 Subject: registration: Add GetEntryUnparsed methods Returns the file before calling parser on it. --- src/core/file_sys/registered_cache.cpp | 12 ++++++++++++ src/core/file_sys/registered_cache.h | 3 +++ 2 files changed, 15 insertions(+) (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index e90dc6695..a128fa33d 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -262,6 +262,18 @@ bool RegisteredCache::HasEntry(RegisteredCacheEntry entry) const { return GetEntryRaw(entry) != nullptr; } +VirtualFile RegisteredCache::GetEntryUnparsed(u64 title_id, ContentRecordType type) const { + const auto id = GetNcaIDFromMetadata(title_id, type); + if (id == boost::none) + return nullptr; + + return GetFileAtID(id.get()); +} + +VirtualFile RegisteredCache::GetEntryUnparsed(RegisteredCacheEntry entry) const { + return GetEntryUnparsed(entry.title_id, entry.type); +} + VirtualFile RegisteredCache::GetEntryRaw(u64 title_id, ContentRecordType type) const { const auto id = GetNcaIDFromMetadata(title_id, type); if (id == boost::none) diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index a7c51a59c..f48cf3146 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h @@ -69,6 +69,9 @@ public: bool HasEntry(u64 title_id, ContentRecordType type) const; bool HasEntry(RegisteredCacheEntry entry) const; + VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const; + VirtualFile GetEntryUnparsed(RegisteredCacheEntry entry) const; + VirtualFile GetEntryRaw(u64 title_id, ContentRecordType type) const; VirtualFile GetEntryRaw(RegisteredCacheEntry entry) const; -- cgit v1.2.3 From ab44192ab01a27115e14a52d4823722cbd357c0d Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 16 Aug 2018 17:08:13 -0400 Subject: file_sys: Implement NAX containers --- src/core/file_sys/xts_archive.cpp | 164 ++++++++++++++++++++++++++++++++++++++ src/core/file_sys/xts_archive.h | 68 ++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 src/core/file_sys/xts_archive.cpp create mode 100644 src/core/file_sys/xts_archive.h (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp new file mode 100644 index 000000000..54be31916 --- /dev/null +++ b/src/core/file_sys/xts_archive.cpp @@ -0,0 +1,164 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include "common/assert.h" +#include "common/hex_util.h" +#include "common/logging/log.h" +#include "core/crypto/aes_util.h" +#include "core/crypto/xts_encryption_layer.h" +#include "core/file_sys/partition_filesystem.h" +#include "core/file_sys/vfs_offset.h" +#include "core/file_sys/xts_archive.h" +#include "core/loader/loader.h" + +namespace FileSys { + +template +static bool CalculateHMAC256(Destination* out, const SourceKey* key, size_t key_length, + const SourceData* data, size_t data_length) { + mbedtls_md_context_t context; + mbedtls_md_init(&context); + + const auto key_f = reinterpret_cast(key); + const std::vector key_v(key_f, key_f + key_length); + + if (mbedtls_md_setup(&context, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1) || + mbedtls_md_hmac_starts(&context, reinterpret_cast(key), key_length) || + mbedtls_md_hmac_update(&context, reinterpret_cast(data), data_length) || + mbedtls_md_hmac_finish(&context, reinterpret_cast(out))) { + mbedtls_md_free(&context); + return false; + } + + mbedtls_md_free(&context); + return true; +} + +NAX::NAX(VirtualFile file_) : file(std::move(file_)), header(std::make_unique()) { + std::string path = FileUtil::SanitizePath(file->GetFullPath()); + static const std::regex nax_path_regex("/registered/(000000[0-9A-F]{2})/([0-9A-F]{32})\\.nca", + std::regex_constants::ECMAScript | + std::regex_constants::icase); + std::smatch match; + if (!std::regex_search(path, match, nax_path_regex)) { + status = Loader::ResultStatus::ErrorBadNAXFilePath; + return; + } + + std::string two_dir = match[1]; + std::string nca_id = match[2]; + std::transform(two_dir.begin(), two_dir.end(), two_dir.begin(), ::toupper); + std::transform(nca_id.begin(), nca_id.end(), nca_id.begin(), ::tolower); + + status = Parse(fmt::format("/registered/{}/{}.nca", two_dir, nca_id)); +} + +NAX::NAX(VirtualFile file_, std::array nca_id) + : file(std::move(file_)), header(std::make_unique()) { + Core::Crypto::SHA256Hash hash{}; + mbedtls_sha256(nca_id.data(), nca_id.size(), hash.data(), 0); + status = Parse(fmt::format("/registered/000000{:02X}/{}.nca", hash[0], + Common::HexArrayToString(nca_id, false))); +} + +Loader::ResultStatus NAX::Parse(std::string path) { + if (file->ReadObject(header.get()) != sizeof(NAXHeader)) + return Loader::ResultStatus::ErrorBadNAXHeader; + + if (header->magic != Common::MakeMagic('N', 'A', 'X', '0')) + return Loader::ResultStatus::ErrorBadNAXHeader; + + if (file->GetSize() < 0x4000 + header->file_size) + return Loader::ResultStatus::ErrorIncorrectNAXFileSize; + + keys.DeriveSDSeedLazy(); + std::array sd_keys{}; + const auto sd_keys_res = Core::Crypto::DeriveSDKeys(sd_keys, keys); + if (sd_keys_res != Loader::ResultStatus::Success) { + return sd_keys_res; + } + + const auto enc_keys = header->key_area; + + size_t i = 0; + for (; i < 2; ++i) { + std::array nax_keys{}; + if (!CalculateHMAC256(nax_keys.data(), sd_keys[i].data(), 0x10, path.c_str(), + path.size())) { + return Loader::ResultStatus::ErrorNAXKeyHMACFailed; + } + + for (size_t j = 0; j < 2; ++j) { + Core::Crypto::AESCipher cipher(nax_keys[j], + Core::Crypto::Mode::ECB); + cipher.Transcode(enc_keys[j].data(), 0x10, header->key_area[j].data(), + Core::Crypto::Op::Decrypt); + } + + Core::Crypto::SHA256Hash validation{}; + if (!CalculateHMAC256(validation.data(), &header->magic, 0x60, sd_keys[i].data() + 0x10, + 0x10)) { + return Loader::ResultStatus::ErrorNAXValidationHMACFailed; + } + if (header->hmac == validation) + break; + } + + if (i == 2) { + return Loader::ResultStatus::ErrorNAXKeyDerivationFailed; + } + + type = static_cast(i); + + Core::Crypto::Key256 final_key{}; + memcpy(final_key.data(), &header->key_area, 0x20); + const auto enc_file = std::make_shared(file, header->file_size, 0x4000); + dec_file = std::make_shared(enc_file, final_key); + + return Loader::ResultStatus::Success; +} + +Loader::ResultStatus NAX::GetStatus() { + return status; +} + +VirtualFile NAX::GetDecrypted() { + return dec_file; +} + +std::shared_ptr NAX::AsNCA() { + if (type == NAXContentType::NCA) + return std::make_shared(GetDecrypted()); + return nullptr; +} + +NAXContentType NAX::GetContentType() { + return type; +} + +std::vector> NAX::GetFiles() const { + return {dec_file}; +} + +std::vector> NAX::GetSubdirectories() const { + return {}; +} + +std::string NAX::GetName() const { + return file->GetName(); +} + +std::shared_ptr NAX::GetParentDirectory() const { + return file->GetContainingDirectory(); +} + +bool NAX::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) { + return false; +} +} // namespace FileSys diff --git a/src/core/file_sys/xts_archive.h b/src/core/file_sys/xts_archive.h new file mode 100644 index 000000000..4e44f634a --- /dev/null +++ b/src/core/file_sys/xts_archive.h @@ -0,0 +1,68 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include "common/common_types.h" +#include "common/swap.h" +#include "core/file_sys/content_archive.h" +#include "core/file_sys/vfs.h" +#include "core/loader/loader.h" + +namespace FileSys { + +struct NAXHeader { + std::array hmac; + u64_le magic; + std::array key_area; + u64_le file_size; + INSERT_PADDING_BYTES(0x30); +}; +static_assert(sizeof(NAXHeader) == 0x80, "NAXHeader has incorrect size."); + +enum class NAXContentType : u8 { + Save = 0, + NCA = 1, +}; + +class NAX : public ReadOnlyVfsDirectory { +public: + explicit NAX(VirtualFile file); + explicit NAX(VirtualFile file, std::array nca_id); + + Loader::ResultStatus GetStatus(); + + VirtualFile GetDecrypted(); + + std::shared_ptr AsNCA(); + + NAXContentType GetContentType(); + + std::vector> GetFiles() const override; + + std::vector> GetSubdirectories() const override; + + std::string GetName() const override; + + std::shared_ptr GetParentDirectory() const override; + +protected: + bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; + +private: + Loader::ResultStatus Parse(std::string path); + + std::unique_ptr header; + + VirtualFile file; + Loader::ResultStatus status; + NAXContentType type; + + VirtualFile dec_file; + + Core::Crypto::KeyManager keys; +}; +} // namespace FileSys -- cgit v1.2.3 From 42dc856ce136c75f587649863ec5bd936ba8b07a Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 18 Aug 2018 21:14:57 -0400 Subject: crypto: Eliminate magic constants --- src/core/file_sys/xts_archive.cpp | 25 ++++++++++++++----------- src/core/file_sys/xts_archive.h | 10 +++++----- 2 files changed, 19 insertions(+), 16 deletions(-) (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp index 54be31916..605c1a283 100644 --- a/src/core/file_sys/xts_archive.cpp +++ b/src/core/file_sys/xts_archive.cpp @@ -19,6 +19,8 @@ namespace FileSys { +constexpr u64 NAX_HEADER_PADDING_SIZE = 0x4000; + template static bool CalculateHMAC256(Destination* out, const SourceKey* key, size_t key_length, const SourceData* data, size_t data_length) { @@ -67,14 +69,14 @@ NAX::NAX(VirtualFile file_, std::array nca_id) Common::HexArrayToString(nca_id, false))); } -Loader::ResultStatus NAX::Parse(std::string path) { +Loader::ResultStatus NAX::Parse(std::string_view path) { if (file->ReadObject(header.get()) != sizeof(NAXHeader)) return Loader::ResultStatus::ErrorBadNAXHeader; if (header->magic != Common::MakeMagic('N', 'A', 'X', '0')) return Loader::ResultStatus::ErrorBadNAXHeader; - if (file->GetSize() < 0x4000 + header->file_size) + if (file->GetSize() < NAX_HEADER_PADDING_SIZE + header->file_size) return Loader::ResultStatus::ErrorIncorrectNAXFileSize; keys.DeriveSDSeedLazy(); @@ -87,14 +89,14 @@ Loader::ResultStatus NAX::Parse(std::string path) { const auto enc_keys = header->key_area; size_t i = 0; - for (; i < 2; ++i) { + for (; i < sd_keys.size(); ++i) { std::array nax_keys{}; - if (!CalculateHMAC256(nax_keys.data(), sd_keys[i].data(), 0x10, path.c_str(), + if (!CalculateHMAC256(nax_keys.data(), sd_keys[i].data(), 0x10, std::string(path).c_str(), path.size())) { return Loader::ResultStatus::ErrorNAXKeyHMACFailed; } - for (size_t j = 0; j < 2; ++j) { + for (size_t j = 0; j < nax_keys.size(); ++j) { Core::Crypto::AESCipher cipher(nax_keys[j], Core::Crypto::Mode::ECB); cipher.Transcode(enc_keys[j].data(), 0x10, header->key_area[j].data(), @@ -117,28 +119,29 @@ Loader::ResultStatus NAX::Parse(std::string path) { type = static_cast(i); Core::Crypto::Key256 final_key{}; - memcpy(final_key.data(), &header->key_area, 0x20); - const auto enc_file = std::make_shared(file, header->file_size, 0x4000); + std::memcpy(final_key.data(), &header->key_area, final_key.size()); + const auto enc_file = + std::make_shared(file, header->file_size, NAX_HEADER_PADDING_SIZE); dec_file = std::make_shared(enc_file, final_key); return Loader::ResultStatus::Success; } -Loader::ResultStatus NAX::GetStatus() { +Loader::ResultStatus NAX::GetStatus() const { return status; } -VirtualFile NAX::GetDecrypted() { +VirtualFile NAX::GetDecrypted() const { return dec_file; } -std::shared_ptr NAX::AsNCA() { +std::shared_ptr NAX::AsNCA() const { if (type == NAXContentType::NCA) return std::make_shared(GetDecrypted()); return nullptr; } -NAXContentType NAX::GetContentType() { +NAXContentType NAX::GetContentType() const { return type; } diff --git a/src/core/file_sys/xts_archive.h b/src/core/file_sys/xts_archive.h index 4e44f634a..5249ad026 100644 --- a/src/core/file_sys/xts_archive.h +++ b/src/core/file_sys/xts_archive.h @@ -33,13 +33,13 @@ public: explicit NAX(VirtualFile file); explicit NAX(VirtualFile file, std::array nca_id); - Loader::ResultStatus GetStatus(); + Loader::ResultStatus GetStatus() const; - VirtualFile GetDecrypted(); + VirtualFile GetDecrypted() const; - std::shared_ptr AsNCA(); + std::shared_ptr AsNCA() const; - NAXContentType GetContentType(); + NAXContentType GetContentType() const; std::vector> GetFiles() const override; @@ -53,7 +53,7 @@ protected: bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; private: - Loader::ResultStatus Parse(std::string path); + Loader::ResultStatus Parse(std::string_view path); std::unique_ptr header; -- cgit v1.2.3 From a7e8d10969f280cd5a869b3525c3339357a958a6 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 18 Aug 2018 21:16:20 -0400 Subject: file_sys: Cut down on includes and copies --- src/core/file_sys/registered_cache.cpp | 2 ++ src/core/file_sys/registered_cache.h | 1 + src/core/file_sys/sdmc_factory.h | 3 +++ 3 files changed, 6 insertions(+) (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index a128fa33d..a02efc71e 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -254,6 +254,8 @@ RegisteredCache::RegisteredCache(VirtualDir dir_, RegisteredCacheParsingFunction Refresh(); } +RegisteredCache::~RegisteredCache() = default; + bool RegisteredCache::HasEntry(u64 title_id, ContentRecordType type) const { return GetEntryRaw(title_id, type) != nullptr; } diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index f48cf3146..7b8955dfa 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h @@ -63,6 +63,7 @@ public: explicit RegisteredCache(VirtualDir dir, RegisteredCacheParsingFunction parsing_function = [](const VirtualFile& file, const NcaID& id) { return file; }); + ~RegisteredCache(); void Refresh(); diff --git a/src/core/file_sys/sdmc_factory.h b/src/core/file_sys/sdmc_factory.h index bb579472c..4eac92621 100644 --- a/src/core/file_sys/sdmc_factory.h +++ b/src/core/file_sys/sdmc_factory.h @@ -4,11 +4,14 @@ #pragma once +#include #include "core/file_sys/vfs.h" #include "core/hle/result.h" namespace FileSys { +class RegisteredCache; + /// File system interface to the SDCard archive class SDMCFactory { public: -- cgit v1.2.3 From 119ab308b551da889782420aeff088aff0d4882e Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Tue, 21 Aug 2018 15:04:03 -0400 Subject: key_manager: Create keys dir if it dosen't exist On call to WriteKeyToFile, so that the autogenerated file can be written. --- src/core/file_sys/sdmc_factory.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp index b14a254c5..e4df5c4d0 100644 --- a/src/core/file_sys/sdmc_factory.cpp +++ b/src/core/file_sys/sdmc_factory.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include "core/file_sys/registered_cache.h" #include "core/file_sys/sdmc_factory.h" #include "core/file_sys/xts_archive.h" -- cgit v1.2.3 From 4f18c17df77e791d30cc8c919108315610f315ef Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 23 Aug 2018 18:53:13 -0400 Subject: content_archive: Add update title detection This is needed because the title IDs of update NCAs will not use the update title ID. The only sure way to tell is to look for a partition with BKTR crypto. --- src/core/file_sys/content_archive.cpp | 8 ++++++++ src/core/file_sys/content_archive.h | 3 +++ 2 files changed, 11 insertions(+) (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 008e11d8c..e8b5d6ece 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -258,6 +258,10 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) { file->ReadBytes(sections.data(), length_sections, SECTION_HEADER_OFFSET); } + is_update = std::find_if(sections.begin(), sections.end(), [](const NCASectionHeader& header) { + return header.raw.header.crypto_type == NCASectionCryptoType::BKTR; + }) != sections.end(); + for (std::ptrdiff_t i = 0; i < number_sections; ++i) { auto section = sections[i]; @@ -358,6 +362,10 @@ VirtualFile NCA::GetBaseFile() const { return file; } +bool NCA::IsUpdate() const { + return is_update; +} + bool NCA::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) { return false; } diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h index 4b74c54ec..b961cfde7 100644 --- a/src/core/file_sys/content_archive.h +++ b/src/core/file_sys/content_archive.h @@ -93,6 +93,8 @@ public: VirtualFile GetBaseFile() const; + bool IsUpdate() const; + protected: bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; @@ -111,6 +113,7 @@ private: NCAHeader header{}; bool has_rights_id{}; + bool is_update{}; Loader::ResultStatus status{}; -- cgit v1.2.3 From d1a6dd61d1e70d41cf7bc0dbf3a199cb21d8fdbd Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 23 Aug 2018 18:53:37 -0400 Subject: xci: Ignore NCA files with updates in secure --- src/core/file_sys/card_image.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index 508f09e56..d61a2ebe1 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp @@ -149,6 +149,9 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) { if (file->GetExtension() != "nca") continue; auto nca = std::make_shared(file); + // TODO(DarkLordZach): Add proper Rev1+ Support + if (nca->IsUpdate()) + continue; if (nca->GetType() == NCAContentType::Program) { program_nca_status = nca->GetStatus(); } -- cgit v1.2.3 From 6314a799aa7e20789562d2e877949dfebb6194ce Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 24 Aug 2018 22:15:32 -0400 Subject: file_sys/crypto: Fix missing/unnecessary includes --- src/core/file_sys/sdmc_factory.cpp | 2 ++ src/core/file_sys/sdmc_factory.h | 1 + src/core/file_sys/xts_archive.cpp | 2 ++ src/core/file_sys/xts_archive.h | 1 + 4 files changed, 6 insertions(+) (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp index e4df5c4d0..d66a9c9a4 100644 --- a/src/core/file_sys/sdmc_factory.cpp +++ b/src/core/file_sys/sdmc_factory.cpp @@ -16,6 +16,8 @@ SDMCFactory::SDMCFactory(VirtualDir dir_) return std::make_shared(file, id)->GetDecrypted(); })) {} +SDMCFactory::~SDMCFactory() = default; + ResultVal SDMCFactory::Open() { return MakeResult(dir); } diff --git a/src/core/file_sys/sdmc_factory.h b/src/core/file_sys/sdmc_factory.h index 4eac92621..ea12149de 100644 --- a/src/core/file_sys/sdmc_factory.h +++ b/src/core/file_sys/sdmc_factory.h @@ -16,6 +16,7 @@ class RegisteredCache; class SDMCFactory { public: explicit SDMCFactory(VirtualDir dir); + ~SDMCFactory(); ResultVal Open(); std::shared_ptr GetSDMCContents() const; diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp index 605c1a283..552835738 100644 --- a/src/core/file_sys/xts_archive.cpp +++ b/src/core/file_sys/xts_archive.cpp @@ -2,7 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include +#include #include #include #include diff --git a/src/core/file_sys/xts_archive.h b/src/core/file_sys/xts_archive.h index 5249ad026..55d2154a6 100644 --- a/src/core/file_sys/xts_archive.h +++ b/src/core/file_sys/xts_archive.h @@ -8,6 +8,7 @@ #include #include "common/common_types.h" #include "common/swap.h" +#include "core/crypto/key_manager.h" #include "core/file_sys/content_archive.h" #include "core/file_sys/vfs.h" #include "core/loader/loader.h" -- cgit v1.2.3