key_manager.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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 <unordered_map>
  7. #include <vector>
  8. #include <fmt/format.h>
  9. #include "common/common_types.h"
  10. namespace Core::Crypto {
  11. using Key128 = std::array<u8, 0x10>;
  12. using Key256 = std::array<u8, 0x20>;
  13. using SHA256Hash = std::array<u8, 0x20>;
  14. static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big.");
  15. static_assert(sizeof(Key256) == 32, "Key128 must be 128 bytes big.");
  16. enum class S256KeyType : u64 {
  17. Header, //
  18. SDSave, //
  19. SDNCA, //
  20. };
  21. enum class S128KeyType : u64 {
  22. Master, // f1=crypto revision
  23. Package1, // f1=crypto revision
  24. Package2, // f1=crypto revision
  25. Titlekek, // f1=crypto revision
  26. ETicketRSAKek, //
  27. KeyArea, // f1=crypto revision f2=type {app, ocean, system}
  28. SDSeed, //
  29. Titlekey, // f1=rights id LSB f2=rights id MSB
  30. };
  31. enum class KeyAreaKeyType : u8 {
  32. Application,
  33. Ocean,
  34. System,
  35. };
  36. template <typename KeyType>
  37. struct KeyIndex {
  38. KeyType type;
  39. u64 field1;
  40. u64 field2;
  41. std::string DebugInfo() const {
  42. u8 key_size = 16;
  43. if (std::is_same_v<KeyType, S256KeyType>)
  44. key_size = 32;
  45. return fmt::format("key_size={:02X}, key={:02X}, field1={:016X}, field2={:016X}", key_size,
  46. static_cast<u8>(type), field1, field2);
  47. }
  48. };
  49. // The following two (== and hash) are so KeyIndex can be a key in unordered_map
  50. template <typename KeyType>
  51. bool operator==(const KeyIndex<KeyType>& lhs, const KeyIndex<KeyType>& rhs) {
  52. return std::tie(lhs.type, lhs.field1, lhs.field2) == std::tie(rhs.type, rhs.field1, rhs.field2);
  53. }
  54. template <typename KeyType>
  55. bool operator!=(const KeyIndex<KeyType>& lhs, const KeyIndex<KeyType>& rhs) {
  56. return !operator==(lhs, rhs);
  57. }
  58. } // namespace Core::Crypto
  59. namespace std {
  60. template <typename KeyType>
  61. struct hash<Core::Crypto::KeyIndex<KeyType>> {
  62. size_t operator()(const Core::Crypto::KeyIndex<KeyType>& k) const {
  63. using std::hash;
  64. return ((hash<u64>()(static_cast<u64>(k.type)) ^ (hash<u64>()(k.field1) << 1)) >> 1) ^
  65. (hash<u64>()(k.field2) << 1);
  66. }
  67. };
  68. } // namespace std
  69. namespace Core::Crypto {
  70. std::array<u8, 0x10> operator"" _array16(const char* str, size_t len);
  71. std::array<u8, 0x20> operator"" _array32(const char* str, size_t len);
  72. class KeyManager {
  73. public:
  74. KeyManager();
  75. bool HasKey(S128KeyType id, u64 field1 = 0, u64 field2 = 0) const;
  76. bool HasKey(S256KeyType id, u64 field1 = 0, u64 field2 = 0) const;
  77. Key128 GetKey(S128KeyType id, u64 field1 = 0, u64 field2 = 0) const;
  78. Key256 GetKey(S256KeyType id, u64 field1 = 0, u64 field2 = 0) const;
  79. void SetKey(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0);
  80. void SetKey(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0);
  81. private:
  82. std::unordered_map<KeyIndex<S128KeyType>, Key128> s128_keys;
  83. std::unordered_map<KeyIndex<S256KeyType>, Key256> s256_keys;
  84. bool dev_mode;
  85. void LoadFromFile(std::string_view filename, bool is_title_keys);
  86. void AttemptLoadKeyFile(std::string_view dir1, std::string_view dir2, std::string_view filename,
  87. bool title);
  88. static std::unordered_map<std::string, KeyIndex<S128KeyType>> s128_file_id;
  89. static std::unordered_map<std::string, KeyIndex<S256KeyType>> s256_file_id;
  90. };
  91. } // namespace Core::Crypto