summaryrefslogtreecommitdiff
path: root/src/core/crypto/key_manager.cpp
diff options
context:
space:
mode:
authorGravatar Zach Hilman2019-04-16 09:12:04 -0400
committerGravatar Zach Hilman2019-07-07 21:38:33 -0400
commitf8718ae779bbdc6a3f514b5ce141515baa97e14f (patch)
tree4a7712329982e2cb512412cbb4a17fa52a53f780 /src/core/crypto/key_manager.cpp
parentes: Implement ETicket GetPersonalizedTicketData (17) (diff)
downloadyuzu-f8718ae779bbdc6a3f514b5ce141515baa97e14f.tar.gz
yuzu-f8718ae779bbdc6a3f514b5ce141515baa97e14f.tar.xz
yuzu-f8718ae779bbdc6a3f514b5ce141515baa97e14f.zip
key_manager: Add structure for Ticket parsing
Diffstat (limited to 'src/core/crypto/key_manager.cpp')
-rw-r--r--src/core/crypto/key_manager.cpp124
1 files changed, 102 insertions, 22 deletions
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index ef139902d..558790a49 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -37,6 +37,7 @@
37namespace Core::Crypto { 37namespace Core::Crypto {
38 38
39constexpr u64 CURRENT_CRYPTO_REVISION = 0x5; 39constexpr u64 CURRENT_CRYPTO_REVISION = 0x5;
40constexpr u64 FULL_TICKET_SIZE = 0x400;
40 41
41using namespace Common; 42using namespace Common;
42 43
@@ -55,6 +56,78 @@ const std::map<std::pair<S128KeyType, u64>, std::string> KEYS_VARIABLE_LENGTH{
55 {{S128KeyType::KeyblobMAC, 0}, "keyblob_mac_key_"}, 56 {{S128KeyType::KeyblobMAC, 0}, "keyblob_mac_key_"},
56}; 57};
57 58
59u64 GetSignatureTypeDataSize(SignatureType type) {
60 switch (type) {
61 case SignatureType::RSA_4096_SHA1:
62 case SignatureType::RSA_4096_SHA256:
63 return 0x200;
64 case SignatureType::RSA_2048_SHA1:
65 case SignatureType::RSA_2048_SHA256:
66 return 0x100;
67 case SignatureType::ECDSA_SHA1:
68 case SignatureType::ECDSA_SHA256:
69 return 0x3C;
70 }
71 UNREACHABLE();
72}
73
74u64 GetSignatureTypePaddingSize(SignatureType type) {
75 switch (type) {
76 case SignatureType::RSA_4096_SHA1:
77 case SignatureType::RSA_4096_SHA256:
78 case SignatureType::RSA_2048_SHA1:
79 case SignatureType::RSA_2048_SHA256:
80 return 0x3C;
81 case SignatureType::ECDSA_SHA1:
82 case SignatureType::ECDSA_SHA256:
83 return 0x40;
84 }
85 UNREACHABLE();
86}
87
88TicketData& Ticket::GetData() {
89 switch (sig_type) {
90 case SignatureType::RSA_4096_SHA1:
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 }
100 UNREACHABLE();
101}
102
103const TicketData& Ticket::GetData() const {
104 switch (sig_type) {
105 case SignatureType::RSA_4096_SHA1:
106 case SignatureType::RSA_4096_SHA256:
107 return rsa_4096.data;
108 case SignatureType::RSA_2048_SHA1:
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 }
115 UNREACHABLE();
116}
117
118u64 Ticket::GetSize() const {
119 return sizeof(SignatureType) + GetSignatureTypeDataSize(sig_type) +
120 GetSignatureTypePaddingSize(sig_type) + sizeof(TicketData);
121}
122
123Ticket Ticket::SynthesizeCommon(Key128 title_key, std::array<u8, 16> rights_id) {
124 Ticket out{};
125 out.sig_type = SignatureType::RSA_2048_SHA256;
126 out.GetData().rights_id = rights_id;
127 out.GetData().title_key_common = title_key;
128 return out;
129}
130
58Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed) { 131Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed) {
59 Key128 out{}; 132 Key128 out{};
60 133
@@ -259,7 +332,7 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& ke
259 return Loader::ResultStatus::Success; 332 return Loader::ResultStatus::Success;
260} 333}
261 334
262std::vector<TicketRaw> GetTicketblob(const FileUtil::IOFile& ticket_save) { 335std::vector<Ticket> GetTicketblob(const FileUtil::IOFile& ticket_save) {
263 if (!ticket_save.IsOpen()) 336 if (!ticket_save.IsOpen())
264 return {}; 337 return {};
265 338
@@ -268,14 +341,14 @@ std::vector<TicketRaw> GetTicketblob(const FileUtil::IOFile& ticket_save) {
268 return {}; 341 return {};
269 } 342 }
270 343
271 std::vector<TicketRaw> out; 344 std::vector<Ticket> out;
272 for (std::size_t offset = 0; offset + 0x4 < buffer.size(); ++offset) { 345 for (std::size_t offset = 0; offset + 0x4 < buffer.size(); ++offset) {
273 if (buffer[offset] == 0x4 && buffer[offset + 1] == 0x0 && buffer[offset + 2] == 0x1 && 346 if (buffer[offset] == 0x4 && buffer[offset + 1] == 0x0 && buffer[offset + 2] == 0x1 &&
274 buffer[offset + 3] == 0x0) { 347 buffer[offset + 3] == 0x0) {
275 out.emplace_back(); 348 out.emplace_back();
276 auto& next = out.back(); 349 auto& next = out.back();
277 std::memcpy(&next, buffer.data() + offset, sizeof(TicketRaw)); 350 std::memcpy(&next, buffer.data() + offset, sizeof(Ticket));
278 offset += next.size(); 351 offset += FULL_TICKET_SIZE;
279 } 352 }
280 } 353 }
281 354
@@ -327,29 +400,25 @@ static std::optional<u64> FindTicketOffset(const std::array<u8, size>& data) {
327 return offset; 400 return offset;
328} 401}
329 402
330std::optional<std::pair<Key128, Key128>> ParseTicket(const TicketRaw& ticket, 403std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket,
331 const RSAKeyPair<2048>& key) { 404 const RSAKeyPair<2048>& key) {
332 u32 cert_authority; 405 const auto issuer = ticket.GetData().issuer;
333 std::memcpy(&cert_authority, ticket.data() + 0x140, sizeof(cert_authority)); 406 if (issuer == std::array<u8, 0x40>{})
334 if (cert_authority == 0)
335 return {}; 407 return {};
336 if (cert_authority != Common::MakeMagic('R', 'o', 'o', 't')) { 408 if (issuer[0] != 'R' || issuer[1] != 'o' || issuer[2] != 'o' || issuer[3] != 't') {
337 LOG_INFO(Crypto, 409 LOG_INFO(Crypto,
338 "Attempting to parse ticket with non-standard certificate authority {:08X}.", 410 "Attempting to parse ticket with non-standard certificate authority {:08X}.",
339 cert_authority); 411 issuer);
340 } 412 }
341 413
342 Key128 rights_id; 414 Key128 rights_id = ticket.GetData().rights_id;
343 std::memcpy(rights_id.data(), ticket.data() + 0x2A0, sizeof(Key128));
344 415
345 if (rights_id == Key128{}) 416 if (rights_id == Key128{})
346 return {}; 417 return {};
347 418
348 Key128 key_temp{}; 419 if (!std::any_of(ticket.GetData().title_key_common_pad.begin(),
349 420 ticket.GetData().title_key_common_pad.end(), [](u8 b) { return b != 0; })) {
350 if (!std::any_of(ticket.begin() + 0x190, ticket.begin() + 0x280, [](u8 b) { return b != 0; })) { 421 return std::make_pair(rights_id, ticket.GetData().title_key_common);
351 std::memcpy(key_temp.data(), ticket.data() + 0x180, key_temp.size());
352 return std::make_pair(rights_id, key_temp);
353 } 422 }
354 423
355 mbedtls_mpi D; // RSA Private Exponent 424 mbedtls_mpi D; // RSA Private Exponent
@@ -364,7 +433,7 @@ std::optional<std::pair<Key128, Key128>> ParseTicket(const TicketRaw& ticket,
364 433
365 mbedtls_mpi_read_binary(&D, key.decryption_key.data(), key.decryption_key.size()); 434 mbedtls_mpi_read_binary(&D, key.decryption_key.data(), key.decryption_key.size());
366 mbedtls_mpi_read_binary(&N, key.modulus.data(), key.modulus.size()); 435 mbedtls_mpi_read_binary(&N, key.modulus.data(), key.modulus.size());
367 mbedtls_mpi_read_binary(&S, ticket.data() + 0x180, 0x100); 436 mbedtls_mpi_read_binary(&S, ticket.GetData().title_key_block.data(), 0x100);
368 437
369 mbedtls_mpi_exp_mod(&M, &S, &D, &N, nullptr); 438 mbedtls_mpi_exp_mod(&M, &S, &D, &N, nullptr);
370 439
@@ -388,6 +457,7 @@ std::optional<std::pair<Key128, Key128>> ParseTicket(const TicketRaw& ticket,
388 return {}; 457 return {};
389 ASSERT(*offset > 0); 458 ASSERT(*offset > 0);
390 459
460 Key128 key_temp{};
391 std::memcpy(key_temp.data(), m_2.data() + *offset, key_temp.size()); 461 std::memcpy(key_temp.data(), m_2.data() + *offset, key_temp.size());
392 462
393 return std::make_pair(rights_id, key_temp); 463 return std::make_pair(rights_id, key_temp);
@@ -411,6 +481,16 @@ KeyManager::KeyManager() {
411 AttemptLoadKeyFile(yuzu_keys_dir, yuzu_keys_dir, "title.keys_autogenerated", true); 481 AttemptLoadKeyFile(yuzu_keys_dir, yuzu_keys_dir, "title.keys_autogenerated", true);
412 AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "console.keys", false); 482 AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "console.keys", false);
413 AttemptLoadKeyFile(yuzu_keys_dir, yuzu_keys_dir, "console.keys_autogenerated", false); 483 AttemptLoadKeyFile(yuzu_keys_dir, yuzu_keys_dir, "console.keys_autogenerated", false);
484
485 for (const auto& key : s128_keys) {
486 if (key.first.type == S128KeyType::Titlekey) {
487 u128 rights_id{key.first.field1, key.first.field2};
488 Key128 rights_id_2;
489 std::memcpy(rights_id_2.data(), rights_id.data(), rights_id_2.size());
490 const auto ticket = Ticket::SynthesizeCommon(key.second, rights_id_2);
491 common_tickets.insert_or_assign(rights_id, ticket);
492 }
493 }
414} 494}
415 495
416static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_t length) { 496static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_t length) {
@@ -1029,15 +1109,15 @@ void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) {
1029 DeriveBase(); 1109 DeriveBase();
1030} 1110}
1031 1111
1032const std::map<u128, TicketRaw>& KeyManager::GetCommonTickets() const { 1112const std::map<u128, Ticket>& KeyManager::GetCommonTickets() const {
1033 return common_tickets; 1113 return common_tickets;
1034} 1114}
1035 1115
1036const std::map<u128, TicketRaw>& KeyManager::GetPersonalizedTickets() const { 1116const std::map<u128, Ticket>& KeyManager::GetPersonalizedTickets() const {
1037 return personal_tickets; 1117 return personal_tickets;
1038} 1118}
1039 1119
1040bool KeyManager::AddTicketCommon(TicketRaw raw) { 1120bool KeyManager::AddTicketCommon(Ticket raw) {
1041 const auto rsa_key = GetETicketRSAKey(); 1121 const auto rsa_key = GetETicketRSAKey();
1042 if (rsa_key == RSAKeyPair<2048>{}) 1122 if (rsa_key == RSAKeyPair<2048>{})
1043 return false; 1123 return false;
@@ -1053,7 +1133,7 @@ bool KeyManager::AddTicketCommon(TicketRaw raw) {
1053 return true; 1133 return true;
1054} 1134}
1055 1135
1056bool KeyManager::AddTicketPersonalized(TicketRaw raw) { 1136bool KeyManager::AddTicketPersonalized(Ticket raw) {
1057 const auto rsa_key = GetETicketRSAKey(); 1137 const auto rsa_key = GetETicketRSAKey();
1058 if (rsa_key == RSAKeyPair<2048>{}) 1138 if (rsa_key == RSAKeyPair<2048>{})
1059 return false; 1139 return false;