diff options
| -rw-r--r-- | src/core/crypto/aes_util.h | 7 | ||||
| -rw-r--r-- | src/core/crypto/ctr_encryption_layer.cpp | 7 | ||||
| -rw-r--r-- | src/core/crypto/ctr_encryption_layer.h | 1 | ||||
| -rw-r--r-- | src/core/crypto/encryption_layer.h | 3 | ||||
| -rw-r--r-- | src/core/crypto/key_manager.cpp | 13 | ||||
| -rw-r--r-- | src/core/crypto/key_manager.h | 7 | ||||
| -rw-r--r-- | src/core/file_sys/card_image.cpp | 5 | ||||
| -rw-r--r-- | src/core/file_sys/card_image.h | 3 | ||||
| -rw-r--r-- | src/core/file_sys/content_archive.cpp | 4 | ||||
| -rw-r--r-- | src/core/file_sys/content_archive.h | 11 | ||||
| -rw-r--r-- | src/core/loader/xci.h | 3 |
11 files changed, 40 insertions, 24 deletions
diff --git a/src/core/crypto/aes_util.h b/src/core/crypto/aes_util.h index fa77d5560..5b0b02738 100644 --- a/src/core/crypto/aes_util.h +++ b/src/core/crypto/aes_util.h | |||
| @@ -4,11 +4,16 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | ||
| 8 | #include <type_traits> | ||
| 9 | #include <vector> | ||
| 7 | #include "common/assert.h" | 10 | #include "common/assert.h" |
| 8 | #include "core/file_sys/vfs.h" | 11 | #include "core/file_sys/vfs.h" |
| 9 | 12 | ||
| 10 | namespace Core::Crypto { | 13 | namespace Core::Crypto { |
| 11 | 14 | ||
| 15 | struct CipherContext; | ||
| 16 | |||
| 12 | enum class Mode { | 17 | enum class Mode { |
| 13 | CTR = 11, | 18 | CTR = 11, |
| 14 | ECB = 2, | 19 | ECB = 2, |
| @@ -20,8 +25,6 @@ enum class Op { | |||
| 20 | Decrypt, | 25 | Decrypt, |
| 21 | }; | 26 | }; |
| 22 | 27 | ||
| 23 | struct CipherContext; | ||
| 24 | |||
| 25 | template <typename Key, size_t KeySize = sizeof(Key)> | 28 | template <typename Key, size_t KeySize = sizeof(Key)> |
| 26 | class AESCipher { | 29 | class AESCipher { |
| 27 | static_assert(std::is_same_v<Key, std::array<u8, KeySize>>, "Key must be std::array of u8."); | 30 | static_assert(std::is_same_v<Key, std::array<u8, KeySize>>, "Key must be std::array of u8."); |
diff --git a/src/core/crypto/ctr_encryption_layer.cpp b/src/core/crypto/ctr_encryption_layer.cpp index 5dbc257e5..106db02b3 100644 --- a/src/core/crypto/ctr_encryption_layer.cpp +++ b/src/core/crypto/ctr_encryption_layer.cpp | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <string.h> | 5 | #include <cstring> |
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "core/crypto/ctr_encryption_layer.h" | 7 | #include "core/crypto/ctr_encryption_layer.h" |
| 8 | 8 | ||
| @@ -33,11 +33,10 @@ size_t CTREncryptionLayer::Read(u8* data, size_t length, size_t offset) const { | |||
| 33 | size_t read = 0x10 - sector_offset; | 33 | size_t read = 0x10 - sector_offset; |
| 34 | 34 | ||
| 35 | if (length + sector_offset < 0x10) { | 35 | if (length + sector_offset < 0x10) { |
| 36 | memcpy(data, block.data() + sector_offset, std::min<u64>(length, read)); | 36 | std::memcpy(data, block.data() + sector_offset, std::min<u64>(length, read)); |
| 37 | return read; | 37 | return read; |
| 38 | } | 38 | } |
| 39 | 39 | std::memcpy(data, block.data() + sector_offset, read); | |
| 40 | memcpy(data, block.data() + sector_offset, read); | ||
| 41 | return read + Read(data + read, length - read, offset + read); | 40 | return read + Read(data + read, length - read, offset + read); |
| 42 | } | 41 | } |
| 43 | 42 | ||
diff --git a/src/core/crypto/ctr_encryption_layer.h b/src/core/crypto/ctr_encryption_layer.h index 697d7c6a5..11b8683c7 100644 --- a/src/core/crypto/ctr_encryption_layer.h +++ b/src/core/crypto/ctr_encryption_layer.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <vector> | ||
| 7 | #include "core/crypto/aes_util.h" | 8 | #include "core/crypto/aes_util.h" |
| 8 | #include "core/crypto/encryption_layer.h" | 9 | #include "core/crypto/encryption_layer.h" |
| 9 | #include "core/crypto/key_manager.h" | 10 | #include "core/crypto/key_manager.h" |
diff --git a/src/core/crypto/encryption_layer.h b/src/core/crypto/encryption_layer.h index 84f11bf5e..71bca1f23 100644 --- a/src/core/crypto/encryption_layer.h +++ b/src/core/crypto/encryption_layer.h | |||
| @@ -10,7 +10,8 @@ namespace Core::Crypto { | |||
| 10 | 10 | ||
| 11 | // Basically non-functional class that implements all of the methods that are irrelevant to an | 11 | // Basically non-functional class that implements all of the methods that are irrelevant to an |
| 12 | // EncryptionLayer. Reduces duplicate code. | 12 | // EncryptionLayer. Reduces duplicate code. |
| 13 | struct EncryptionLayer : public FileSys::VfsFile { | 13 | class EncryptionLayer : public FileSys::VfsFile { |
| 14 | public: | ||
| 14 | explicit EncryptionLayer(FileSys::VirtualFile base); | 15 | explicit EncryptionLayer(FileSys::VirtualFile base); |
| 15 | 16 | ||
| 16 | size_t Read(u8* data, size_t length, size_t offset) const override = 0; | 17 | size_t Read(u8* data, size_t length, size_t offset) const override = 0; |
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index dea092b5e..33633de7e 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp | |||
| @@ -2,9 +2,11 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <array> | ||
| 5 | #include <fstream> | 6 | #include <fstream> |
| 6 | #include <locale> | 7 | #include <locale> |
| 7 | #include <sstream> | 8 | #include <sstream> |
| 9 | #include <string_view> | ||
| 8 | #include <mbedtls/sha256.h> | 10 | #include <mbedtls/sha256.h> |
| 9 | #include "common/assert.h" | 11 | #include "common/assert.h" |
| 10 | #include "common/common_paths.h" | 12 | #include "common/common_paths.h" |
| @@ -86,17 +88,18 @@ void KeyManager::LoadFromFile(std::string_view filename_, bool is_title_keys) { | |||
| 86 | 88 | ||
| 87 | if (is_title_keys) { | 89 | if (is_title_keys) { |
| 88 | auto rights_id_raw = HexStringToArray<16>(out[0]); | 90 | auto rights_id_raw = HexStringToArray<16>(out[0]); |
| 89 | u128 rights_id = *reinterpret_cast<std::array<u64, 2>*>(&rights_id_raw); | 91 | u128 rights_id{}; |
| 92 | std::memcpy(rights_id.data(), rights_id_raw.data(), rights_id_raw.size()); | ||
| 90 | Key128 key = HexStringToArray<16>(out[1]); | 93 | Key128 key = HexStringToArray<16>(out[1]); |
| 91 | SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]); | 94 | SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]); |
| 92 | } else { | 95 | } else { |
| 93 | std::transform(out[0].begin(), out[0].end(), out[0].begin(), ::tolower); | 96 | std::transform(out[0].begin(), out[0].end(), out[0].begin(), ::tolower); |
| 94 | if (s128_file_id.find(out[0]) != s128_file_id.end()) { | 97 | if (s128_file_id.find(out[0]) != s128_file_id.end()) { |
| 95 | const auto index = s128_file_id[out[0]]; | 98 | const auto index = s128_file_id.at(out[0]); |
| 96 | Key128 key = HexStringToArray<16>(out[1]); | 99 | Key128 key = HexStringToArray<16>(out[1]); |
| 97 | SetKey(index.type, key, index.field1, index.field2); | 100 | SetKey(index.type, key, index.field1, index.field2); |
| 98 | } else if (s256_file_id.find(out[0]) != s256_file_id.end()) { | 101 | } else if (s256_file_id.find(out[0]) != s256_file_id.end()) { |
| 99 | const auto index = s256_file_id[out[0]]; | 102 | const auto index = s256_file_id.at(out[0]); |
| 100 | Key256 key = HexStringToArray<32>(out[1]); | 103 | Key256 key = HexStringToArray<32>(out[1]); |
| 101 | SetKey(index.type, key, index.field1, index.field2); | 104 | SetKey(index.type, key, index.field1, index.field2); |
| 102 | } | 105 | } |
| @@ -143,7 +146,7 @@ void KeyManager::SetKey(S256KeyType id, Key256 key, u64 field1, u64 field2) { | |||
| 143 | s256_keys[{id, field1, field2}] = key; | 146 | s256_keys[{id, field1, field2}] = key; |
| 144 | } | 147 | } |
| 145 | 148 | ||
| 146 | std::unordered_map<std::string, KeyIndex<S128KeyType>> KeyManager::s128_file_id = { | 149 | const std::unordered_map<std::string, KeyIndex<S128KeyType>> KeyManager::s128_file_id = { |
| 147 | {"master_key_00", {S128KeyType::Master, 0, 0}}, | 150 | {"master_key_00", {S128KeyType::Master, 0, 0}}, |
| 148 | {"master_key_01", {S128KeyType::Master, 1, 0}}, | 151 | {"master_key_01", {S128KeyType::Master, 1, 0}}, |
| 149 | {"master_key_02", {S128KeyType::Master, 2, 0}}, | 152 | {"master_key_02", {S128KeyType::Master, 2, 0}}, |
| @@ -187,7 +190,7 @@ std::unordered_map<std::string, KeyIndex<S128KeyType>> KeyManager::s128_file_id | |||
| 187 | {"key_area_key_system_04", {S128KeyType::KeyArea, 4, static_cast<u64>(KeyAreaKeyType::System)}}, | 190 | {"key_area_key_system_04", {S128KeyType::KeyArea, 4, static_cast<u64>(KeyAreaKeyType::System)}}, |
| 188 | }; | 191 | }; |
| 189 | 192 | ||
| 190 | std::unordered_map<std::string, KeyIndex<S256KeyType>> KeyManager::s256_file_id = { | 193 | const std::unordered_map<std::string, KeyIndex<S256KeyType>> KeyManager::s256_file_id = { |
| 191 | {"header_key", {S256KeyType::Header, 0, 0}}, | 194 | {"header_key", {S256KeyType::Header, 0, 0}}, |
| 192 | {"sd_card_save_key", {S256KeyType::SDSave, 0, 0}}, | 195 | {"sd_card_save_key", {S256KeyType::SDSave, 0, 0}}, |
| 193 | {"sd_card_nca_key", {S256KeyType::SDNCA, 0, 0}}, | 196 | {"sd_card_nca_key", {S256KeyType::SDNCA, 0, 0}}, |
diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h index a52ea4cb9..28a560a3f 100644 --- a/src/core/crypto/key_manager.h +++ b/src/core/crypto/key_manager.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <type_traits> | ||
| 8 | #include <unordered_map> | 9 | #include <unordered_map> |
| 9 | #include <vector> | 10 | #include <vector> |
| 10 | #include <fmt/format.h> | 11 | #include <fmt/format.h> |
| @@ -50,7 +51,7 @@ struct KeyIndex { | |||
| 50 | 51 | ||
| 51 | std::string DebugInfo() const { | 52 | std::string DebugInfo() const { |
| 52 | u8 key_size = 16; | 53 | u8 key_size = 16; |
| 53 | if (std::is_same_v<KeyType, S256KeyType>) | 54 | if constexpr (std::is_same_v<KeyType, S256KeyType>) |
| 54 | key_size = 32; | 55 | key_size = 32; |
| 55 | return fmt::format("key_size={:02X}, key={:02X}, field1={:016X}, field2={:016X}", key_size, | 56 | return fmt::format("key_size={:02X}, key={:02X}, field1={:016X}, field2={:016X}", key_size, |
| 56 | static_cast<u8>(type), field1, field2); | 57 | static_cast<u8>(type), field1, field2); |
| @@ -110,7 +111,7 @@ private: | |||
| 110 | void AttemptLoadKeyFile(std::string_view dir1, std::string_view dir2, std::string_view filename, | 111 | void AttemptLoadKeyFile(std::string_view dir1, std::string_view dir2, std::string_view filename, |
| 111 | bool title); | 112 | bool title); |
| 112 | 113 | ||
| 113 | static std::unordered_map<std::string, KeyIndex<S128KeyType>> s128_file_id; | 114 | const static std::unordered_map<std::string, KeyIndex<S128KeyType>> s128_file_id; |
| 114 | static std::unordered_map<std::string, KeyIndex<S256KeyType>> s256_file_id; | 115 | const static std::unordered_map<std::string, KeyIndex<S256KeyType>> s256_file_id; |
| 115 | }; | 116 | }; |
| 116 | } // namespace Core::Crypto | 117 | } // namespace Core::Crypto |
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index 3c1dbf46c..c69812455 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp | |||
| @@ -93,8 +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 | auto iter = std::find_if(ncas.begin(), ncas.end(), | 96 | const auto iter = |
| 97 | [type](std::shared_ptr<NCA> nca) { return nca->GetType() == type; }); | 97 | std::find_if(ncas.begin(), ncas.end(), |
| 98 | [type](const std::shared_ptr<NCA>& nca) { return nca->GetType() == type; }); | ||
| 98 | return iter == ncas.end() ? nullptr : *iter; | 99 | return iter == ncas.end() ? nullptr : *iter; |
| 99 | } | 100 | } |
| 100 | 101 | ||
diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h index b765c8bc1..e089d737c 100644 --- a/src/core/file_sys/card_image.h +++ b/src/core/file_sys/card_image.h | |||
| @@ -4,10 +4,13 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | ||
| 7 | #include <vector> | 8 | #include <vector> |
| 9 | #include "common/common_types.h" | ||
| 8 | #include "common/swap.h" | 10 | #include "common/swap.h" |
| 9 | #include "core/file_sys/content_archive.h" | 11 | #include "core/file_sys/content_archive.h" |
| 10 | #include "core/file_sys/vfs.h" | 12 | #include "core/file_sys/vfs.h" |
| 13 | #include "core/loader/loader.h" | ||
| 11 | 14 | ||
| 12 | namespace FileSys { | 15 | namespace FileSys { |
| 13 | 16 | ||
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 952dc7068..9eceaa4c4 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp | |||
| @@ -76,7 +76,7 @@ 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) { | 79 | 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; |
| @@ -105,7 +105,7 @@ Core::Crypto::Key128 NCA::GetKeyAreaKey(NCASectionCryptoType type) { | |||
| 105 | return out; | 105 | return out; |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | VirtualFile NCA::Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset) { | 108 | VirtualFile NCA::Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset) const { |
| 109 | if (!encrypted) | 109 | if (!encrypted) |
| 110 | return in; | 110 | return in; |
| 111 | 111 | ||
diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h index 153142b06..e68ab0235 100644 --- a/src/core/file_sys/content_archive.h +++ b/src/core/file_sys/content_archive.h | |||
| @@ -17,6 +17,9 @@ | |||
| 17 | #include "core/loader/loader.h" | 17 | #include "core/loader/loader.h" |
| 18 | 18 | ||
| 19 | namespace FileSys { | 19 | namespace FileSys { |
| 20 | |||
| 21 | union NCASectionHeader; | ||
| 22 | |||
| 20 | enum class NCAContentType : u8 { | 23 | enum class NCAContentType : u8 { |
| 21 | Program = 0, | 24 | Program = 0, |
| 22 | Meta = 1, | 25 | Meta = 1, |
| @@ -61,8 +64,6 @@ struct NCAHeader { | |||
| 61 | }; | 64 | }; |
| 62 | static_assert(sizeof(NCAHeader) == 0x400, "NCAHeader has incorrect size."); | 65 | static_assert(sizeof(NCAHeader) == 0x400, "NCAHeader has incorrect size."); |
| 63 | 66 | ||
| 64 | union NCASectionHeader; | ||
| 65 | |||
| 66 | inline bool IsDirectoryExeFS(const std::shared_ptr<VfsDirectory>& pfs) { | 67 | inline bool IsDirectoryExeFS(const std::shared_ptr<VfsDirectory>& pfs) { |
| 67 | // According to switchbrew, an exefs must only contain these two files: | 68 | // According to switchbrew, an exefs must only contain these two files: |
| 68 | return pfs->GetFile("main") != nullptr && pfs->GetFile("main.npdm") != nullptr; | 69 | return pfs->GetFile("main") != nullptr && pfs->GetFile("main.npdm") != nullptr; |
| @@ -94,6 +95,9 @@ protected: | |||
| 94 | bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; | 95 | bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; |
| 95 | 96 | ||
| 96 | private: | 97 | private: |
| 98 | Core::Crypto::Key128 GetKeyAreaKey(NCASectionCryptoType type) const; | ||
| 99 | VirtualFile Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset) const; | ||
| 100 | |||
| 97 | std::vector<VirtualDir> dirs; | 101 | std::vector<VirtualDir> dirs; |
| 98 | std::vector<VirtualFile> files; | 102 | std::vector<VirtualFile> files; |
| 99 | 103 | ||
| @@ -108,9 +112,6 @@ private: | |||
| 108 | bool encrypted; | 112 | bool encrypted; |
| 109 | 113 | ||
| 110 | Core::Crypto::KeyManager keys; | 114 | Core::Crypto::KeyManager keys; |
| 111 | Core::Crypto::Key128 GetKeyAreaKey(NCASectionCryptoType type); | ||
| 112 | |||
| 113 | VirtualFile Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset); | ||
| 114 | }; | 115 | }; |
| 115 | 116 | ||
| 116 | } // namespace FileSys | 117 | } // namespace FileSys |
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h index 2a09caa5f..0dbcfbdf8 100644 --- a/src/core/loader/xci.h +++ b/src/core/loader/xci.h | |||
| @@ -4,7 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | ||
| 8 | #include "common/common_types.h" | ||
| 7 | #include "core/file_sys/card_image.h" | 9 | #include "core/file_sys/card_image.h" |
| 10 | #include "core/loader/loader.h" | ||
| 8 | #include "core/loader/nca.h" | 11 | #include "core/loader/nca.h" |
| 9 | 12 | ||
| 10 | namespace Loader { | 13 | namespace Loader { |