diff options
Diffstat (limited to 'src/core/crypto/key_manager.h')
| -rw-r--r-- | src/core/crypto/key_manager.h | 104 |
1 files changed, 93 insertions, 11 deletions
diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h index 978eec8dc..a41abbdfc 100644 --- a/src/core/crypto/key_manager.h +++ b/src/core/crypto/key_manager.h | |||
| @@ -5,11 +5,18 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <map> | ||
| 8 | #include <string> | 9 | #include <string> |
| 9 | #include <boost/container/flat_map.hpp> | 10 | #include <boost/container/flat_map.hpp> |
| 10 | #include <boost/optional.hpp> | 11 | #include <boost/optional.hpp> |
| 11 | #include <fmt/format.h> | 12 | #include <fmt/format.h> |
| 12 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "core/crypto/partition_data_manager.h" | ||
| 15 | #include "core/file_sys/vfs_types.h" | ||
| 16 | |||
| 17 | namespace FileUtil { | ||
| 18 | class IOFile; | ||
| 19 | } | ||
| 13 | 20 | ||
| 14 | namespace Loader { | 21 | namespace Loader { |
| 15 | enum class ResultStatus : u16; | 22 | enum class ResultStatus : u16; |
| @@ -22,13 +29,30 @@ constexpr u64 TICKET_FILE_TITLEKEY_OFFSET = 0x180; | |||
| 22 | using Key128 = std::array<u8, 0x10>; | 29 | using Key128 = std::array<u8, 0x10>; |
| 23 | using Key256 = std::array<u8, 0x20>; | 30 | using Key256 = std::array<u8, 0x20>; |
| 24 | using SHA256Hash = std::array<u8, 0x20>; | 31 | using SHA256Hash = std::array<u8, 0x20>; |
| 32 | using TicketRaw = std::array<u8, 0x400>; | ||
| 25 | 33 | ||
| 26 | static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big."); | 34 | static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big."); |
| 27 | static_assert(sizeof(Key256) == 32, "Key128 must be 128 bytes big."); | 35 | static_assert(sizeof(Key256) == 32, "Key256 must be 256 bytes big."); |
| 36 | |||
| 37 | template <size_t bit_size, size_t byte_size = (bit_size >> 3)> | ||
| 38 | struct RSAKeyPair { | ||
| 39 | std::array<u8, byte_size> encryption_key; | ||
| 40 | std::array<u8, byte_size> decryption_key; | ||
| 41 | std::array<u8, byte_size> modulus; | ||
| 42 | std::array<u8, 4> exponent; | ||
| 43 | }; | ||
| 44 | |||
| 45 | enum class KeyCategory : u8 { | ||
| 46 | Standard, | ||
| 47 | Title, | ||
| 48 | Console, | ||
| 49 | }; | ||
| 28 | 50 | ||
| 29 | enum class S256KeyType : u64 { | 51 | enum class S256KeyType : u64 { |
| 30 | Header, // | 52 | SDKey, // f1=SDKeyType |
| 31 | SDKeySource, // f1=SDKeyType | 53 | Header, // |
| 54 | SDKeySource, // f1=SDKeyType | ||
| 55 | HeaderSource, // | ||
| 32 | }; | 56 | }; |
| 33 | 57 | ||
| 34 | enum class S128KeyType : u64 { | 58 | enum class S128KeyType : u64 { |
| @@ -41,6 +65,14 @@ enum class S128KeyType : u64 { | |||
| 41 | SDSeed, // | 65 | SDSeed, // |
| 42 | Titlekey, // f1=rights id LSB f2=rights id MSB | 66 | Titlekey, // f1=rights id LSB f2=rights id MSB |
| 43 | Source, // f1=source type, f2= sub id | 67 | Source, // f1=source type, f2= sub id |
| 68 | Keyblob, // f1=crypto revision | ||
| 69 | KeyblobMAC, // f1=crypto revision | ||
| 70 | TSEC, // | ||
| 71 | SecureBoot, // | ||
| 72 | BIS, // f1=partition (0-3), f2=type {crypt, tweak} | ||
| 73 | HeaderKek, // | ||
| 74 | SDKek, // | ||
| 75 | RSAKek, // | ||
| 44 | }; | 76 | }; |
| 45 | 77 | ||
| 46 | enum class KeyAreaKeyType : u8 { | 78 | enum class KeyAreaKeyType : u8 { |
| @@ -50,9 +82,19 @@ enum class KeyAreaKeyType : u8 { | |||
| 50 | }; | 82 | }; |
| 51 | 83 | ||
| 52 | enum class SourceKeyType : u8 { | 84 | enum class SourceKeyType : u8 { |
| 53 | SDKEK, | 85 | SDKek, // |
| 54 | AESKEKGeneration, | 86 | AESKekGeneration, // |
| 55 | AESKeyGeneration, | 87 | AESKeyGeneration, // |
| 88 | RSAOaepKekGeneration, // | ||
| 89 | Master, // | ||
| 90 | Keyblob, // f2=crypto revision | ||
| 91 | KeyAreaKey, // f2=KeyAreaKeyType | ||
| 92 | Titlekek, // | ||
| 93 | Package2, // | ||
| 94 | HeaderKek, // | ||
| 95 | KeyblobMAC, // | ||
| 96 | ETicketKek, // | ||
| 97 | ETicketKekek, // | ||
| 56 | }; | 98 | }; |
| 57 | 99 | ||
| 58 | enum class SDKeyType : u8 { | 100 | enum class SDKeyType : u8 { |
| @@ -60,6 +102,16 @@ enum class SDKeyType : u8 { | |||
| 60 | NCA, | 102 | NCA, |
| 61 | }; | 103 | }; |
| 62 | 104 | ||
| 105 | enum class BISKeyType : u8 { | ||
| 106 | Crypto, | ||
| 107 | Tweak, | ||
| 108 | }; | ||
| 109 | |||
| 110 | enum class RSAKekType : u8 { | ||
| 111 | Mask0, | ||
| 112 | Seed3, | ||
| 113 | }; | ||
| 114 | |||
| 63 | template <typename KeyType> | 115 | template <typename KeyType> |
| 64 | struct KeyIndex { | 116 | struct KeyIndex { |
| 65 | KeyType type; | 117 | KeyType type; |
| @@ -91,6 +143,8 @@ public: | |||
| 91 | Key128 GetKey(S128KeyType id, u64 field1 = 0, u64 field2 = 0) const; | 143 | Key128 GetKey(S128KeyType id, u64 field1 = 0, u64 field2 = 0) const; |
| 92 | Key256 GetKey(S256KeyType id, u64 field1 = 0, u64 field2 = 0) const; | 144 | Key256 GetKey(S256KeyType id, u64 field1 = 0, u64 field2 = 0) const; |
| 93 | 145 | ||
| 146 | Key256 GetBISKey(u8 partition_id) const; | ||
| 147 | |||
| 94 | void SetKey(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0); | 148 | void SetKey(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0); |
| 95 | void SetKey(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0); | 149 | void SetKey(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0); |
| 96 | 150 | ||
| @@ -100,23 +154,51 @@ public: | |||
| 100 | // 8*43 and the private file to exist. | 154 | // 8*43 and the private file to exist. |
| 101 | void DeriveSDSeedLazy(); | 155 | void DeriveSDSeedLazy(); |
| 102 | 156 | ||
| 157 | bool BaseDeriveNecessary() const; | ||
| 158 | void DeriveBase(); | ||
| 159 | void DeriveETicket(PartitionDataManager& data); | ||
| 160 | |||
| 161 | void PopulateFromPartitionData(PartitionDataManager& data); | ||
| 162 | |||
| 103 | private: | 163 | private: |
| 104 | boost::container::flat_map<KeyIndex<S128KeyType>, Key128> s128_keys; | 164 | std::map<KeyIndex<S128KeyType>, Key128> s128_keys; |
| 105 | boost::container::flat_map<KeyIndex<S256KeyType>, Key256> s256_keys; | 165 | std::map<KeyIndex<S256KeyType>, Key256> s256_keys; |
| 166 | |||
| 167 | std::array<std::array<u8, 0xB0>, 0x20> encrypted_keyblobs{}; | ||
| 168 | std::array<std::array<u8, 0x90>, 0x20> keyblobs{}; | ||
| 106 | 169 | ||
| 107 | bool dev_mode; | 170 | bool dev_mode; |
| 108 | void LoadFromFile(const std::string& filename, bool is_title_keys); | 171 | void LoadFromFile(const std::string& filename, bool is_title_keys); |
| 109 | void AttemptLoadKeyFile(const std::string& dir1, const std::string& dir2, | 172 | void AttemptLoadKeyFile(const std::string& dir1, const std::string& dir2, |
| 110 | const std::string& filename, bool title); | 173 | const std::string& filename, bool title); |
| 111 | template <std::size_t Size> | 174 | template <size_t Size> |
| 112 | void WriteKeyToFile(bool title_key, std::string_view keyname, const std::array<u8, Size>& key); | 175 | void WriteKeyToFile(KeyCategory category, std::string_view keyname, |
| 176 | const std::array<u8, Size>& key); | ||
| 177 | |||
| 178 | void DeriveGeneralPurposeKeys(u8 crypto_revision); | ||
| 179 | |||
| 180 | void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0); | ||
| 181 | void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0); | ||
| 113 | 182 | ||
| 114 | static const boost::container::flat_map<std::string, KeyIndex<S128KeyType>> s128_file_id; | 183 | static const boost::container::flat_map<std::string, KeyIndex<S128KeyType>> s128_file_id; |
| 115 | static const boost::container::flat_map<std::string, KeyIndex<S256KeyType>> s256_file_id; | 184 | static const boost::container::flat_map<std::string, KeyIndex<S256KeyType>> s256_file_id; |
| 116 | }; | 185 | }; |
| 117 | 186 | ||
| 118 | Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed); | 187 | Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed); |
| 188 | Key128 DeriveKeyblobKey(const Key128& sbk, const Key128& tsec, Key128 source); | ||
| 189 | Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source); | ||
| 190 | Key128 DeriveMasterKey(const std::array<u8, 0x90>& keyblob, const Key128& master_source); | ||
| 191 | std::array<u8, 0x90> DecryptKeyblob(const std::array<u8, 0xB0>& encrypted_keyblob, | ||
| 192 | const Key128& key); | ||
| 193 | |||
| 119 | boost::optional<Key128> DeriveSDSeed(); | 194 | boost::optional<Key128> DeriveSDSeed(); |
| 120 | Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, const KeyManager& keys); | 195 | Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& keys); |
| 196 | |||
| 197 | std::vector<TicketRaw> GetTicketblob(const FileUtil::IOFile& ticket_save); | ||
| 198 | |||
| 199 | // Returns a pair of {rights_id, titlekey}. Fails if the ticket has no certificate authority (offset | ||
| 200 | // 0x140-0x144 is zero) | ||
| 201 | boost::optional<std::pair<Key128, Key128>> ParseTicket( | ||
| 202 | const TicketRaw& ticket, const RSAKeyPair<2048>& eticket_extended_key); | ||
| 121 | 203 | ||
| 122 | } // namespace Core::Crypto | 204 | } // namespace Core::Crypto |