summaryrefslogtreecommitdiff
path: root/src/core/crypto/key_manager.h
diff options
context:
space:
mode:
authorGravatar bunnei2018-08-04 14:33:11 -0400
committerGravatar GitHub2018-08-04 14:33:11 -0400
commit2b06301dbfbfe79687219bf7783a6d1b47695401 (patch)
tree222cc27ecbc7f7e86d2edef8d36436600dee7d7a /src/core/crypto/key_manager.h
parentMerge pull request #919 from lioncash/sign (diff)
parentAdd missing parameter to files.push_back() (diff)
downloadyuzu-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.h119
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
14namespace Core::Crypto {
15
16using Key128 = std::array<u8, 0x10>;
17using Key256 = std::array<u8, 0x20>;
18using SHA256Hash = std::array<u8, 0x20>;
19
20static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big.");
21static_assert(sizeof(Key256) == 32, "Key128 must be 128 bytes big.");
22
23enum class S256KeyType : u64 {
24 Header, //
25 SDSave, //
26 SDNCA, //
27};
28
29enum 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
40enum class KeyAreaKeyType : u8 {
41 Application,
42 Ocean,
43 System,
44};
45
46template <typename KeyType>
47struct 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
63template <typename KeyType>
64bool 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
68template <typename KeyType>
69bool operator!=(const KeyIndex<KeyType>& lhs, const KeyIndex<KeyType>& rhs) {
70 return !operator==(lhs, rhs);
71}
72
73} // namespace Core::Crypto
74
75namespace std {
76template <typename KeyType>
77struct 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
87namespace Core::Crypto {
88
89std::array<u8, 0x10> operator"" _array16(const char* str, size_t len);
90std::array<u8, 0x20> operator"" _array32(const char* str, size_t len);
91
92class KeyManager {
93public:
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
107private:
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