diff options
Diffstat (limited to 'src/core/file_sys')
| -rw-r--r-- | src/core/file_sys/card_image.cpp | 15 | ||||
| -rw-r--r-- | src/core/file_sys/content_archive.cpp | 48 | ||||
| -rw-r--r-- | src/core/file_sys/content_archive.h | 5 | ||||
| -rw-r--r-- | src/core/file_sys/vfs.cpp | 7 |
4 files changed, 30 insertions, 45 deletions
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index 5ff09a362..3c1dbf46c 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp | |||
| @@ -30,8 +30,8 @@ XCI::XCI(VirtualFile file_) : file(std::move(file_)), partitions(0x4) { | |||
| 30 | return; | 30 | return; |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | const static std::array<std::string, 0x4> partition_names = {"update", "normal", "secure", | 33 | static constexpr std::array<const char*, 0x4> partition_names = {"update", "normal", "secure", |
| 34 | "logo"}; | 34 | "logo"}; |
| 35 | 35 | ||
| 36 | for (XCIPartition partition : | 36 | for (XCIPartition partition : |
| 37 | {XCIPartition::Update, XCIPartition::Normal, XCIPartition::Secure, XCIPartition::Logo}) { | 37 | {XCIPartition::Update, XCIPartition::Normal, XCIPartition::Secure, XCIPartition::Logo}) { |
| @@ -93,12 +93,9 @@ VirtualDir XCI::GetLogoPartition() const { | |||
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | std::shared_ptr<NCA> XCI::GetNCAByType(NCAContentType type) const { | 95 | std::shared_ptr<NCA> XCI::GetNCAByType(NCAContentType type) const { |
| 96 | for (const auto& nca : ncas) { | 96 | auto iter = std::find_if(ncas.begin(), ncas.end(), |
| 97 | if (nca->GetType() == type) | 97 | [type](std::shared_ptr<NCA> nca) { return nca->GetType() == type; }); |
| 98 | return nca; | 98 | return iter == ncas.end() ? nullptr : *iter; |
| 99 | } | ||
| 100 | |||
| 101 | return nullptr; | ||
| 102 | } | 99 | } |
| 103 | 100 | ||
| 104 | VirtualFile XCI::GetNCAFileByType(NCAContentType type) const { | 101 | VirtualFile XCI::GetNCAFileByType(NCAContentType type) const { |
| @@ -133,7 +130,7 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) { | |||
| 133 | return Loader::ResultStatus::ErrorInvalidFormat; | 130 | return Loader::ResultStatus::ErrorInvalidFormat; |
| 134 | } | 131 | } |
| 135 | 132 | ||
| 136 | for (VirtualFile file : partitions[static_cast<size_t>(part)]->GetFiles()) { | 133 | for (const VirtualFile& file : partitions[static_cast<size_t>(part)]->GetFiles()) { |
| 137 | if (file->GetExtension() != "nca") | 134 | if (file->GetExtension() != "nca") |
| 138 | continue; | 135 | continue; |
| 139 | auto nca = std::make_shared<NCA>(file); | 136 | auto nca = std::make_shared<NCA>(file); |
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index add01974e..952dc7068 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp | |||
| @@ -9,10 +9,9 @@ | |||
| 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" |
| 11 | #include "core/file_sys/content_archive.h" | 11 | #include "core/file_sys/content_archive.h" |
| 12 | #include "core/file_sys/romfs.h" | ||
| 12 | #include "core/file_sys/vfs_offset.h" | 13 | #include "core/file_sys/vfs_offset.h" |
| 13 | #include "core/loader/loader.h" | 14 | #include "core/loader/loader.h" |
| 14 | #include "mbedtls/cipher.h" | ||
| 15 | #include "romfs.h" | ||
| 16 | 15 | ||
| 17 | namespace FileSys { | 16 | namespace FileSys { |
| 18 | 17 | ||
| @@ -77,7 +76,7 @@ bool IsValidNCA(const NCAHeader& header) { | |||
| 77 | return header.magic == Common::MakeMagic('N', 'C', 'A', '3'); | 76 | return header.magic == Common::MakeMagic('N', 'C', 'A', '3'); |
| 78 | } | 77 | } |
| 79 | 78 | ||
| 80 | Crypto::Key128 NCA::GetKeyAreaKey(NCASectionCryptoType type) { | 79 | Core::Crypto::Key128 NCA::GetKeyAreaKey(NCASectionCryptoType type) { |
| 81 | u8 master_key_id = header.crypto_type; | 80 | u8 master_key_id = header.crypto_type; |
| 82 | if (header.crypto_type_2 > master_key_id) | 81 | if (header.crypto_type_2 > master_key_id) |
| 83 | master_key_id = header.crypto_type_2; | 82 | master_key_id = header.crypto_type_2; |
| @@ -85,16 +84,12 @@ Crypto::Key128 NCA::GetKeyAreaKey(NCASectionCryptoType type) { | |||
| 85 | --master_key_id; | 84 | --master_key_id; |
| 86 | 85 | ||
| 87 | std::vector<u8> key_area(header.key_area.begin(), header.key_area.end()); | 86 | std::vector<u8> key_area(header.key_area.begin(), header.key_area.end()); |
| 88 | if (!Crypto::keys.ValidateKey(Crypto::S128KeyType::KEY_AREA, master_key_id, header.key_index)) { | 87 | Core::Crypto::AESCipher<Core::Crypto::Key128> cipher( |
| 89 | status = Loader::ResultStatus::ErrorEncrypted; | 88 | keys.GetKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, header.key_index), |
| 90 | return {}; | 89 | Core::Crypto::Mode::ECB); |
| 91 | } | 90 | cipher.Transcode(key_area.data(), key_area.size(), key_area.data(), Core::Crypto::Op::Decrypt); |
| 92 | Crypto::AESCipher<Crypto::Key128> cipher( | ||
| 93 | Crypto::keys.GetKey(Crypto::S128KeyType::KEY_AREA, master_key_id, header.key_index), | ||
| 94 | Crypto::Mode::ECB); | ||
| 95 | cipher.Transcode(key_area.data(), key_area.size(), key_area.data(), Crypto::Op::DECRYPT); | ||
| 96 | 91 | ||
| 97 | Crypto::Key128 out; | 92 | Core::Crypto::Key128 out; |
| 98 | if (type == NCASectionCryptoType::XTS) | 93 | if (type == NCASectionCryptoType::XTS) |
| 99 | std::copy(key_area.begin(), key_area.begin() + 0x10, out.begin()); | 94 | std::copy(key_area.begin(), key_area.begin() + 0x10, out.begin()); |
| 100 | else if (type == NCASectionCryptoType::CTR) | 95 | else if (type == NCASectionCryptoType::CTR) |
| @@ -102,8 +97,8 @@ Crypto::Key128 NCA::GetKeyAreaKey(NCASectionCryptoType type) { | |||
| 102 | else | 97 | else |
| 103 | LOG_CRITICAL(Crypto, "Called GetKeyAreaKey on invalid NCASectionCryptoType type={:02X}", | 98 | LOG_CRITICAL(Crypto, "Called GetKeyAreaKey on invalid NCASectionCryptoType type={:02X}", |
| 104 | static_cast<u8>(type)); | 99 | static_cast<u8>(type)); |
| 105 | 100 | u128 out_128{}; | |
| 106 | u128 out_128 = *reinterpret_cast<u128*>(&out); | 101 | memcpy(out_128.data(), out.data(), 16); |
| 107 | LOG_DEBUG(Crypto, "called with crypto_rev={:02X}, kak_index={:02X}, key={:016X}{:016X}", | 102 | LOG_DEBUG(Crypto, "called with crypto_rev={:02X}, kak_index={:02X}, key={:016X}{:016X}", |
| 108 | master_key_id, header.key_index, out_128[1], out_128[0]); | 103 | master_key_id, header.key_index, out_128[1], out_128[0]); |
| 109 | 104 | ||
| @@ -121,9 +116,9 @@ VirtualFile NCA::Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_o | |||
| 121 | case NCASectionCryptoType::CTR: | 116 | case NCASectionCryptoType::CTR: |
| 122 | LOG_DEBUG(Crypto, "called with mode=CTR, starting_offset={:016X}", starting_offset); | 117 | LOG_DEBUG(Crypto, "called with mode=CTR, starting_offset={:016X}", starting_offset); |
| 123 | { | 118 | { |
| 124 | auto out = std::make_shared<Crypto::CTREncryptionLayer>( | 119 | auto out = std::make_shared<Core::Crypto::CTREncryptionLayer>( |
| 125 | std::move(in), GetKeyAreaKey(NCASectionCryptoType::CTR), starting_offset); | 120 | std::move(in), GetKeyAreaKey(NCASectionCryptoType::CTR), starting_offset); |
| 126 | std::vector<u8> iv(16, 0); | 121 | std::vector<u8> iv(16); |
| 127 | for (u8 i = 0; i < 8; ++i) | 122 | for (u8 i = 0; i < 8; ++i) |
| 128 | iv[i] = header.raw.section_ctr[0x8 - i - 1]; | 123 | iv[i] = header.raw.section_ctr[0x8 - i - 1]; |
| 129 | out->SetIV(iv); | 124 | out->SetIV(iv); |
| @@ -146,13 +141,10 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) { | |||
| 146 | 141 | ||
| 147 | if (!IsValidNCA(header)) { | 142 | if (!IsValidNCA(header)) { |
| 148 | NCAHeader dec_header{}; | 143 | NCAHeader dec_header{}; |
| 149 | if (!Crypto::keys.ValidateKey(Crypto::S256KeyType::HEADER)) { | 144 | Core::Crypto::AESCipher<Core::Crypto::Key256> cipher( |
| 150 | status = Loader::ResultStatus::ErrorEncrypted; | 145 | keys.GetKey(Core::Crypto::S256KeyType::Header), Core::Crypto::Mode::XTS); |
| 151 | return; | 146 | cipher.XTSTranscode(&header, sizeof(NCAHeader), &dec_header, 0, 0x200, |
| 152 | } | 147 | Core::Crypto::Op::Decrypt); |
| 153 | Crypto::AESCipher<Crypto::Key256> cipher(Crypto::keys.GetKey(Crypto::S256KeyType::HEADER), | ||
| 154 | Crypto::Mode::XTS); | ||
| 155 | cipher.XTSTranscode(&header, sizeof(NCAHeader), &dec_header, 0, 0x200, Crypto::Op::DECRYPT); | ||
| 156 | if (IsValidNCA(dec_header)) { | 148 | if (IsValidNCA(dec_header)) { |
| 157 | header = dec_header; | 149 | header = dec_header; |
| 158 | encrypted = true; | 150 | encrypted = true; |
| @@ -171,14 +163,10 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) { | |||
| 171 | 163 | ||
| 172 | if (encrypted) { | 164 | if (encrypted) { |
| 173 | auto raw = file->ReadBytes(length_sections, SECTION_HEADER_OFFSET); | 165 | auto raw = file->ReadBytes(length_sections, SECTION_HEADER_OFFSET); |
| 174 | if (!Crypto::keys.ValidateKey(Crypto::S256KeyType::HEADER)) { | 166 | Core::Crypto::AESCipher<Core::Crypto::Key256> cipher( |
| 175 | status = Loader::ResultStatus::ErrorEncrypted; | 167 | keys.GetKey(Core::Crypto::S256KeyType::Header), Core::Crypto::Mode::XTS); |
| 176 | return; | ||
| 177 | } | ||
| 178 | Crypto::AESCipher<Crypto::Key256> cipher(Crypto::keys.GetKey(Crypto::S256KeyType::HEADER), | ||
| 179 | Crypto::Mode::XTS); | ||
| 180 | cipher.XTSTranscode(raw.data(), length_sections, sections.data(), 2, SECTION_HEADER_SIZE, | 168 | cipher.XTSTranscode(raw.data(), length_sections, sections.data(), 2, SECTION_HEADER_SIZE, |
| 181 | Crypto::Op::DECRYPT); | 169 | Core::Crypto::Op::Decrypt); |
| 182 | } else { | 170 | } else { |
| 183 | file->ReadBytes(sections.data(), length_sections, SECTION_HEADER_OFFSET); | 171 | file->ReadBytes(sections.data(), length_sections, SECTION_HEADER_OFFSET); |
| 184 | } | 172 | } |
diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h index d9ad3bf7e..153142b06 100644 --- a/src/core/file_sys/content_archive.h +++ b/src/core/file_sys/content_archive.h | |||
| @@ -9,12 +9,12 @@ | |||
| 9 | #include <string> | 9 | #include <string> |
| 10 | #include <vector> | 10 | #include <vector> |
| 11 | 11 | ||
| 12 | #include "core/loader/loader.h" | ||
| 13 | #include "common/common_funcs.h" | 12 | #include "common/common_funcs.h" |
| 14 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 15 | #include "common/swap.h" | 14 | #include "common/swap.h" |
| 16 | #include "core/crypto/key_manager.h" | 15 | #include "core/crypto/key_manager.h" |
| 17 | #include "core/file_sys/partition_filesystem.h" | 16 | #include "core/file_sys/partition_filesystem.h" |
| 17 | #include "core/loader/loader.h" | ||
| 18 | 18 | ||
| 19 | namespace FileSys { | 19 | namespace FileSys { |
| 20 | enum class NCAContentType : u8 { | 20 | enum class NCAContentType : u8 { |
| @@ -107,7 +107,8 @@ private: | |||
| 107 | 107 | ||
| 108 | bool encrypted; | 108 | bool encrypted; |
| 109 | 109 | ||
| 110 | Crypto::Key128 GetKeyAreaKey(NCASectionCryptoType type); | 110 | Core::Crypto::KeyManager keys; |
| 111 | Core::Crypto::Key128 GetKeyAreaKey(NCASectionCryptoType type); | ||
| 111 | 112 | ||
| 112 | VirtualFile Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset); | 113 | VirtualFile Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset); |
| 113 | }; | 114 | }; |
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp index 57d0aeb85..dae1c16ef 100644 --- a/src/core/file_sys/vfs.cpp +++ b/src/core/file_sys/vfs.cpp | |||
| @@ -297,10 +297,9 @@ bool DeepEquals(const VirtualFile& file1, const VirtualFile& file2, size_t block | |||
| 297 | 297 | ||
| 298 | if (f1_vs != f2_vs) | 298 | if (f1_vs != f2_vs) |
| 299 | return false; | 299 | return false; |
| 300 | for (size_t j = 0; j < f1_vs; ++j) { | 300 | auto iters = std::mismatch(f1_v.begin(), f1_v.end(), f2_v.begin(), f2_v.end()); |
| 301 | if (f1_v[j] != f2_v[j]) | 301 | if (iters.first != f1_v.end() && iters.second != f2_v.end()) |
| 302 | return false; | 302 | return false; |
| 303 | } | ||
| 304 | } | 303 | } |
| 305 | 304 | ||
| 306 | return true; | 305 | return true; |