summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Zach Hilman2019-05-26 13:01:42 -0400
committerGravatar Zach Hilman2019-07-07 21:38:33 -0400
commit50d541407507edc2f29ad6a46f3f17724e52f7f7 (patch)
tree2a63feb14069c769a85a512a42d1447c05634027
parentes: Populate/synthesize tickets on construction (diff)
downloadyuzu-50d541407507edc2f29ad6a46f3f17724e52f7f7.tar.gz
yuzu-50d541407507edc2f29ad6a46f3f17724e52f7f7.tar.xz
yuzu-50d541407507edc2f29ad6a46f3f17724e52f7f7.zip
key_manager: Convert Ticket union to std::variant
-rw-r--r--src/core/crypto/key_manager.cpp91
-rw-r--r--src/core/crypto/key_manager.h50
-rw-r--r--src/core/hle/service/es/es.cpp4
3 files changed, 88 insertions, 57 deletions
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index 3c51e3dc2..46aceec3d 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -56,6 +56,13 @@ const std::map<std::pair<S128KeyType, u64>, std::string> KEYS_VARIABLE_LENGTH{
56 {{S128KeyType::KeyblobMAC, 0}, "keyblob_mac_key_"}, 56 {{S128KeyType::KeyblobMAC, 0}, "keyblob_mac_key_"},
57}; 57};
58 58
59namespace {
60template <std::size_t Size>
61bool IsAllZeroArray(const std::array<u8, Size>& array) {
62 return std::all_of(array.begin(), array.end(), [](const auto& elem) { return elem == 0; });
63}
64} // namespace
65
59u64 GetSignatureTypeDataSize(SignatureType type) { 66u64 GetSignatureTypeDataSize(SignatureType type) {
60 switch (type) { 67 switch (type) {
61 case SignatureType::RSA_4096_SHA1: 68 case SignatureType::RSA_4096_SHA1:
@@ -85,47 +92,61 @@ u64 GetSignatureTypePaddingSize(SignatureType type) {
85 UNREACHABLE(); 92 UNREACHABLE();
86} 93}
87 94
95SignatureType Ticket::GetSignatureType() const {
96 if (auto ticket = std::get_if<RSA4096Ticket>(&data)) {
97 return ticket->sig_type;
98 }
99 if (auto ticket = std::get_if<RSA2048Ticket>(&data)) {
100 return ticket->sig_type;
101 }
102 if (auto ticket = std::get_if<ECDSATicket>(&data)) {
103 return ticket->sig_type;
104 }
105
106 UNREACHABLE();
107}
108
88TicketData& Ticket::GetData() { 109TicketData& Ticket::GetData() {
89 switch (sig_type) { 110 if (auto ticket = std::get_if<RSA4096Ticket>(&data)) {
90 case SignatureType::RSA_4096_SHA1: 111 return ticket->data;
91 case SignatureType::RSA_4096_SHA256:
92 return rsa_4096.data;
93 case SignatureType::RSA_2048_SHA1:
94 case SignatureType::RSA_2048_SHA256:
95 return rsa_2048.data;
96 case SignatureType::ECDSA_SHA1:
97 case SignatureType::ECDSA_SHA256:
98 return ecdsa.data;
99 } 112 }
113 if (auto ticket = std::get_if<RSA2048Ticket>(&data)) {
114 return ticket->data;
115 }
116 if (auto ticket = std::get_if<ECDSATicket>(&data)) {
117 return ticket->data;
118 }
119
100 UNREACHABLE(); 120 UNREACHABLE();
101} 121}
102 122
103const TicketData& Ticket::GetData() const { 123const TicketData& Ticket::GetData() const {
104 switch (sig_type) { 124 if (auto ticket = std::get_if<RSA4096Ticket>(&data)) {
105 case SignatureType::RSA_4096_SHA1: 125 return ticket->data;
106 case SignatureType::RSA_4096_SHA256: 126 }
107 return rsa_4096.data; 127 if (auto ticket = std::get_if<RSA2048Ticket>(&data)) {
108 case SignatureType::RSA_2048_SHA1: 128 return ticket->data;
109 case SignatureType::RSA_2048_SHA256:
110 return rsa_2048.data;
111 case SignatureType::ECDSA_SHA1:
112 case SignatureType::ECDSA_SHA256:
113 return ecdsa.data;
114 } 129 }
130 if (auto ticket = std::get_if<ECDSATicket>(&data)) {
131 return ticket->data;
132 }
133
115 UNREACHABLE(); 134 UNREACHABLE();
116} 135}
117 136
118u64 Ticket::GetSize() const { 137u64 Ticket::GetSize() const {
138 const auto sig_type = GetSignatureType();
139
119 return sizeof(SignatureType) + GetSignatureTypeDataSize(sig_type) + 140 return sizeof(SignatureType) + GetSignatureTypeDataSize(sig_type) +
120 GetSignatureTypePaddingSize(sig_type) + sizeof(TicketData); 141 GetSignatureTypePaddingSize(sig_type) + sizeof(TicketData);
121} 142}
122 143
123Ticket Ticket::SynthesizeCommon(Key128 title_key, std::array<u8, 16> rights_id) { 144Ticket Ticket::SynthesizeCommon(Key128 title_key, const std::array<u8, 16>& rights_id) {
124 Ticket out{}; 145 RSA2048Ticket out{};
125 out.sig_type = SignatureType::RSA_2048_SHA256; 146 out.sig_type = SignatureType::RSA_2048_SHA256;
126 out.GetData().rights_id = rights_id; 147 out.data.rights_id = rights_id;
127 out.GetData().title_key_common = title_key; 148 out.data.title_key_common = title_key;
128 return out; 149 return Ticket{out};
129} 150}
130 151
131Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed) { 152Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed) {
@@ -208,14 +229,13 @@ void KeyManager::DeriveGeneralPurposeKeys(std::size_t crypto_revision) {
208 } 229 }
209} 230}
210 231
211RSAKeyPair<2048> KeyManager::GetETicketRSAKey() { 232RSAKeyPair<2048> KeyManager::GetETicketRSAKey() const {
212 if (eticket_extended_kek == std::array<u8, 576>{} || !HasKey(S128KeyType::ETicketRSAKek)) 233 if (IsAllZeroArray(eticket_extended_kek) || !HasKey(S128KeyType::ETicketRSAKek))
213 return {}; 234 return {};
214 235
215 const auto eticket_final = GetKey(S128KeyType::ETicketRSAKek); 236 const auto eticket_final = GetKey(S128KeyType::ETicketRSAKek);
216 237
217 std::vector<u8> extended_iv(0x10); 238 std::vector<u8> extended_iv(eticket_extended_kek.begin(), eticket_extended_kek.begin() + 0x10);
218 std::memcpy(extended_iv.data(), eticket_extended_kek.data(), extended_iv.size());
219 std::array<u8, 0x230> extended_dec{}; 239 std::array<u8, 0x230> extended_dec{};
220 AESCipher<Key128> rsa_1(eticket_final, Mode::CTR); 240 AESCipher<Key128> rsa_1(eticket_final, Mode::CTR);
221 rsa_1.SetIV(extended_iv); 241 rsa_1.SetIV(extended_iv);
@@ -1001,13 +1021,14 @@ void KeyManager::PopulateTickets() {
1001 1021
1002void KeyManager::SynthesizeTickets() { 1022void KeyManager::SynthesizeTickets() {
1003 for (const auto& key : s128_keys) { 1023 for (const auto& key : s128_keys) {
1004 if (key.first.type == S128KeyType::Titlekey) { 1024 if (key.first.type != S128KeyType::Titlekey) {
1005 u128 rights_id{key.first.field1, key.first.field2}; 1025 continue;
1006 Key128 rights_id_2;
1007 std::memcpy(rights_id_2.data(), rights_id.data(), rights_id_2.size());
1008 const auto ticket = Ticket::SynthesizeCommon(key.second, rights_id_2);
1009 common_tickets.insert_or_assign(rights_id, ticket);
1010 } 1026 }
1027 u128 rights_id{key.first.field1, key.first.field2};
1028 Key128 rights_id_2;
1029 std::memcpy(rights_id_2.data(), rights_id.data(), rights_id_2.size());
1030 const auto ticket = Ticket::SynthesizeCommon(key.second, rights_id_2);
1031 common_tickets.insert_or_assign(rights_id, ticket);
1011 } 1032 }
1012} 1033}
1013 1034
diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h
index d4e89d35c..7265c4171 100644
--- a/src/core/crypto/key_manager.h
+++ b/src/core/crypto/key_manager.h
@@ -9,6 +9,7 @@
9#include <optional> 9#include <optional>
10#include <string> 10#include <string>
11 11
12#include <variant>
12#include <boost/container/flat_map.hpp> 13#include <boost/container/flat_map.hpp>
13#include <fmt/format.h> 14#include <fmt/format.h>
14#include "common/common_funcs.h" 15#include "common/common_funcs.h"
@@ -73,33 +74,36 @@ struct TicketData {
73}; 74};
74static_assert(sizeof(TicketData) == 0x2C0, "TicketData has incorrect size."); 75static_assert(sizeof(TicketData) == 0x2C0, "TicketData has incorrect size.");
75 76
76struct Ticket { 77struct RSA4096Ticket {
77 SignatureType sig_type; 78 SignatureType sig_type;
78 union { 79 std::array<u8, 0x200> sig_data;
79 struct { 80 INSERT_PADDING_BYTES(0x3C);
80 std::array<u8, 0x200> sig_data; 81 TicketData data;
81 INSERT_PADDING_BYTES(0x3C); 82};
82 TicketData data;
83 } rsa_4096;
84 83
85 struct { 84struct RSA2048Ticket {
86 std::array<u8, 0x100> sig_data; 85 SignatureType sig_type;
87 INSERT_PADDING_BYTES(0x3C); 86 std::array<u8, 0x100> sig_data;
88 TicketData data; 87 INSERT_PADDING_BYTES(0x3C);
89 } rsa_2048; 88 TicketData data;
89};
90 90
91 struct { 91struct ECDSATicket {
92 std::array<u8, 0x3C> sig_data; 92 SignatureType sig_type;
93 INSERT_PADDING_BYTES(0x40); 93 std::array<u8, 0x3C> sig_data;
94 TicketData data; 94 INSERT_PADDING_BYTES(0x40);
95 } ecdsa; 95 TicketData data;
96 }; 96};
97
98struct Ticket {
99 std::variant<RSA4096Ticket, RSA2048Ticket, ECDSATicket> data;
97 100
101 SignatureType GetSignatureType() const;
98 TicketData& GetData(); 102 TicketData& GetData();
99 const TicketData& GetData() const; 103 const TicketData& GetData() const;
100 u64 GetSize() const; 104 u64 GetSize() const;
101 105
102 static Ticket SynthesizeCommon(Key128 title_key, std::array<u8, 0x10> rights_id); 106 static Ticket SynthesizeCommon(Key128 title_key, const std::array<u8, 0x10>& rights_id);
103}; 107};
104 108
105static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big."); 109static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big.");
@@ -120,6 +124,12 @@ bool operator==(const RSAKeyPair<bit_size, byte_size>& lhs,
120 std::tie(rhs.encryption_key, rhs.decryption_key, rhs.modulus, rhs.exponent); 124 std::tie(rhs.encryption_key, rhs.decryption_key, rhs.modulus, rhs.exponent);
121} 125}
122 126
127template <size_t bit_size, size_t byte_size>
128bool operator!=(const RSAKeyPair<bit_size, byte_size>& lhs,
129 const RSAKeyPair<bit_size, byte_size>& rhs) {
130 return !(lhs == rhs);
131}
132
123enum class KeyCategory : u8 { 133enum class KeyCategory : u8 {
124 Standard, 134 Standard,
125 Title, 135 Title,
@@ -268,7 +278,7 @@ private:
268 278
269 void DeriveGeneralPurposeKeys(std::size_t crypto_revision); 279 void DeriveGeneralPurposeKeys(std::size_t crypto_revision);
270 280
271 RSAKeyPair<2048> GetETicketRSAKey(); 281 RSAKeyPair<2048> GetETicketRSAKey() const;
272 282
273 void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0); 283 void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0);
274 void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0); 284 void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0);
diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp
index 92fa2bef8..af70d174d 100644
--- a/src/core/hle/service/es/es.cpp
+++ b/src/core/hle/service/es/es.cpp
@@ -234,7 +234,7 @@ private:
234 234
235 const auto ticket = keys.GetCommonTickets().at(rights_id); 235 const auto ticket = keys.GetCommonTickets().at(rights_id);
236 236
237 const auto write_size = std::min(ticket.GetSize(), ctx.GetWriteBufferSize()); 237 const auto write_size = std::min<u64>(ticket.GetSize(), ctx.GetWriteBufferSize());
238 ctx.WriteBuffer(&ticket, write_size); 238 ctx.WriteBuffer(&ticket, write_size);
239 239
240 IPC::ResponseBuilder rb{ctx, 4}; 240 IPC::ResponseBuilder rb{ctx, 4};
@@ -253,7 +253,7 @@ private:
253 253
254 const auto ticket = keys.GetPersonalizedTickets().at(rights_id); 254 const auto ticket = keys.GetPersonalizedTickets().at(rights_id);
255 255
256 const auto write_size = std::min(ticket.GetSize(), ctx.GetWriteBufferSize()); 256 const auto write_size = std::min<u64>(ticket.GetSize(), ctx.GetWriteBufferSize());
257 ctx.WriteBuffer(&ticket, write_size); 257 ctx.WriteBuffer(&ticket, write_size);
258 258
259 IPC::ResponseBuilder rb{ctx, 4}; 259 IPC::ResponseBuilder rb{ctx, 4};