diff options
| author | 2018-07-29 20:47:33 -0400 | |
|---|---|---|
| committer | 2018-08-01 00:16:54 -0400 | |
| commit | a9c921a41dec63f76f80df1f0d5dc3be40fa80de (patch) | |
| tree | 51e17454ad3e03e68aff05511e76681e8d5a93eb /src | |
| parent | Add missing includes and use const where applicable (diff) | |
| download | yuzu-a9c921a41dec63f76f80df1f0d5dc3be40fa80de.tar.gz yuzu-a9c921a41dec63f76f80df1f0d5dc3be40fa80de.tar.xz yuzu-a9c921a41dec63f76f80df1f0d5dc3be40fa80de.zip | |
Use ErrorEncrypted where applicable and fix no keys crash
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/file_sys/card_image.cpp | 1 | ||||
| -rw-r--r-- | src/core/file_sys/content_archive.cpp | 45 | ||||
| -rw-r--r-- | src/core/file_sys/content_archive.h | 4 | ||||
| -rw-r--r-- | src/core/loader/xci.cpp | 4 |
4 files changed, 37 insertions, 17 deletions
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) { | |||
| 45 | status = result; | 45 | status = result; |
| 46 | return; | 46 | return; |
| 47 | } | 47 | } |
| 48 | |||
| 48 | result = AddNCAFromPartition(XCIPartition::Update); | 49 | result = AddNCAFromPartition(XCIPartition::Update); |
| 49 | if (result != Loader::ResultStatus::Success) { | 50 | if (result != Loader::ResultStatus::Success) { |
| 50 | status = result; | 51 | 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 @@ | |||
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <utility> | 6 | #include <utility> |
| 7 | 7 | #include <boost/optional.hpp> | |
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "core/crypto/aes_util.h" | 9 | #include "core/crypto/aes_util.h" |
| 10 | #include "core/crypto/ctr_encryption_layer.h" | 10 | #include "core/crypto/ctr_encryption_layer.h" |
| @@ -76,13 +76,16 @@ bool IsValidNCA(const NCAHeader& header) { | |||
| 76 | return header.magic == Common::MakeMagic('N', 'C', 'A', '3'); | 76 | return header.magic == Common::MakeMagic('N', 'C', 'A', '3'); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | Core::Crypto::Key128 NCA::GetKeyAreaKey(NCASectionCryptoType type) const { | 79 | boost::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType type) const { |
| 80 | u8 master_key_id = header.crypto_type; | 80 | u8 master_key_id = header.crypto_type; |
| 81 | if (header.crypto_type_2 > master_key_id) | 81 | if (header.crypto_type_2 > master_key_id) |
| 82 | master_key_id = header.crypto_type_2; | 82 | master_key_id = header.crypto_type_2; |
| 83 | if (master_key_id > 0) | 83 | if (master_key_id > 0) |
| 84 | --master_key_id; | 84 | --master_key_id; |
| 85 | 85 | ||
| 86 | if (!keys.HasKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, header.key_index)) | ||
| 87 | return boost::none; | ||
| 88 | |||
| 86 | std::vector<u8> key_area(header.key_area.begin(), header.key_area.end()); | 89 | std::vector<u8> key_area(header.key_area.begin(), header.key_area.end()); |
| 87 | Core::Crypto::AESCipher<Core::Crypto::Key128> cipher( | 90 | Core::Crypto::AESCipher<Core::Crypto::Key128> cipher( |
| 88 | keys.GetKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, header.key_index), | 91 | 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 | |||
| 116 | case NCASectionCryptoType::CTR: | 119 | case NCASectionCryptoType::CTR: |
| 117 | LOG_DEBUG(Crypto, "called with mode=CTR, starting_offset={:016X}", starting_offset); | 120 | LOG_DEBUG(Crypto, "called with mode=CTR, starting_offset={:016X}", starting_offset); |
| 118 | { | 121 | { |
| 122 | const auto key = GetKeyAreaKey(NCASectionCryptoType::CTR); | ||
| 123 | if (key == boost::none) | ||
| 124 | return nullptr; | ||
| 119 | auto out = std::make_shared<Core::Crypto::CTREncryptionLayer>( | 125 | auto out = std::make_shared<Core::Crypto::CTREncryptionLayer>( |
| 120 | std::move(in), GetKeyAreaKey(NCASectionCryptoType::CTR), starting_offset); | 126 | std::move(in), key.value(), starting_offset); |
| 121 | std::vector<u8> iv(16); | 127 | std::vector<u8> iv(16); |
| 122 | for (u8 i = 0; i < 8; ++i) | 128 | for (u8 i = 0; i < 8; ++i) |
| 123 | iv[i] = header.raw.section_ctr[0x8 - i - 1]; | 129 | iv[i] = header.raw.section_ctr[0x8 - i - 1]; |
| 124 | out->SetIV(iv); | 130 | out->SetIV(iv); |
| 125 | return out; | 131 | return std::static_pointer_cast<VfsFile>(out); |
| 126 | } | 132 | } |
| 127 | case NCASectionCryptoType::XTS: | 133 | case NCASectionCryptoType::XTS: |
| 128 | // TODO(DarkLordZach): Implement XTSEncryptionLayer and title key encryption. | 134 | // TODO(DarkLordZach): Implement XTSEncryptionLayer and title key encryption. |
| @@ -149,7 +155,10 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) { | |||
| 149 | header = dec_header; | 155 | header = dec_header; |
| 150 | encrypted = true; | 156 | encrypted = true; |
| 151 | } else { | 157 | } else { |
| 152 | status = Loader::ResultStatus::ErrorInvalidFormat; | 158 | if (!keys.HasKey(Core::Crypto::S256KeyType::Header)) |
| 159 | status = Loader::ResultStatus::ErrorEncrypted; | ||
| 160 | else | ||
| 161 | status = Loader::ResultStatus::ErrorInvalidFormat; | ||
| 153 | return; | 162 | return; |
| 154 | } | 163 | } |
| 155 | } | 164 | } |
| @@ -179,23 +188,29 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) { | |||
| 179 | header.section_tables[i].media_offset * MEDIA_OFFSET_MULTIPLIER + | 188 | header.section_tables[i].media_offset * MEDIA_OFFSET_MULTIPLIER + |
| 180 | section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].offset; | 189 | section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].offset; |
| 181 | const size_t romfs_size = section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].size; | 190 | const size_t romfs_size = section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].size; |
| 182 | files.emplace_back( | 191 | const auto dec = |
| 183 | Decrypt(section, std::make_shared<OffsetVfsFile>(file, romfs_size, romfs_offset), | 192 | Decrypt(section, std::make_shared<OffsetVfsFile>(file, romfs_size, romfs_offset), |
| 184 | romfs_offset)); | 193 | romfs_offset); |
| 185 | romfs = files.back(); | 194 | if (dec != nullptr) { |
| 195 | files.emplace_back(); | ||
| 196 | romfs = files.back(); | ||
| 197 | } | ||
| 186 | } else if (section.raw.header.filesystem_type == NCASectionFilesystemType::PFS0) { | 198 | } else if (section.raw.header.filesystem_type == NCASectionFilesystemType::PFS0) { |
| 187 | u64 offset = (static_cast<u64>(header.section_tables[i].media_offset) * | 199 | u64 offset = (static_cast<u64>(header.section_tables[i].media_offset) * |
| 188 | MEDIA_OFFSET_MULTIPLIER) + | 200 | MEDIA_OFFSET_MULTIPLIER) + |
| 189 | section.pfs0.pfs0_header_offset; | 201 | section.pfs0.pfs0_header_offset; |
| 190 | u64 size = MEDIA_OFFSET_MULTIPLIER * (header.section_tables[i].media_end_offset - | 202 | u64 size = MEDIA_OFFSET_MULTIPLIER * (header.section_tables[i].media_end_offset - |
| 191 | header.section_tables[i].media_offset); | 203 | header.section_tables[i].media_offset); |
| 192 | auto npfs = std::make_shared<PartitionFilesystem>( | 204 | const auto dec = |
| 193 | Decrypt(section, std::make_shared<OffsetVfsFile>(file, size, offset), offset)); | 205 | Decrypt(section, std::make_shared<OffsetVfsFile>(file, size, offset), offset); |
| 194 | 206 | if (dec != nullptr) { | |
| 195 | if (npfs->GetStatus() == Loader::ResultStatus::Success) { | 207 | auto npfs = std::make_shared<PartitionFilesystem>(dec); |
| 196 | dirs.emplace_back(npfs); | 208 | |
| 197 | if (IsDirectoryExeFS(dirs.back())) | 209 | if (npfs->GetStatus() == Loader::ResultStatus::Success) { |
| 198 | exefs = dirs.back(); | 210 | dirs.emplace_back(npfs); |
| 211 | if (IsDirectoryExeFS(dirs.back())) | ||
| 212 | exefs = dirs.back(); | ||
| 213 | } | ||
| 199 | } | 214 | } |
| 200 | } | 215 | } |
| 201 | } | 216 | } |
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 @@ | |||
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | #include <string> | 9 | #include <string> |
| 10 | #include <vector> | 10 | #include <vector> |
| 11 | 11 | #include <boost/optional.hpp> | |
| 12 | #include "common/common_funcs.h" | 12 | #include "common/common_funcs.h" |
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "common/swap.h" | 14 | #include "common/swap.h" |
| @@ -95,7 +95,7 @@ protected: | |||
| 95 | bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; | 95 | bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; |
| 96 | 96 | ||
| 97 | private: | 97 | private: |
| 98 | Core::Crypto::Key128 GetKeyAreaKey(NCASectionCryptoType type) const; | 98 | boost::optional<Core::Crypto::Key128> GetKeyAreaKey(NCASectionCryptoType type) const; |
| 99 | VirtualFile Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset) const; | 99 | VirtualFile Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset) const; |
| 100 | 100 | ||
| 101 | std::vector<VirtualDir> dirs; | 101 | std::vector<VirtualDir> 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<Kernel::Process>& process) { | |||
| 48 | return ResultStatus::ErrorAlreadyLoaded; | 48 | return ResultStatus::ErrorAlreadyLoaded; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | if (xci->GetNCAFileByType(FileSys::NCAContentType::Program) == nullptr) { | ||
| 52 | return ResultStatus::ErrorEncrypted; | ||
| 53 | } | ||
| 54 | |||
| 51 | auto result = nca_loader->Load(process); | 55 | auto result = nca_loader->Load(process); |
| 52 | if (result != ResultStatus::Success) | 56 | if (result != ResultStatus::Success) |
| 53 | return result; | 57 | return result; |