From a9c921a41dec63f76f80df1f0d5dc3be40fa80de Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 29 Jul 2018 20:47:33 -0400 Subject: Use ErrorEncrypted where applicable and fix no keys crash --- src/core/file_sys/card_image.cpp | 1 + src/core/file_sys/content_archive.cpp | 45 +++++++++++++++++++++++------------ src/core/file_sys/content_archive.h | 4 ++-- src/core/loader/xci.cpp | 4 ++++ 4 files changed, 37 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index c69812455..395eea8ae 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp @@ -45,6 +45,7 @@ XCI::XCI(VirtualFile file_) : file(std::move(file_)), partitions(0x4) { status = result; return; } + result = AddNCAFromPartition(XCIPartition::Update); if (result != Loader::ResultStatus::Success) { status = result; diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 9eceaa4c4..cb59c0a2b 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -4,7 +4,7 @@ #include #include - +#include #include "common/logging/log.h" #include "core/crypto/aes_util.h" #include "core/crypto/ctr_encryption_layer.h" @@ -76,13 +76,16 @@ bool IsValidNCA(const NCAHeader& header) { return header.magic == Common::MakeMagic('N', 'C', 'A', '3'); } -Core::Crypto::Key128 NCA::GetKeyAreaKey(NCASectionCryptoType type) const { +boost::optional NCA::GetKeyAreaKey(NCASectionCryptoType type) const { u8 master_key_id = header.crypto_type; if (header.crypto_type_2 > master_key_id) master_key_id = header.crypto_type_2; if (master_key_id > 0) --master_key_id; + if (!keys.HasKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, header.key_index)) + return boost::none; + std::vector key_area(header.key_area.begin(), header.key_area.end()); Core::Crypto::AESCipher cipher( keys.GetKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, header.key_index), @@ -116,13 +119,16 @@ VirtualFile NCA::Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_o case NCASectionCryptoType::CTR: LOG_DEBUG(Crypto, "called with mode=CTR, starting_offset={:016X}", starting_offset); { + const auto key = GetKeyAreaKey(NCASectionCryptoType::CTR); + if (key == boost::none) + return nullptr; auto out = std::make_shared( - std::move(in), GetKeyAreaKey(NCASectionCryptoType::CTR), starting_offset); + std::move(in), key.value(), starting_offset); std::vector iv(16); for (u8 i = 0; i < 8; ++i) iv[i] = header.raw.section_ctr[0x8 - i - 1]; out->SetIV(iv); - return out; + return std::static_pointer_cast(out); } case NCASectionCryptoType::XTS: // TODO(DarkLordZach): Implement XTSEncryptionLayer and title key encryption. @@ -149,7 +155,10 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) { header = dec_header; encrypted = true; } else { - status = Loader::ResultStatus::ErrorInvalidFormat; + if (!keys.HasKey(Core::Crypto::S256KeyType::Header)) + status = Loader::ResultStatus::ErrorEncrypted; + else + status = Loader::ResultStatus::ErrorInvalidFormat; return; } } @@ -179,23 +188,29 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) { header.section_tables[i].media_offset * MEDIA_OFFSET_MULTIPLIER + section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].offset; const size_t romfs_size = section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].size; - files.emplace_back( + const auto dec = Decrypt(section, std::make_shared(file, romfs_size, romfs_offset), - romfs_offset)); - romfs = files.back(); + romfs_offset); + if (dec != nullptr) { + files.emplace_back(); + romfs = files.back(); + } } else if (section.raw.header.filesystem_type == NCASectionFilesystemType::PFS0) { u64 offset = (static_cast(header.section_tables[i].media_offset) * MEDIA_OFFSET_MULTIPLIER) + section.pfs0.pfs0_header_offset; u64 size = MEDIA_OFFSET_MULTIPLIER * (header.section_tables[i].media_end_offset - header.section_tables[i].media_offset); - auto npfs = std::make_shared( - Decrypt(section, std::make_shared(file, size, offset), offset)); - - if (npfs->GetStatus() == Loader::ResultStatus::Success) { - dirs.emplace_back(npfs); - if (IsDirectoryExeFS(dirs.back())) - exefs = dirs.back(); + const auto dec = + Decrypt(section, std::make_shared(file, size, offset), offset); + if (dec != nullptr) { + auto npfs = std::make_shared(dec); + + if (npfs->GetStatus() == Loader::ResultStatus::Success) { + dirs.emplace_back(npfs); + if (IsDirectoryExeFS(dirs.back())) + exefs = dirs.back(); + } } } } diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h index e68ab0235..6492163b5 100644 --- a/src/core/file_sys/content_archive.h +++ b/src/core/file_sys/content_archive.h @@ -8,7 +8,7 @@ #include #include #include - +#include #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" @@ -95,7 +95,7 @@ protected: bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; private: - Core::Crypto::Key128 GetKeyAreaKey(NCASectionCryptoType type) const; + boost::optional GetKeyAreaKey(NCASectionCryptoType type) const; VirtualFile Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset) const; std::vector dirs; diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp index b4de5bd16..74940fb83 100644 --- a/src/core/loader/xci.cpp +++ b/src/core/loader/xci.cpp @@ -48,6 +48,10 @@ ResultStatus AppLoader_XCI::Load(Kernel::SharedPtr& process) { return ResultStatus::ErrorAlreadyLoaded; } + if (xci->GetNCAFileByType(FileSys::NCAContentType::Program) == nullptr) { + return ResultStatus::ErrorEncrypted; + } + auto result = nca_loader->Load(process); if (result != ResultStatus::Success) return result; -- cgit v1.2.3