summaryrefslogtreecommitdiff
path: root/src/core/crypto/key_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/crypto/key_manager.cpp')
-rw-r--r--src/core/crypto/key_manager.cpp286
1 files changed, 176 insertions, 110 deletions
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index c09f7ad41..8783d1ac2 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -96,13 +96,13 @@ u64 GetSignatureTypePaddingSize(SignatureType type) {
96} 96}
97 97
98SignatureType Ticket::GetSignatureType() const { 98SignatureType Ticket::GetSignatureType() const {
99 if (auto ticket = std::get_if<RSA4096Ticket>(&data)) { 99 if (const auto* ticket = std::get_if<RSA4096Ticket>(&data)) {
100 return ticket->sig_type; 100 return ticket->sig_type;
101 } 101 }
102 if (auto ticket = std::get_if<RSA2048Ticket>(&data)) { 102 if (const auto* ticket = std::get_if<RSA2048Ticket>(&data)) {
103 return ticket->sig_type; 103 return ticket->sig_type;
104 } 104 }
105 if (auto ticket = std::get_if<ECDSATicket>(&data)) { 105 if (const auto* ticket = std::get_if<ECDSATicket>(&data)) {
106 return ticket->sig_type; 106 return ticket->sig_type;
107 } 107 }
108 108
@@ -110,13 +110,13 @@ SignatureType Ticket::GetSignatureType() const {
110} 110}
111 111
112TicketData& Ticket::GetData() { 112TicketData& Ticket::GetData() {
113 if (auto ticket = std::get_if<RSA4096Ticket>(&data)) { 113 if (auto* ticket = std::get_if<RSA4096Ticket>(&data)) {
114 return ticket->data; 114 return ticket->data;
115 } 115 }
116 if (auto ticket = std::get_if<RSA2048Ticket>(&data)) { 116 if (auto* ticket = std::get_if<RSA2048Ticket>(&data)) {
117 return ticket->data; 117 return ticket->data;
118 } 118 }
119 if (auto ticket = std::get_if<ECDSATicket>(&data)) { 119 if (auto* ticket = std::get_if<ECDSATicket>(&data)) {
120 return ticket->data; 120 return ticket->data;
121 } 121 }
122 122
@@ -124,13 +124,13 @@ TicketData& Ticket::GetData() {
124} 124}
125 125
126const TicketData& Ticket::GetData() const { 126const TicketData& Ticket::GetData() const {
127 if (auto ticket = std::get_if<RSA4096Ticket>(&data)) { 127 if (const auto* ticket = std::get_if<RSA4096Ticket>(&data)) {
128 return ticket->data; 128 return ticket->data;
129 } 129 }
130 if (auto ticket = std::get_if<RSA2048Ticket>(&data)) { 130 if (const auto* ticket = std::get_if<RSA2048Ticket>(&data)) {
131 return ticket->data; 131 return ticket->data;
132 } 132 }
133 if (auto ticket = std::get_if<ECDSATicket>(&data)) { 133 if (const auto* ticket = std::get_if<ECDSATicket>(&data)) {
134 return ticket->data; 134 return ticket->data;
135 } 135 }
136 136
@@ -233,8 +233,9 @@ void KeyManager::DeriveGeneralPurposeKeys(std::size_t crypto_revision) {
233} 233}
234 234
235RSAKeyPair<2048> KeyManager::GetETicketRSAKey() const { 235RSAKeyPair<2048> KeyManager::GetETicketRSAKey() const {
236 if (IsAllZeroArray(eticket_extended_kek) || !HasKey(S128KeyType::ETicketRSAKek)) 236 if (IsAllZeroArray(eticket_extended_kek) || !HasKey(S128KeyType::ETicketRSAKek)) {
237 return {}; 237 return {};
238 }
238 239
239 const auto eticket_final = GetKey(S128KeyType::ETicketRSAKek); 240 const auto eticket_final = GetKey(S128KeyType::ETicketRSAKek);
240 241
@@ -261,27 +262,30 @@ Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source)
261} 262}
262 263
263std::optional<Key128> DeriveSDSeed() { 264std::optional<Key128> DeriveSDSeed() {
264 const FileUtil::IOFile save_43(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + 265 const Common::FS::IOFile save_43(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) +
265 "/system/save/8000000000000043", 266 "/system/save/8000000000000043",
266 "rb+"); 267 "rb+");
267 if (!save_43.IsOpen()) 268 if (!save_43.IsOpen()) {
268 return {}; 269 return std::nullopt;
270 }
269 271
270 const FileUtil::IOFile sd_private( 272 const Common::FS::IOFile sd_private(Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir) +
271 FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + "/Nintendo/Contents/private", "rb+"); 273 "/Nintendo/Contents/private",
272 if (!sd_private.IsOpen()) 274 "rb+");
273 return {}; 275 if (!sd_private.IsOpen()) {
276 return std::nullopt;
277 }
274 278
275 std::array<u8, 0x10> private_seed{}; 279 std::array<u8, 0x10> private_seed{};
276 if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != private_seed.size()) { 280 if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != private_seed.size()) {
277 return {}; 281 return std::nullopt;
278 } 282 }
279 283
280 std::array<u8, 0x10> buffer{}; 284 std::array<u8, 0x10> buffer{};
281 std::size_t offset = 0; 285 std::size_t offset = 0;
282 for (; offset + 0x10 < save_43.GetSize(); ++offset) { 286 for (; offset + 0x10 < save_43.GetSize(); ++offset) {
283 if (!save_43.Seek(offset, SEEK_SET)) { 287 if (!save_43.Seek(offset, SEEK_SET)) {
284 return {}; 288 return std::nullopt;
285 } 289 }
286 290
287 save_43.ReadBytes(buffer.data(), buffer.size()); 291 save_43.ReadBytes(buffer.data(), buffer.size());
@@ -291,23 +295,26 @@ std::optional<Key128> DeriveSDSeed() {
291 } 295 }
292 296
293 if (!save_43.Seek(offset + 0x10, SEEK_SET)) { 297 if (!save_43.Seek(offset + 0x10, SEEK_SET)) {
294 return {}; 298 return std::nullopt;
295 } 299 }
296 300
297 Key128 seed{}; 301 Key128 seed{};
298 if (save_43.ReadBytes(seed.data(), seed.size()) != seed.size()) { 302 if (save_43.ReadBytes(seed.data(), seed.size()) != seed.size()) {
299 return {}; 303 return std::nullopt;
300 } 304 }
301 return seed; 305 return seed;
302} 306}
303 307
304Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& keys) { 308Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& keys) {
305 if (!keys.HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek))) 309 if (!keys.HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek))) {
306 return Loader::ResultStatus::ErrorMissingSDKEKSource; 310 return Loader::ResultStatus::ErrorMissingSDKEKSource;
307 if (!keys.HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration))) 311 }
312 if (!keys.HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration))) {
308 return Loader::ResultStatus::ErrorMissingAESKEKGenerationSource; 313 return Loader::ResultStatus::ErrorMissingAESKEKGenerationSource;
309 if (!keys.HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKeyGeneration))) 314 }
315 if (!keys.HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKeyGeneration))) {
310 return Loader::ResultStatus::ErrorMissingAESKeyGenerationSource; 316 return Loader::ResultStatus::ErrorMissingAESKeyGenerationSource;
317 }
311 318
312 const auto sd_kek_source = 319 const auto sd_kek_source =
313 keys.GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek)); 320 keys.GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek));
@@ -320,14 +327,17 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& ke
320 GenerateKeyEncryptionKey(sd_kek_source, master_00, aes_kek_gen, aes_key_gen); 327 GenerateKeyEncryptionKey(sd_kek_source, master_00, aes_kek_gen, aes_key_gen);
321 keys.SetKey(S128KeyType::SDKek, sd_kek); 328 keys.SetKey(S128KeyType::SDKek, sd_kek);
322 329
323 if (!keys.HasKey(S128KeyType::SDSeed)) 330 if (!keys.HasKey(S128KeyType::SDSeed)) {
324 return Loader::ResultStatus::ErrorMissingSDSeed; 331 return Loader::ResultStatus::ErrorMissingSDSeed;
332 }
325 const auto sd_seed = keys.GetKey(S128KeyType::SDSeed); 333 const auto sd_seed = keys.GetKey(S128KeyType::SDSeed);
326 334
327 if (!keys.HasKey(S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save))) 335 if (!keys.HasKey(S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save))) {
328 return Loader::ResultStatus::ErrorMissingSDSaveKeySource; 336 return Loader::ResultStatus::ErrorMissingSDSaveKeySource;
329 if (!keys.HasKey(S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::NCA))) 337 }
338 if (!keys.HasKey(S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::NCA))) {
330 return Loader::ResultStatus::ErrorMissingSDNCAKeySource; 339 return Loader::ResultStatus::ErrorMissingSDNCAKeySource;
340 }
331 341
332 std::array<Key256, 2> sd_key_sources{ 342 std::array<Key256, 2> sd_key_sources{
333 keys.GetKey(S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save)), 343 keys.GetKey(S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save)),
@@ -336,8 +346,9 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& ke
336 346
337 // Combine sources and seed 347 // Combine sources and seed
338 for (auto& source : sd_key_sources) { 348 for (auto& source : sd_key_sources) {
339 for (std::size_t i = 0; i < source.size(); ++i) 349 for (std::size_t i = 0; i < source.size(); ++i) {
340 source[i] ^= sd_seed[i & 0xF]; 350 source[i] ^= sd_seed[i & 0xF];
351 }
341 } 352 }
342 353
343 AESCipher<Key128> cipher(sd_kek, Mode::ECB); 354 AESCipher<Key128> cipher(sd_kek, Mode::ECB);
@@ -355,9 +366,10 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& ke
355 return Loader::ResultStatus::Success; 366 return Loader::ResultStatus::Success;
356} 367}
357 368
358std::vector<Ticket> GetTicketblob(const FileUtil::IOFile& ticket_save) { 369std::vector<Ticket> GetTicketblob(const Common::FS::IOFile& ticket_save) {
359 if (!ticket_save.IsOpen()) 370 if (!ticket_save.IsOpen()) {
360 return {}; 371 return {};
372 }
361 373
362 std::vector<u8> buffer(ticket_save.GetSize()); 374 std::vector<u8> buffer(ticket_save.GetSize());
363 if (ticket_save.ReadBytes(buffer.data(), buffer.size()) != buffer.size()) { 375 if (ticket_save.ReadBytes(buffer.data(), buffer.size()) != buffer.size()) {
@@ -417,7 +429,7 @@ static std::optional<u64> FindTicketOffset(const std::array<u8, size>& data) {
417 offset = i + 1; 429 offset = i + 1;
418 break; 430 break;
419 } else if (data[i] != 0x0) { 431 } else if (data[i] != 0x0) {
420 return {}; 432 return std::nullopt;
421 } 433 }
422 } 434 }
423 435
@@ -427,16 +439,18 @@ static std::optional<u64> FindTicketOffset(const std::array<u8, size>& data) {
427std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket, 439std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket,
428 const RSAKeyPair<2048>& key) { 440 const RSAKeyPair<2048>& key) {
429 const auto issuer = ticket.GetData().issuer; 441 const auto issuer = ticket.GetData().issuer;
430 if (IsAllZeroArray(issuer)) 442 if (IsAllZeroArray(issuer)) {
431 return {}; 443 return std::nullopt;
444 }
432 if (issuer[0] != 'R' || issuer[1] != 'o' || issuer[2] != 'o' || issuer[3] != 't') { 445 if (issuer[0] != 'R' || issuer[1] != 'o' || issuer[2] != 'o' || issuer[3] != 't') {
433 LOG_INFO(Crypto, "Attempting to parse ticket with non-standard certificate authority."); 446 LOG_INFO(Crypto, "Attempting to parse ticket with non-standard certificate authority.");
434 } 447 }
435 448
436 Key128 rights_id = ticket.GetData().rights_id; 449 Key128 rights_id = ticket.GetData().rights_id;
437 450
438 if (rights_id == Key128{}) 451 if (rights_id == Key128{}) {
439 return {}; 452 return std::nullopt;
453 }
440 454
441 if (!std::any_of(ticket.GetData().title_key_common_pad.begin(), 455 if (!std::any_of(ticket.GetData().title_key_common_pad.begin(),
442 ticket.GetData().title_key_common_pad.end(), [](u8 b) { return b != 0; })) { 456 ticket.GetData().title_key_common_pad.end(), [](u8 b) { return b != 0; })) {
@@ -468,15 +482,17 @@ std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket,
468 std::array<u8, 0xDF> m_2; 482 std::array<u8, 0xDF> m_2;
469 std::memcpy(m_2.data(), rsa_step.data() + 0x21, m_2.size()); 483 std::memcpy(m_2.data(), rsa_step.data() + 0x21, m_2.size());
470 484
471 if (m_0 != 0) 485 if (m_0 != 0) {
472 return {}; 486 return std::nullopt;
487 }
473 488
474 m_1 = m_1 ^ MGF1<0x20>(m_2); 489 m_1 = m_1 ^ MGF1<0x20>(m_2);
475 m_2 = m_2 ^ MGF1<0xDF>(m_1); 490 m_2 = m_2 ^ MGF1<0xDF>(m_1);
476 491
477 const auto offset = FindTicketOffset(m_2); 492 const auto offset = FindTicketOffset(m_2);
478 if (!offset) 493 if (!offset) {
479 return {}; 494 return std::nullopt;
495 }
480 ASSERT(*offset > 0); 496 ASSERT(*offset > 0);
481 497
482 Key128 key_temp{}; 498 Key128 key_temp{};
@@ -487,8 +503,8 @@ std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket,
487 503
488KeyManager::KeyManager() { 504KeyManager::KeyManager() {
489 // Initialize keys 505 // Initialize keys
490 const std::string hactool_keys_dir = FileUtil::GetHactoolConfigurationPath(); 506 const std::string hactool_keys_dir = Common::FS::GetHactoolConfigurationPath();
491 const std::string yuzu_keys_dir = FileUtil::GetUserPath(FileUtil::UserPath::KeysDir); 507 const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir);
492 if (Settings::values.use_dev_keys) { 508 if (Settings::values.use_dev_keys) {
493 dev_mode = true; 509 dev_mode = true;
494 AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "dev.keys", false); 510 AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "dev.keys", false);
@@ -506,34 +522,39 @@ KeyManager::KeyManager() {
506} 522}
507 523
508static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_t length) { 524static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_t length) {
509 if (base.size() < begin + length) 525 if (base.size() < begin + length) {
510 return false; 526 return false;
527 }
511 return std::all_of(base.begin() + begin, base.begin() + begin + length, 528 return std::all_of(base.begin() + begin, base.begin() + begin + length,
512 [](u8 c) { return std::isxdigit(c); }); 529 [](u8 c) { return std::isxdigit(c); });
513} 530}
514 531
515void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) { 532void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
516 std::ifstream file; 533 std::ifstream file;
517 OpenFStream(file, filename, std::ios_base::in); 534 Common::FS::OpenFStream(file, filename, std::ios_base::in);
518 if (!file.is_open()) 535 if (!file.is_open()) {
519 return; 536 return;
537 }
520 538
521 std::string line; 539 std::string line;
522 while (std::getline(file, line)) { 540 while (std::getline(file, line)) {
523 std::vector<std::string> out; 541 std::vector<std::string> out;
524 std::stringstream stream(line); 542 std::stringstream stream(line);
525 std::string item; 543 std::string item;
526 while (std::getline(stream, item, '=')) 544 while (std::getline(stream, item, '=')) {
527 out.push_back(std::move(item)); 545 out.push_back(std::move(item));
546 }
528 547
529 if (out.size() != 2) 548 if (out.size() != 2) {
530 continue; 549 continue;
550 }
531 551
532 out[0].erase(std::remove(out[0].begin(), out[0].end(), ' '), out[0].end()); 552 out[0].erase(std::remove(out[0].begin(), out[0].end(), ' '), out[0].end());
533 out[1].erase(std::remove(out[1].begin(), out[1].end(), ' '), out[1].end()); 553 out[1].erase(std::remove(out[1].begin(), out[1].end(), ' '), out[1].end());
534 554
535 if (out[0].compare(0, 1, "#") == 0) 555 if (out[0].compare(0, 1, "#") == 0) {
536 continue; 556 continue;
557 }
537 558
538 if (is_title_keys) { 559 if (is_title_keys) {
539 auto rights_id_raw = Common::HexStringToArray<16>(out[0]); 560 auto rights_id_raw = Common::HexStringToArray<16>(out[0]);
@@ -553,14 +574,16 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
553 s256_keys[{index.type, index.field1, index.field2}] = key; 574 s256_keys[{index.type, index.field1, index.field2}] = key;
554 } else if (out[0].compare(0, 8, "keyblob_") == 0 && 575 } else if (out[0].compare(0, 8, "keyblob_") == 0 &&
555 out[0].compare(0, 9, "keyblob_k") != 0) { 576 out[0].compare(0, 9, "keyblob_k") != 0) {
556 if (!ValidCryptoRevisionString(out[0], 8, 2)) 577 if (!ValidCryptoRevisionString(out[0], 8, 2)) {
557 continue; 578 continue;
579 }
558 580
559 const auto index = std::stoul(out[0].substr(8, 2), nullptr, 16); 581 const auto index = std::stoul(out[0].substr(8, 2), nullptr, 16);
560 keyblobs[index] = Common::HexStringToArray<0x90>(out[1]); 582 keyblobs[index] = Common::HexStringToArray<0x90>(out[1]);
561 } else if (out[0].compare(0, 18, "encrypted_keyblob_") == 0) { 583 } else if (out[0].compare(0, 18, "encrypted_keyblob_") == 0) {
562 if (!ValidCryptoRevisionString(out[0], 18, 2)) 584 if (!ValidCryptoRevisionString(out[0], 18, 2)) {
563 continue; 585 continue;
586 }
564 587
565 const auto index = std::stoul(out[0].substr(18, 2), nullptr, 16); 588 const auto index = std::stoul(out[0].substr(18, 2), nullptr, 16);
566 encrypted_keyblobs[index] = Common::HexStringToArray<0xB0>(out[1]); 589 encrypted_keyblobs[index] = Common::HexStringToArray<0xB0>(out[1]);
@@ -568,8 +591,9 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
568 eticket_extended_kek = Common::HexStringToArray<576>(out[1]); 591 eticket_extended_kek = Common::HexStringToArray<576>(out[1]);
569 } else { 592 } else {
570 for (const auto& kv : KEYS_VARIABLE_LENGTH) { 593 for (const auto& kv : KEYS_VARIABLE_LENGTH) {
571 if (!ValidCryptoRevisionString(out[0], kv.second.size(), 2)) 594 if (!ValidCryptoRevisionString(out[0], kv.second.size(), 2)) {
572 continue; 595 continue;
596 }
573 if (out[0].compare(0, kv.second.size(), kv.second) == 0) { 597 if (out[0].compare(0, kv.second.size(), kv.second) == 0) {
574 const auto index = 598 const auto index =
575 std::stoul(out[0].substr(kv.second.size(), 2), nullptr, 16); 599 std::stoul(out[0].substr(kv.second.size(), 2), nullptr, 16);
@@ -604,10 +628,11 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
604 628
605void KeyManager::AttemptLoadKeyFile(const std::string& dir1, const std::string& dir2, 629void KeyManager::AttemptLoadKeyFile(const std::string& dir1, const std::string& dir2,
606 const std::string& filename, bool title) { 630 const std::string& filename, bool title) {
607 if (FileUtil::Exists(dir1 + DIR_SEP + filename)) 631 if (Common::FS::Exists(dir1 + DIR_SEP + filename)) {
608 LoadFromFile(dir1 + DIR_SEP + filename, title); 632 LoadFromFile(dir1 + DIR_SEP + filename, title);
609 else if (FileUtil::Exists(dir2 + DIR_SEP + filename)) 633 } else if (Common::FS::Exists(dir2 + DIR_SEP + filename)) {
610 LoadFromFile(dir2 + DIR_SEP + filename, title); 634 LoadFromFile(dir2 + DIR_SEP + filename, title);
635 }
611} 636}
612 637
613bool KeyManager::BaseDeriveNecessary() const { 638bool KeyManager::BaseDeriveNecessary() const {
@@ -615,8 +640,9 @@ bool KeyManager::BaseDeriveNecessary() const {
615 return !HasKey(key_type, index1, index2); 640 return !HasKey(key_type, index1, index2);
616 }; 641 };
617 642
618 if (check_key_existence(S256KeyType::Header)) 643 if (check_key_existence(S256KeyType::Header)) {
619 return true; 644 return true;
645 }
620 646
621 for (size_t i = 0; i < CURRENT_CRYPTO_REVISION; ++i) { 647 for (size_t i = 0; i < CURRENT_CRYPTO_REVISION; ++i) {
622 if (check_key_existence(S128KeyType::Master, i) || 648 if (check_key_existence(S128KeyType::Master, i) ||
@@ -641,14 +667,16 @@ bool KeyManager::HasKey(S256KeyType id, u64 field1, u64 field2) const {
641} 667}
642 668
643Key128 KeyManager::GetKey(S128KeyType id, u64 field1, u64 field2) const { 669Key128 KeyManager::GetKey(S128KeyType id, u64 field1, u64 field2) const {
644 if (!HasKey(id, field1, field2)) 670 if (!HasKey(id, field1, field2)) {
645 return {}; 671 return {};
672 }
646 return s128_keys.at({id, field1, field2}); 673 return s128_keys.at({id, field1, field2});
647} 674}
648 675
649Key256 KeyManager::GetKey(S256KeyType id, u64 field1, u64 field2) const { 676Key256 KeyManager::GetKey(S256KeyType id, u64 field1, u64 field2) const {
650 if (!HasKey(id, field1, field2)) 677 if (!HasKey(id, field1, field2)) {
651 return {}; 678 return {};
679 }
652 return s256_keys.at({id, field1, field2}); 680 return s256_keys.at({id, field1, field2});
653} 681}
654 682
@@ -670,7 +698,7 @@ Key256 KeyManager::GetBISKey(u8 partition_id) const {
670template <size_t Size> 698template <size_t Size>
671void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname, 699void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname,
672 const std::array<u8, Size>& key) { 700 const std::array<u8, Size>& key) {
673 const std::string yuzu_keys_dir = FileUtil::GetUserPath(FileUtil::UserPath::KeysDir); 701 const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir);
674 std::string filename = "title.keys_autogenerated"; 702 std::string filename = "title.keys_autogenerated";
675 if (category == KeyCategory::Standard) { 703 if (category == KeyCategory::Standard) {
676 filename = dev_mode ? "dev.keys_autogenerated" : "prod.keys_autogenerated"; 704 filename = dev_mode ? "dev.keys_autogenerated" : "prod.keys_autogenerated";
@@ -679,9 +707,9 @@ void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname,
679 } 707 }
680 708
681 const auto path = yuzu_keys_dir + DIR_SEP + filename; 709 const auto path = yuzu_keys_dir + DIR_SEP + filename;
682 const auto add_info_text = !FileUtil::Exists(path); 710 const auto add_info_text = !Common::FS::Exists(path);
683 FileUtil::CreateFullPath(path); 711 Common::FS::CreateFullPath(path);
684 FileUtil::IOFile file{path, "a"}; 712 Common::FS::IOFile file{path, "a"};
685 if (!file.IsOpen()) { 713 if (!file.IsOpen()) {
686 return; 714 return;
687 } 715 }
@@ -765,29 +793,31 @@ void KeyManager::SetKey(S256KeyType id, Key256 key, u64 field1, u64 field2) {
765} 793}
766 794
767bool KeyManager::KeyFileExists(bool title) { 795bool KeyManager::KeyFileExists(bool title) {
768 const std::string hactool_keys_dir = FileUtil::GetHactoolConfigurationPath(); 796 const std::string hactool_keys_dir = Common::FS::GetHactoolConfigurationPath();
769 const std::string yuzu_keys_dir = FileUtil::GetUserPath(FileUtil::UserPath::KeysDir); 797 const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir);
770 if (title) { 798 if (title) {
771 return FileUtil::Exists(hactool_keys_dir + DIR_SEP + "title.keys") || 799 return Common::FS::Exists(hactool_keys_dir + DIR_SEP + "title.keys") ||
772 FileUtil::Exists(yuzu_keys_dir + DIR_SEP + "title.keys"); 800 Common::FS::Exists(yuzu_keys_dir + DIR_SEP + "title.keys");
773 } 801 }
774 802
775 if (Settings::values.use_dev_keys) { 803 if (Settings::values.use_dev_keys) {
776 return FileUtil::Exists(hactool_keys_dir + DIR_SEP + "dev.keys") || 804 return Common::FS::Exists(hactool_keys_dir + DIR_SEP + "dev.keys") ||
777 FileUtil::Exists(yuzu_keys_dir + DIR_SEP + "dev.keys"); 805 Common::FS::Exists(yuzu_keys_dir + DIR_SEP + "dev.keys");
778 } 806 }
779 807
780 return FileUtil::Exists(hactool_keys_dir + DIR_SEP + "prod.keys") || 808 return Common::FS::Exists(hactool_keys_dir + DIR_SEP + "prod.keys") ||
781 FileUtil::Exists(yuzu_keys_dir + DIR_SEP + "prod.keys"); 809 Common::FS::Exists(yuzu_keys_dir + DIR_SEP + "prod.keys");
782} 810}
783 811
784void KeyManager::DeriveSDSeedLazy() { 812void KeyManager::DeriveSDSeedLazy() {
785 if (HasKey(S128KeyType::SDSeed)) 813 if (HasKey(S128KeyType::SDSeed)) {
786 return; 814 return;
815 }
787 816
788 const auto res = DeriveSDSeed(); 817 const auto res = DeriveSDSeed();
789 if (res) 818 if (res) {
790 SetKey(S128KeyType::SDSeed, *res); 819 SetKey(S128KeyType::SDSeed, *res);
820 }
791} 821}
792 822
793static Key128 CalculateCMAC(const u8* source, size_t size, const Key128& key) { 823static Key128 CalculateCMAC(const u8* source, size_t size, const Key128& key) {
@@ -799,11 +829,13 @@ static Key128 CalculateCMAC(const u8* source, size_t size, const Key128& key) {
799} 829}
800 830
801void KeyManager::DeriveBase() { 831void KeyManager::DeriveBase() {
802 if (!BaseDeriveNecessary()) 832 if (!BaseDeriveNecessary()) {
803 return; 833 return;
834 }
804 835
805 if (!HasKey(S128KeyType::SecureBoot) || !HasKey(S128KeyType::TSEC)) 836 if (!HasKey(S128KeyType::SecureBoot) || !HasKey(S128KeyType::TSEC)) {
806 return; 837 return;
838 }
807 839
808 const auto has_bis = [this](u64 id) { 840 const auto has_bis = [this](u64 id) {
809 return HasKey(S128KeyType::BIS, id, static_cast<u64>(BISKeyType::Crypto)) && 841 return HasKey(S128KeyType::BIS, id, static_cast<u64>(BISKeyType::Crypto)) &&
@@ -820,10 +852,11 @@ void KeyManager::DeriveBase() {
820 static_cast<u64>(BISKeyType::Tweak)); 852 static_cast<u64>(BISKeyType::Tweak));
821 }; 853 };
822 854
823 if (has_bis(2) && !has_bis(3)) 855 if (has_bis(2) && !has_bis(3)) {
824 copy_bis(2, 3); 856 copy_bis(2, 3);
825 else if (has_bis(3) && !has_bis(2)) 857 } else if (has_bis(3) && !has_bis(2)) {
826 copy_bis(3, 2); 858 copy_bis(3, 2);
859 }
827 860
828 std::bitset<32> revisions(0xFFFFFFFF); 861 std::bitset<32> revisions(0xFFFFFFFF);
829 for (size_t i = 0; i < revisions.size(); ++i) { 862 for (size_t i = 0; i < revisions.size(); ++i) {
@@ -833,15 +866,17 @@ void KeyManager::DeriveBase() {
833 } 866 }
834 } 867 }
835 868
836 if (!revisions.any()) 869 if (!revisions.any()) {
837 return; 870 return;
871 }
838 872
839 const auto sbk = GetKey(S128KeyType::SecureBoot); 873 const auto sbk = GetKey(S128KeyType::SecureBoot);
840 const auto tsec = GetKey(S128KeyType::TSEC); 874 const auto tsec = GetKey(S128KeyType::TSEC);
841 875
842 for (size_t i = 0; i < revisions.size(); ++i) { 876 for (size_t i = 0; i < revisions.size(); ++i) {
843 if (!revisions[i]) 877 if (!revisions[i]) {
844 continue; 878 continue;
879 }
845 880
846 // Derive keyblob key 881 // Derive keyblob key
847 const auto key = DeriveKeyblobKey( 882 const auto key = DeriveKeyblobKey(
@@ -850,16 +885,18 @@ void KeyManager::DeriveBase() {
850 SetKey(S128KeyType::Keyblob, key, i); 885 SetKey(S128KeyType::Keyblob, key, i);
851 886
852 // Derive keyblob MAC key 887 // Derive keyblob MAC key
853 if (!HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC))) 888 if (!HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC))) {
854 continue; 889 continue;
890 }
855 891
856 const auto mac_key = DeriveKeyblobMACKey( 892 const auto mac_key = DeriveKeyblobMACKey(
857 key, GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC))); 893 key, GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC)));
858 SetKey(S128KeyType::KeyblobMAC, mac_key, i); 894 SetKey(S128KeyType::KeyblobMAC, mac_key, i);
859 895
860 Key128 cmac = CalculateCMAC(encrypted_keyblobs[i].data() + 0x10, 0xA0, mac_key); 896 Key128 cmac = CalculateCMAC(encrypted_keyblobs[i].data() + 0x10, 0xA0, mac_key);
861 if (std::memcmp(cmac.data(), encrypted_keyblobs[i].data(), cmac.size()) != 0) 897 if (std::memcmp(cmac.data(), encrypted_keyblobs[i].data(), cmac.size()) != 0) {
862 continue; 898 continue;
899 }
863 900
864 // Decrypt keyblob 901 // Decrypt keyblob
865 if (keyblobs[i] == std::array<u8, 0x90>{}) { 902 if (keyblobs[i] == std::array<u8, 0x90>{}) {
@@ -883,16 +920,19 @@ void KeyManager::DeriveBase() {
883 920
884 revisions.set(); 921 revisions.set();
885 for (size_t i = 0; i < revisions.size(); ++i) { 922 for (size_t i = 0; i < revisions.size(); ++i) {
886 if (!HasKey(S128KeyType::Master, i)) 923 if (!HasKey(S128KeyType::Master, i)) {
887 revisions.reset(i); 924 revisions.reset(i);
925 }
888 } 926 }
889 927
890 if (!revisions.any()) 928 if (!revisions.any()) {
891 return; 929 return;
930 }
892 931
893 for (size_t i = 0; i < revisions.size(); ++i) { 932 for (size_t i = 0; i < revisions.size(); ++i) {
894 if (!revisions[i]) 933 if (!revisions[i]) {
895 continue; 934 continue;
935 }
896 936
897 // Derive general purpose keys 937 // Derive general purpose keys
898 DeriveGeneralPurposeKeys(i); 938 DeriveGeneralPurposeKeys(i);
@@ -922,16 +962,19 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) {
922 const auto es = Core::System::GetInstance().GetContentProvider().GetEntry( 962 const auto es = Core::System::GetInstance().GetContentProvider().GetEntry(
923 0x0100000000000033, FileSys::ContentRecordType::Program); 963 0x0100000000000033, FileSys::ContentRecordType::Program);
924 964
925 if (es == nullptr) 965 if (es == nullptr) {
926 return; 966 return;
967 }
927 968
928 const auto exefs = es->GetExeFS(); 969 const auto exefs = es->GetExeFS();
929 if (exefs == nullptr) 970 if (exefs == nullptr) {
930 return; 971 return;
972 }
931 973
932 const auto main = exefs->GetFile("main"); 974 const auto main = exefs->GetFile("main");
933 if (main == nullptr) 975 if (main == nullptr) {
934 return; 976 return;
977 }
935 978
936 const auto bytes = main->ReadAllBytes(); 979 const auto bytes = main->ReadAllBytes();
937 980
@@ -941,16 +984,19 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) {
941 const auto seed3 = data.GetRSAKekSeed3(); 984 const auto seed3 = data.GetRSAKekSeed3();
942 const auto mask0 = data.GetRSAKekMask0(); 985 const auto mask0 = data.GetRSAKekMask0();
943 986
944 if (eticket_kek != Key128{}) 987 if (eticket_kek != Key128{}) {
945 SetKey(S128KeyType::Source, eticket_kek, static_cast<size_t>(SourceKeyType::ETicketKek)); 988 SetKey(S128KeyType::Source, eticket_kek, static_cast<size_t>(SourceKeyType::ETicketKek));
989 }
946 if (eticket_kekek != Key128{}) { 990 if (eticket_kekek != Key128{}) {
947 SetKey(S128KeyType::Source, eticket_kekek, 991 SetKey(S128KeyType::Source, eticket_kekek,
948 static_cast<size_t>(SourceKeyType::ETicketKekek)); 992 static_cast<size_t>(SourceKeyType::ETicketKekek));
949 } 993 }
950 if (seed3 != Key128{}) 994 if (seed3 != Key128{}) {
951 SetKey(S128KeyType::RSAKek, seed3, static_cast<size_t>(RSAKekType::Seed3)); 995 SetKey(S128KeyType::RSAKek, seed3, static_cast<size_t>(RSAKekType::Seed3));
952 if (mask0 != Key128{}) 996 }
997 if (mask0 != Key128{}) {
953 SetKey(S128KeyType::RSAKek, mask0, static_cast<size_t>(RSAKekType::Mask0)); 998 SetKey(S128KeyType::RSAKek, mask0, static_cast<size_t>(RSAKekType::Mask0));
999 }
954 if (eticket_kek == Key128{} || eticket_kekek == Key128{} || seed3 == Key128{} || 1000 if (eticket_kek == Key128{} || eticket_kekek == Key128{} || seed3 == Key128{} ||
955 mask0 == Key128{}) { 1001 mask0 == Key128{}) {
956 return; 1002 return;
@@ -976,8 +1022,9 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) {
976 AESCipher<Key128> es_kek(temp_kekek, Mode::ECB); 1022 AESCipher<Key128> es_kek(temp_kekek, Mode::ECB);
977 es_kek.Transcode(eticket_kek.data(), eticket_kek.size(), eticket_final.data(), Op::Decrypt); 1023 es_kek.Transcode(eticket_kek.data(), eticket_kek.size(), eticket_final.data(), Op::Decrypt);
978 1024
979 if (eticket_final == Key128{}) 1025 if (eticket_final == Key128{}) {
980 return; 1026 return;
1027 }
981 1028
982 SetKey(S128KeyType::ETicketRSAKek, eticket_final); 1029 SetKey(S128KeyType::ETicketRSAKek, eticket_final);
983 1030
@@ -992,18 +1039,20 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) {
992void KeyManager::PopulateTickets() { 1039void KeyManager::PopulateTickets() {
993 const auto rsa_key = GetETicketRSAKey(); 1040 const auto rsa_key = GetETicketRSAKey();
994 1041
995 if (rsa_key == RSAKeyPair<2048>{}) 1042 if (rsa_key == RSAKeyPair<2048>{}) {
996 return; 1043 return;
1044 }
997 1045
998 if (!common_tickets.empty() && !personal_tickets.empty()) 1046 if (!common_tickets.empty() && !personal_tickets.empty()) {
999 return; 1047 return;
1048 }
1000 1049
1001 const FileUtil::IOFile save1(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + 1050 const Common::FS::IOFile save1(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) +
1002 "/system/save/80000000000000e1", 1051 "/system/save/80000000000000e1",
1003 "rb+"); 1052 "rb+");
1004 const FileUtil::IOFile save2(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + 1053 const Common::FS::IOFile save2(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) +
1005 "/system/save/80000000000000e2", 1054 "/system/save/80000000000000e2",
1006 "rb+"); 1055 "rb+");
1007 1056
1008 const auto blob2 = GetTicketblob(save2); 1057 const auto blob2 = GetTicketblob(save2);
1009 auto res = GetTicketblob(save1); 1058 auto res = GetTicketblob(save1);
@@ -1013,8 +1062,10 @@ void KeyManager::PopulateTickets() {
1013 for (std::size_t i = 0; i < res.size(); ++i) { 1062 for (std::size_t i = 0; i < res.size(); ++i) {
1014 const auto common = i < idx; 1063 const auto common = i < idx;
1015 const auto pair = ParseTicket(res[i], rsa_key); 1064 const auto pair = ParseTicket(res[i], rsa_key);
1016 if (!pair) 1065 if (!pair) {
1017 continue; 1066 continue;
1067 }
1068
1018 const auto& [rid, key] = *pair; 1069 const auto& [rid, key] = *pair;
1019 u128 rights_id; 1070 u128 rights_id;
1020 std::memcpy(rights_id.data(), rid.data(), rid.size()); 1071 std::memcpy(rights_id.data(), rid.data(), rid.size());
@@ -1043,27 +1094,33 @@ void KeyManager::SynthesizeTickets() {
1043} 1094}
1044 1095
1045void KeyManager::SetKeyWrapped(S128KeyType id, Key128 key, u64 field1, u64 field2) { 1096void KeyManager::SetKeyWrapped(S128KeyType id, Key128 key, u64 field1, u64 field2) {
1046 if (key == Key128{}) 1097 if (key == Key128{}) {
1047 return; 1098 return;
1099 }
1048 SetKey(id, key, field1, field2); 1100 SetKey(id, key, field1, field2);
1049} 1101}
1050 1102
1051void KeyManager::SetKeyWrapped(S256KeyType id, Key256 key, u64 field1, u64 field2) { 1103void KeyManager::SetKeyWrapped(S256KeyType id, Key256 key, u64 field1, u64 field2) {
1052 if (key == Key256{}) 1104 if (key == Key256{}) {
1053 return; 1105 return;
1106 }
1107
1054 SetKey(id, key, field1, field2); 1108 SetKey(id, key, field1, field2);
1055} 1109}
1056 1110
1057void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) { 1111void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) {
1058 if (!BaseDeriveNecessary()) 1112 if (!BaseDeriveNecessary()) {
1059 return; 1113 return;
1114 }
1060 1115
1061 if (!data.HasBoot0()) 1116 if (!data.HasBoot0()) {
1062 return; 1117 return;
1118 }
1063 1119
1064 for (size_t i = 0; i < encrypted_keyblobs.size(); ++i) { 1120 for (size_t i = 0; i < encrypted_keyblobs.size(); ++i) {
1065 if (encrypted_keyblobs[i] != std::array<u8, 0xB0>{}) 1121 if (encrypted_keyblobs[i] != std::array<u8, 0xB0>{}) {
1066 continue; 1122 continue;
1123 }
1067 encrypted_keyblobs[i] = data.GetEncryptedKeyblob(i); 1124 encrypted_keyblobs[i] = data.GetEncryptedKeyblob(i);
1068 WriteKeyToFile<0xB0>(KeyCategory::Console, fmt::format("encrypted_keyblob_{:02X}", i), 1125 WriteKeyToFile<0xB0>(KeyCategory::Console, fmt::format("encrypted_keyblob_{:02X}", i),
1069 encrypted_keyblobs[i]); 1126 encrypted_keyblobs[i]);
@@ -1085,8 +1142,9 @@ void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) {
1085 static_cast<u64>(SourceKeyType::Keyblob), i); 1142 static_cast<u64>(SourceKeyType::Keyblob), i);
1086 } 1143 }
1087 1144
1088 if (data.HasFuses()) 1145 if (data.HasFuses()) {
1089 SetKeyWrapped(S128KeyType::SecureBoot, data.GetSecureBootKey()); 1146 SetKeyWrapped(S128KeyType::SecureBoot, data.GetSecureBootKey());
1147 }
1090 1148
1091 DeriveBase(); 1149 DeriveBase();
1092 1150
@@ -1100,8 +1158,9 @@ void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) {
1100 1158
1101 const auto masters = data.GetTZMasterKeys(latest_master); 1159 const auto masters = data.GetTZMasterKeys(latest_master);
1102 for (size_t i = 0; i < masters.size(); ++i) { 1160 for (size_t i = 0; i < masters.size(); ++i) {
1103 if (masters[i] != Key128{} && !HasKey(S128KeyType::Master, i)) 1161 if (masters[i] != Key128{} && !HasKey(S128KeyType::Master, i)) {
1104 SetKey(S128KeyType::Master, masters[i], i); 1162 SetKey(S128KeyType::Master, masters[i], i);
1163 }
1105 } 1164 }
1106 1165
1107 DeriveBase(); 1166 DeriveBase();
@@ -1111,8 +1170,9 @@ void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) {
1111 1170
1112 std::array<Key128, 0x20> package2_keys{}; 1171 std::array<Key128, 0x20> package2_keys{};
1113 for (size_t i = 0; i < package2_keys.size(); ++i) { 1172 for (size_t i = 0; i < package2_keys.size(); ++i) {
1114 if (HasKey(S128KeyType::Package2, i)) 1173 if (HasKey(S128KeyType::Package2, i)) {
1115 package2_keys[i] = GetKey(S128KeyType::Package2, i); 1174 package2_keys[i] = GetKey(S128KeyType::Package2, i);
1175 }
1116 } 1176 }
1117 data.DecryptPackage2(package2_keys, Package2Type::NormalMain); 1177 data.DecryptPackage2(package2_keys, Package2Type::NormalMain);
1118 1178
@@ -1150,12 +1210,15 @@ const std::map<u128, Ticket>& KeyManager::GetPersonalizedTickets() const {
1150 1210
1151bool KeyManager::AddTicketCommon(Ticket raw) { 1211bool KeyManager::AddTicketCommon(Ticket raw) {
1152 const auto rsa_key = GetETicketRSAKey(); 1212 const auto rsa_key = GetETicketRSAKey();
1153 if (rsa_key == RSAKeyPair<2048>{}) 1213 if (rsa_key == RSAKeyPair<2048>{}) {
1154 return false; 1214 return false;
1215 }
1155 1216
1156 const auto pair = ParseTicket(raw, rsa_key); 1217 const auto pair = ParseTicket(raw, rsa_key);
1157 if (!pair) 1218 if (!pair) {
1158 return false; 1219 return false;
1220 }
1221
1159 const auto& [rid, key] = *pair; 1222 const auto& [rid, key] = *pair;
1160 u128 rights_id; 1223 u128 rights_id;
1161 std::memcpy(rights_id.data(), rid.data(), rid.size()); 1224 std::memcpy(rights_id.data(), rid.data(), rid.size());
@@ -1166,12 +1229,15 @@ bool KeyManager::AddTicketCommon(Ticket raw) {
1166 1229
1167bool KeyManager::AddTicketPersonalized(Ticket raw) { 1230bool KeyManager::AddTicketPersonalized(Ticket raw) {
1168 const auto rsa_key = GetETicketRSAKey(); 1231 const auto rsa_key = GetETicketRSAKey();
1169 if (rsa_key == RSAKeyPair<2048>{}) 1232 if (rsa_key == RSAKeyPair<2048>{}) {
1170 return false; 1233 return false;
1234 }
1171 1235
1172 const auto pair = ParseTicket(raw, rsa_key); 1236 const auto pair = ParseTicket(raw, rsa_key);
1173 if (!pair) 1237 if (!pair) {
1174 return false; 1238 return false;
1239 }
1240
1175 const auto& [rid, key] = *pair; 1241 const auto& [rid, key] = *pair;
1176 u128 rights_id; 1242 u128 rights_id;
1177 std::memcpy(rights_id.data(), rid.data(), rid.size()); 1243 std::memcpy(rights_id.data(), rid.data(), rid.size());