key_manager.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <array>
  6. #include <map>
  7. #include <optional>
  8. #include <string>
  9. #include <boost/container/flat_map.hpp>
  10. #include <fmt/format.h>
  11. #include "common/common_types.h"
  12. #include "core/crypto/partition_data_manager.h"
  13. #include "core/file_sys/vfs_types.h"
  14. namespace FileUtil {
  15. class IOFile;
  16. }
  17. namespace Loader {
  18. enum class ResultStatus : u16;
  19. }
  20. namespace Core::Crypto {
  21. constexpr u64 TICKET_FILE_TITLEKEY_OFFSET = 0x180;
  22. using Key128 = std::array<u8, 0x10>;
  23. using Key256 = std::array<u8, 0x20>;
  24. using SHA256Hash = std::array<u8, 0x20>;
  25. using TicketRaw = std::array<u8, 0x400>;
  26. static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big.");
  27. static_assert(sizeof(Key256) == 32, "Key256 must be 256 bytes big.");
  28. template <size_t bit_size, size_t byte_size = (bit_size >> 3)>
  29. struct RSAKeyPair {
  30. std::array<u8, byte_size> encryption_key;
  31. std::array<u8, byte_size> decryption_key;
  32. std::array<u8, byte_size> modulus;
  33. std::array<u8, 4> exponent;
  34. };
  35. enum class KeyCategory : u8 {
  36. Standard,
  37. Title,
  38. Console,
  39. };
  40. enum class S256KeyType : u64 {
  41. SDKey, // f1=SDKeyType
  42. Header, //
  43. SDKeySource, // f1=SDKeyType
  44. HeaderSource, //
  45. };
  46. enum class S128KeyType : u64 {
  47. Master, // f1=crypto revision
  48. Package1, // f1=crypto revision
  49. Package2, // f1=crypto revision
  50. Titlekek, // f1=crypto revision
  51. ETicketRSAKek, //
  52. KeyArea, // f1=crypto revision f2=type {app, ocean, system}
  53. SDSeed, //
  54. Titlekey, // f1=rights id LSB f2=rights id MSB
  55. Source, // f1=source type, f2= sub id
  56. Keyblob, // f1=crypto revision
  57. KeyblobMAC, // f1=crypto revision
  58. TSEC, //
  59. SecureBoot, //
  60. BIS, // f1=partition (0-3), f2=type {crypt, tweak}
  61. HeaderKek, //
  62. SDKek, //
  63. RSAKek, //
  64. };
  65. enum class KeyAreaKeyType : u8 {
  66. Application,
  67. Ocean,
  68. System,
  69. };
  70. enum class SourceKeyType : u8 {
  71. SDKek, //
  72. AESKekGeneration, //
  73. AESKeyGeneration, //
  74. RSAOaepKekGeneration, //
  75. Master, //
  76. Keyblob, // f2=crypto revision
  77. KeyAreaKey, // f2=KeyAreaKeyType
  78. Titlekek, //
  79. Package2, //
  80. HeaderKek, //
  81. KeyblobMAC, //
  82. ETicketKek, //
  83. ETicketKekek, //
  84. };
  85. enum class SDKeyType : u8 {
  86. Save,
  87. NCA,
  88. };
  89. enum class BISKeyType : u8 {
  90. Crypto,
  91. Tweak,
  92. };
  93. enum class RSAKekType : u8 {
  94. Mask0,
  95. Seed3,
  96. };
  97. template <typename KeyType>
  98. struct KeyIndex {
  99. KeyType type;
  100. u64 field1;
  101. u64 field2;
  102. std::string DebugInfo() const {
  103. u8 key_size = 16;
  104. if constexpr (std::is_same_v<KeyType, S256KeyType>)
  105. key_size = 32;
  106. return fmt::format("key_size={:02X}, key={:02X}, field1={:016X}, field2={:016X}", key_size,
  107. static_cast<u8>(type), field1, field2);
  108. }
  109. };
  110. // boost flat_map requires operator< for O(log(n)) lookups.
  111. template <typename KeyType>
  112. bool operator<(const KeyIndex<KeyType>& lhs, const KeyIndex<KeyType>& rhs) {
  113. return std::tie(lhs.type, lhs.field1, lhs.field2) < std::tie(rhs.type, rhs.field1, rhs.field2);
  114. }
  115. class KeyManager {
  116. public:
  117. KeyManager();
  118. bool HasKey(S128KeyType id, u64 field1 = 0, u64 field2 = 0) const;
  119. bool HasKey(S256KeyType id, u64 field1 = 0, u64 field2 = 0) const;
  120. Key128 GetKey(S128KeyType id, u64 field1 = 0, u64 field2 = 0) const;
  121. Key256 GetKey(S256KeyType id, u64 field1 = 0, u64 field2 = 0) const;
  122. Key256 GetBISKey(u8 partition_id) const;
  123. void SetKey(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0);
  124. void SetKey(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0);
  125. static bool KeyFileExists(bool title);
  126. // Call before using the sd seed to attempt to derive it if it dosen't exist. Needs system save
  127. // 8*43 and the private file to exist.
  128. void DeriveSDSeedLazy();
  129. bool BaseDeriveNecessary() const;
  130. void DeriveBase();
  131. void DeriveETicket(PartitionDataManager& data);
  132. void PopulateFromPartitionData(PartitionDataManager& data);
  133. private:
  134. std::map<KeyIndex<S128KeyType>, Key128> s128_keys;
  135. std::map<KeyIndex<S256KeyType>, Key256> s256_keys;
  136. std::array<std::array<u8, 0xB0>, 0x20> encrypted_keyblobs{};
  137. std::array<std::array<u8, 0x90>, 0x20> keyblobs{};
  138. bool dev_mode;
  139. void LoadFromFile(const std::string& filename, bool is_title_keys);
  140. void AttemptLoadKeyFile(const std::string& dir1, const std::string& dir2,
  141. const std::string& filename, bool title);
  142. template <size_t Size>
  143. void WriteKeyToFile(KeyCategory category, std::string_view keyname,
  144. const std::array<u8, Size>& key);
  145. void DeriveGeneralPurposeKeys(std::size_t crypto_revision);
  146. void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0);
  147. void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0);
  148. static const boost::container::flat_map<std::string, KeyIndex<S128KeyType>> s128_file_id;
  149. static const boost::container::flat_map<std::string, KeyIndex<S256KeyType>> s256_file_id;
  150. };
  151. Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed);
  152. Key128 DeriveKeyblobKey(const Key128& sbk, const Key128& tsec, Key128 source);
  153. Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source);
  154. Key128 DeriveMasterKey(const std::array<u8, 0x90>& keyblob, const Key128& master_source);
  155. std::array<u8, 0x90> DecryptKeyblob(const std::array<u8, 0xB0>& encrypted_keyblob,
  156. const Key128& key);
  157. std::optional<Key128> DeriveSDSeed();
  158. Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& keys);
  159. std::vector<TicketRaw> GetTicketblob(const FileUtil::IOFile& ticket_save);
  160. // Returns a pair of {rights_id, titlekey}. Fails if the ticket has no certificate authority (offset
  161. // 0x140-0x144 is zero)
  162. std::optional<std::pair<Key128, Key128>> ParseTicket(const TicketRaw& ticket,
  163. const RSAKeyPair<2048>& eticket_extended_key);
  164. } // namespace Core::Crypto