diff options
| author | 2018-08-04 14:33:11 -0400 | |
|---|---|---|
| committer | 2018-08-04 14:33:11 -0400 | |
| commit | 2b06301dbfbfe79687219bf7783a6d1b47695401 (patch) | |
| tree | 222cc27ecbc7f7e86d2edef8d36436600dee7d7a /src/core/crypto/key_manager.h | |
| parent | Merge pull request #919 from lioncash/sign (diff) | |
| parent | Add missing parameter to files.push_back() (diff) | |
| download | yuzu-2b06301dbfbfe79687219bf7783a6d1b47695401.tar.gz yuzu-2b06301dbfbfe79687219bf7783a6d1b47695401.tar.xz yuzu-2b06301dbfbfe79687219bf7783a6d1b47695401.zip | |
Merge pull request #849 from DarkLordZach/xci
XCI and Encrypted NCA Support
Diffstat (limited to 'src/core/crypto/key_manager.h')
| -rw-r--r-- | src/core/crypto/key_manager.h | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h new file mode 100644 index 000000000..03152a12c --- /dev/null +++ b/src/core/crypto/key_manager.h | |||
| @@ -0,0 +1,119 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <type_traits> | ||
| 9 | #include <unordered_map> | ||
| 10 | #include <vector> | ||
| 11 | #include <fmt/format.h> | ||
| 12 | #include "common/common_types.h" | ||
| 13 | |||
| 14 | namespace Core::Crypto { | ||
| 15 | |||
| 16 | using Key128 = std::array<u8, 0x10>; | ||
| 17 | using Key256 = std::array<u8, 0x20>; | ||
| 18 | using SHA256Hash = std::array<u8, 0x20>; | ||
| 19 | |||
| 20 | static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big."); | ||
| 21 | static_assert(sizeof(Key256) == 32, "Key128 must be 128 bytes big."); | ||
| 22 | |||
| 23 | enum class S256KeyType : u64 { | ||
| 24 | Header, // | ||
| 25 | SDSave, // | ||
| 26 | SDNCA, // | ||
| 27 | }; | ||
| 28 | |||
| 29 | enum class S128KeyType : u64 { | ||
| 30 | Master, // f1=crypto revision | ||
| 31 | Package1, // f1=crypto revision | ||
| 32 | Package2, // f1=crypto revision | ||
| 33 | Titlekek, // f1=crypto revision | ||
| 34 | ETicketRSAKek, // | ||
| 35 | KeyArea, // f1=crypto revision f2=type {app, ocean, system} | ||
| 36 | SDSeed, // | ||
| 37 | Titlekey, // f1=rights id LSB f2=rights id MSB | ||
| 38 | }; | ||
| 39 | |||
| 40 | enum class KeyAreaKeyType : u8 { | ||
| 41 | Application, | ||
| 42 | Ocean, | ||
| 43 | System, | ||
| 44 | }; | ||
| 45 | |||
| 46 | template <typename KeyType> | ||
| 47 | struct KeyIndex { | ||
| 48 | KeyType type; | ||
| 49 | u64 field1; | ||
| 50 | u64 field2; | ||
| 51 | |||
| 52 | std::string DebugInfo() const { | ||
| 53 | u8 key_size = 16; | ||
| 54 | if constexpr (std::is_same_v<KeyType, S256KeyType>) | ||
| 55 | key_size = 32; | ||
| 56 | return fmt::format("key_size={:02X}, key={:02X}, field1={:016X}, field2={:016X}", key_size, | ||
| 57 | static_cast<u8>(type), field1, field2); | ||
| 58 | } | ||
| 59 | }; | ||
| 60 | |||
| 61 | // The following two (== and hash) are so KeyIndex can be a key in unordered_map | ||
| 62 | |||
| 63 | template <typename KeyType> | ||
| 64 | bool operator==(const KeyIndex<KeyType>& lhs, const KeyIndex<KeyType>& rhs) { | ||
| 65 | return std::tie(lhs.type, lhs.field1, lhs.field2) == std::tie(rhs.type, rhs.field1, rhs.field2); | ||
| 66 | } | ||
| 67 | |||
| 68 | template <typename KeyType> | ||
| 69 | bool operator!=(const KeyIndex<KeyType>& lhs, const KeyIndex<KeyType>& rhs) { | ||
| 70 | return !operator==(lhs, rhs); | ||
| 71 | } | ||
| 72 | |||
| 73 | } // namespace Core::Crypto | ||
| 74 | |||
| 75 | namespace std { | ||
| 76 | template <typename KeyType> | ||
| 77 | struct hash<Core::Crypto::KeyIndex<KeyType>> { | ||
| 78 | size_t operator()(const Core::Crypto::KeyIndex<KeyType>& k) const { | ||
| 79 | using std::hash; | ||
| 80 | |||
| 81 | return ((hash<u64>()(static_cast<u64>(k.type)) ^ (hash<u64>()(k.field1) << 1)) >> 1) ^ | ||
| 82 | (hash<u64>()(k.field2) << 1); | ||
| 83 | } | ||
| 84 | }; | ||
| 85 | } // namespace std | ||
| 86 | |||
| 87 | namespace Core::Crypto { | ||
| 88 | |||
| 89 | std::array<u8, 0x10> operator"" _array16(const char* str, size_t len); | ||
| 90 | std::array<u8, 0x20> operator"" _array32(const char* str, size_t len); | ||
| 91 | |||
| 92 | class KeyManager { | ||
| 93 | public: | ||
| 94 | KeyManager(); | ||
| 95 | |||
| 96 | bool HasKey(S128KeyType id, u64 field1 = 0, u64 field2 = 0) const; | ||
| 97 | bool HasKey(S256KeyType id, u64 field1 = 0, u64 field2 = 0) const; | ||
| 98 | |||
| 99 | Key128 GetKey(S128KeyType id, u64 field1 = 0, u64 field2 = 0) const; | ||
| 100 | Key256 GetKey(S256KeyType id, u64 field1 = 0, u64 field2 = 0) const; | ||
| 101 | |||
| 102 | void SetKey(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0); | ||
| 103 | void SetKey(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0); | ||
| 104 | |||
| 105 | static bool KeyFileExists(bool title); | ||
| 106 | |||
| 107 | private: | ||
| 108 | std::unordered_map<KeyIndex<S128KeyType>, Key128> s128_keys; | ||
| 109 | std::unordered_map<KeyIndex<S256KeyType>, Key256> s256_keys; | ||
| 110 | |||
| 111 | bool dev_mode; | ||
| 112 | void LoadFromFile(std::string_view filename, bool is_title_keys); | ||
| 113 | void AttemptLoadKeyFile(std::string_view dir1, std::string_view dir2, std::string_view filename, | ||
| 114 | bool title); | ||
| 115 | |||
| 116 | static const std::unordered_map<std::string, KeyIndex<S128KeyType>> s128_file_id; | ||
| 117 | static const std::unordered_map<std::string, KeyIndex<S256KeyType>> s256_file_id; | ||
| 118 | }; | ||
| 119 | } // namespace Core::Crypto | ||