summaryrefslogtreecommitdiff
path: root/src/core/crypto/key_manager.cpp
diff options
context:
space:
mode:
authorGravatar Zach Hilman2019-04-10 10:22:04 -0400
committerGravatar Zach Hilman2019-07-07 21:38:33 -0400
commite35fac205406c6d485bd755c4260a69f312eeaf6 (patch)
tree3cd23d06902fc9c8339716be849265d8dda7b281 /src/core/crypto/key_manager.cpp
parentkey_manager: Add equality operator for RSAKeyPair (diff)
downloadyuzu-e35fac205406c6d485bd755c4260a69f312eeaf6.tar.gz
yuzu-e35fac205406c6d485bd755c4260a69f312eeaf6.tar.xz
yuzu-e35fac205406c6d485bd755c4260a69f312eeaf6.zip
key_manager: Add accessors/helpers for ticket management
Diffstat (limited to 'src/core/crypto/key_manager.cpp')
-rw-r--r--src/core/crypto/key_manager.cpp100
1 files changed, 86 insertions, 14 deletions
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index 6dd633363..ef139902d 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -135,6 +135,28 @@ void KeyManager::DeriveGeneralPurposeKeys(std::size_t crypto_revision) {
135 } 135 }
136} 136}
137 137
138RSAKeyPair<2048> KeyManager::GetETicketRSAKey() {
139 if (eticket_extended_kek == std::array<u8, 576>{} || !HasKey(S128KeyType::ETicketRSAKek))
140 return {};
141
142 const auto eticket_final = GetKey(S128KeyType::ETicketRSAKek);
143
144 std::vector<u8> extended_iv(0x10);
145 std::memcpy(extended_iv.data(), eticket_extended_kek.data(), extended_iv.size());
146 std::array<u8, 0x230> extended_dec{};
147 AESCipher<Key128> rsa_1(eticket_final, Mode::CTR);
148 rsa_1.SetIV(extended_iv);
149 rsa_1.Transcode(eticket_extended_kek.data() + 0x10, eticket_extended_kek.size() - 0x10,
150 extended_dec.data(), Op::Decrypt);
151
152 RSAKeyPair<2048> rsa_key{};
153 std::memcpy(rsa_key.decryption_key.data(), extended_dec.data(), rsa_key.decryption_key.size());
154 std::memcpy(rsa_key.modulus.data(), extended_dec.data() + 0x100, rsa_key.modulus.size());
155 std::memcpy(rsa_key.exponent.data(), extended_dec.data() + 0x200, rsa_key.exponent.size());
156
157 return rsa_key;
158}
159
138Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source) { 160Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source) {
139 AESCipher<Key128> mac_cipher(keyblob_key, Mode::ECB); 161 AESCipher<Key128> mac_cipher(keyblob_key, Mode::ECB);
140 Key128 mac_key{}; 162 Key128 mac_key{};
@@ -450,6 +472,8 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
450 472
451 const auto index = std::stoul(out[0].substr(18, 2), nullptr, 16); 473 const auto index = std::stoul(out[0].substr(18, 2), nullptr, 16);
452 encrypted_keyblobs[index] = Common::HexStringToArray<0xB0>(out[1]); 474 encrypted_keyblobs[index] = Common::HexStringToArray<0xB0>(out[1]);
475 } else if (out[0].compare(0, 20, "eticket_extended_kek") == 0) {
476 eticket_extended_kek = Common::HexStringToArray<576>(out[1]);
453 } else { 477 } else {
454 for (const auto& kv : KEYS_VARIABLE_LENGTH) { 478 for (const auto& kv : KEYS_VARIABLE_LENGTH) {
455 if (!ValidCryptoRevisionString(out[0], kv.second.size(), 2)) 479 if (!ValidCryptoRevisionString(out[0], kv.second.size(), 2))
@@ -862,20 +886,19 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) {
862 // Titlekeys 886 // Titlekeys
863 data.DecryptProdInfo(GetBISKey(0)); 887 data.DecryptProdInfo(GetBISKey(0));
864 888
865 const auto eticket_extended_kek = data.GetETicketExtendedKek(); 889 eticket_extended_kek = data.GetETicketExtendedKek();
890 WriteKeyToFile(KeyCategory::Console, "eticket_extended_kek", eticket_extended_kek);
891 PopulateTickets();
892}
866 893
867 std::vector<u8> extended_iv(0x10); 894void KeyManager::PopulateTickets() {
868 std::memcpy(extended_iv.data(), eticket_extended_kek.data(), extended_iv.size()); 895 const auto rsa_key = GetETicketRSAKey();
869 std::array<u8, 0x230> extended_dec{};
870 AESCipher<Key128> rsa_1(eticket_final, Mode::CTR);
871 rsa_1.SetIV(extended_iv);
872 rsa_1.Transcode(eticket_extended_kek.data() + 0x10, eticket_extended_kek.size() - 0x10,
873 extended_dec.data(), Op::Decrypt);
874 896
875 RSAKeyPair<2048> rsa_key{}; 897 if (rsa_key == RSAKeyPair<2048>{})
876 std::memcpy(rsa_key.decryption_key.data(), extended_dec.data(), rsa_key.decryption_key.size()); 898 return;
877 std::memcpy(rsa_key.modulus.data(), extended_dec.data() + 0x100, rsa_key.modulus.size()); 899
878 std::memcpy(rsa_key.exponent.data(), extended_dec.data() + 0x200, rsa_key.exponent.size()); 900 if (!common_tickets.empty() && !personal_tickets.empty())
901 return;
879 902
880 const FileUtil::IOFile save1(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + 903 const FileUtil::IOFile save1(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) +
881 "/system/save/80000000000000e1", 904 "/system/save/80000000000000e1",
@@ -886,15 +909,24 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) {
886 909
887 const auto blob2 = GetTicketblob(save2); 910 const auto blob2 = GetTicketblob(save2);
888 auto res = GetTicketblob(save1); 911 auto res = GetTicketblob(save1);
912 const auto idx = res.size();
889 res.insert(res.end(), blob2.begin(), blob2.end()); 913 res.insert(res.end(), blob2.begin(), blob2.end());
890 914
891 for (const auto& raw : res) { 915 for (std::size_t i = 0; i < res.size(); ++i) {
892 const auto pair = ParseTicket(raw, rsa_key); 916 const auto common = i < idx;
917 const auto pair = ParseTicket(res[i], rsa_key);
893 if (!pair) 918 if (!pair)
894 continue; 919 continue;
895 const auto& [rid, key] = *pair; 920 const auto& [rid, key] = *pair;
896 u128 rights_id; 921 u128 rights_id;
897 std::memcpy(rights_id.data(), rid.data(), rid.size()); 922 std::memcpy(rights_id.data(), rid.data(), rid.size());
923
924 if (common) {
925 common_tickets[rights_id] = res[i];
926 } else {
927 personal_tickets[rights_id] = res[i];
928 }
929
898 SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]); 930 SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
899 } 931 }
900} 932}
@@ -997,6 +1029,46 @@ void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) {
997 DeriveBase(); 1029 DeriveBase();
998} 1030}
999 1031
1032const std::map<u128, TicketRaw>& KeyManager::GetCommonTickets() const {
1033 return common_tickets;
1034}
1035
1036const std::map<u128, TicketRaw>& KeyManager::GetPersonalizedTickets() const {
1037 return personal_tickets;
1038}
1039
1040bool KeyManager::AddTicketCommon(TicketRaw raw) {
1041 const auto rsa_key = GetETicketRSAKey();
1042 if (rsa_key == RSAKeyPair<2048>{})
1043 return false;
1044
1045 const auto pair = ParseTicket(raw, rsa_key);
1046 if (!pair)
1047 return false;
1048 const auto& [rid, key] = *pair;
1049 u128 rights_id;
1050 std::memcpy(rights_id.data(), rid.data(), rid.size());
1051 common_tickets[rights_id] = raw;
1052 SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
1053 return true;
1054}
1055
1056bool KeyManager::AddTicketPersonalized(TicketRaw raw) {
1057 const auto rsa_key = GetETicketRSAKey();
1058 if (rsa_key == RSAKeyPair<2048>{})
1059 return false;
1060
1061 const auto pair = ParseTicket(raw, rsa_key);
1062 if (!pair)
1063 return false;
1064 const auto& [rid, key] = *pair;
1065 u128 rights_id;
1066 std::memcpy(rights_id.data(), rid.data(), rid.size());
1067 common_tickets[rights_id] = raw;
1068 SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
1069 return true;
1070}
1071
1000const boost::container::flat_map<std::string, KeyIndex<S128KeyType>> KeyManager::s128_file_id = { 1072const boost::container::flat_map<std::string, KeyIndex<S128KeyType>> KeyManager::s128_file_id = {
1001 {"eticket_rsa_kek", {S128KeyType::ETicketRSAKek, 0, 0}}, 1073 {"eticket_rsa_kek", {S128KeyType::ETicketRSAKek, 0, 0}},
1002 {"eticket_rsa_kek_source", 1074 {"eticket_rsa_kek_source",