diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/crypto/key_manager.cpp | 124 | ||||
| -rw-r--r-- | src/core/crypto/key_manager.h | 96 | ||||
| -rw-r--r-- | src/core/hle/service/es/es.cpp | 18 |
3 files changed, 194 insertions, 44 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 @@ | |||
| 37 | namespace Core::Crypto { | 37 | namespace Core::Crypto { |
| 38 | 38 | ||
| 39 | constexpr u64 CURRENT_CRYPTO_REVISION = 0x5; | 39 | constexpr u64 CURRENT_CRYPTO_REVISION = 0x5; |
| 40 | constexpr u64 FULL_TICKET_SIZE = 0x400; | ||
| 40 | 41 | ||
| 41 | using namespace Common; | 42 | using 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 | ||
| 59 | u64 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 | |||
| 74 | u64 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 | |||
| 88 | TicketData& 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 | |||
| 103 | const 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 | |||
| 118 | u64 Ticket::GetSize() const { | ||
| 119 | return sizeof(SignatureType) + GetSignatureTypeDataSize(sig_type) + | ||
| 120 | GetSignatureTypePaddingSize(sig_type) + sizeof(TicketData); | ||
| 121 | } | ||
| 122 | |||
| 123 | Ticket 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 | |||
| 58 | Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed) { | 131 | Key128 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 | ||
| 262 | std::vector<TicketRaw> GetTicketblob(const FileUtil::IOFile& ticket_save) { | 335 | std::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 | ||
| 330 | std::optional<std::pair<Key128, Key128>> ParseTicket(const TicketRaw& ticket, | 403 | std::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 | ||
| 416 | static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_t length) { | 496 | static 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 | ||
| 1032 | const std::map<u128, TicketRaw>& KeyManager::GetCommonTickets() const { | 1112 | const std::map<u128, Ticket>& KeyManager::GetCommonTickets() const { |
| 1033 | return common_tickets; | 1113 | return common_tickets; |
| 1034 | } | 1114 | } |
| 1035 | 1115 | ||
| 1036 | const std::map<u128, TicketRaw>& KeyManager::GetPersonalizedTickets() const { | 1116 | const std::map<u128, Ticket>& KeyManager::GetPersonalizedTickets() const { |
| 1037 | return personal_tickets; | 1117 | return personal_tickets; |
| 1038 | } | 1118 | } |
| 1039 | 1119 | ||
| 1040 | bool KeyManager::AddTicketCommon(TicketRaw raw) { | 1120 | bool 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 | ||
| 1056 | bool KeyManager::AddTicketPersonalized(TicketRaw raw) { | 1136 | bool 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; |
diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h index 8a67b172d..ff6bd08e1 100644 --- a/src/core/crypto/key_manager.h +++ b/src/core/crypto/key_manager.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include <boost/container/flat_map.hpp> | 12 | #include <boost/container/flat_map.hpp> |
| 13 | #include <fmt/format.h> | 13 | #include <fmt/format.h> |
| 14 | #include "common/common_funcs.h" | ||
| 14 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 15 | #include "core/crypto/partition_data_manager.h" | 16 | #include "core/crypto/partition_data_manager.h" |
| 16 | #include "core/file_sys/vfs_types.h" | 17 | #include "core/file_sys/vfs_types.h" |
| @@ -30,7 +31,76 @@ constexpr u64 TICKET_FILE_TITLEKEY_OFFSET = 0x180; | |||
| 30 | using Key128 = std::array<u8, 0x10>; | 31 | using Key128 = std::array<u8, 0x10>; |
| 31 | using Key256 = std::array<u8, 0x20>; | 32 | using Key256 = std::array<u8, 0x20>; |
| 32 | using SHA256Hash = std::array<u8, 0x20>; | 33 | using SHA256Hash = std::array<u8, 0x20>; |
| 33 | using TicketRaw = std::array<u8, 0x400>; | 34 | |
| 35 | enum class SignatureType { | ||
| 36 | RSA_4096_SHA1 = 0x10000, | ||
| 37 | RSA_2048_SHA1 = 0x10001, | ||
| 38 | ECDSA_SHA1 = 0x10002, | ||
| 39 | RSA_4096_SHA256 = 0x10003, | ||
| 40 | RSA_2048_SHA256 = 0x10004, | ||
| 41 | ECDSA_SHA256 = 0x10005, | ||
| 42 | }; | ||
| 43 | |||
| 44 | u64 GetSignatureTypeDataSize(SignatureType type); | ||
| 45 | u64 GetSignatureTypePaddingSize(SignatureType type); | ||
| 46 | |||
| 47 | enum class TitleKeyType : u8 { | ||
| 48 | Common = 0, | ||
| 49 | Personalized = 1, | ||
| 50 | }; | ||
| 51 | |||
| 52 | struct TicketData { | ||
| 53 | std::array<u8, 0x40> issuer; | ||
| 54 | union { | ||
| 55 | std::array<u8, 0x100> title_key_block; | ||
| 56 | |||
| 57 | struct { | ||
| 58 | Key128 title_key_common; | ||
| 59 | std::array<u8, 0xF0> title_key_common_pad; | ||
| 60 | }; | ||
| 61 | }; | ||
| 62 | |||
| 63 | INSERT_PADDING_BYTES(0x1); | ||
| 64 | TitleKeyType type; | ||
| 65 | INSERT_PADDING_BYTES(0x3); | ||
| 66 | u8 revision; | ||
| 67 | INSERT_PADDING_BYTES(0xA); | ||
| 68 | u64 ticket_id; | ||
| 69 | u64 device_id; | ||
| 70 | std::array<u8, 0x10> rights_id; | ||
| 71 | u32 account_id; | ||
| 72 | INSERT_PADDING_BYTES(0x14C); | ||
| 73 | }; | ||
| 74 | static_assert(sizeof(TicketData) == 0x2C0, "TicketData has incorrect size."); | ||
| 75 | |||
| 76 | struct Ticket { | ||
| 77 | SignatureType sig_type; | ||
| 78 | union { | ||
| 79 | struct { | ||
| 80 | std::array<u8, 0x200> sig_data; | ||
| 81 | INSERT_PADDING_BYTES(0x3C); | ||
| 82 | TicketData data; | ||
| 83 | } rsa_4096; | ||
| 84 | |||
| 85 | struct { | ||
| 86 | std::array<u8, 0x100> sig_data; | ||
| 87 | INSERT_PADDING_BYTES(0x3C); | ||
| 88 | TicketData data; | ||
| 89 | } rsa_2048; | ||
| 90 | |||
| 91 | struct { | ||
| 92 | std::array<u8, 0x3C> sig_data; | ||
| 93 | INSERT_PADDING_BYTES(0x40); | ||
| 94 | TicketData data; | ||
| 95 | } ecdsa; | ||
| 96 | }; | ||
| 97 | |||
| 98 | TicketData& GetData(); | ||
| 99 | const TicketData& GetData() const; | ||
| 100 | u64 GetSize() const; | ||
| 101 | |||
| 102 | static Ticket SynthesizeCommon(Key128 title_key, std::array<u8, 0x10> rights_id); | ||
| 103 | }; | ||
| 34 | 104 | ||
| 35 | static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big."); | 105 | static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big."); |
| 36 | static_assert(sizeof(Key256) == 32, "Key256 must be 256 bytes big."); | 106 | static_assert(sizeof(Key256) == 32, "Key256 must be 256 bytes big."); |
| @@ -158,8 +228,8 @@ public: | |||
| 158 | 228 | ||
| 159 | static bool KeyFileExists(bool title); | 229 | static bool KeyFileExists(bool title); |
| 160 | 230 | ||
| 161 | // Call before using the sd seed to attempt to derive it if it dosen't exist. Needs system save | 231 | // Call before using the sd seed to attempt to derive it if it dosen't exist. Needs system |
| 162 | // 8*43 and the private file to exist. | 232 | // save 8*43 and the private file to exist. |
| 163 | void DeriveSDSeedLazy(); | 233 | void DeriveSDSeedLazy(); |
| 164 | 234 | ||
| 165 | bool BaseDeriveNecessary() const; | 235 | bool BaseDeriveNecessary() const; |
| @@ -169,19 +239,19 @@ public: | |||
| 169 | 239 | ||
| 170 | void PopulateFromPartitionData(PartitionDataManager& data); | 240 | void PopulateFromPartitionData(PartitionDataManager& data); |
| 171 | 241 | ||
| 172 | const std::map<u128, TicketRaw>& GetCommonTickets() const; | 242 | const std::map<u128, Ticket>& GetCommonTickets() const; |
| 173 | const std::map<u128, TicketRaw>& GetPersonalizedTickets() const; | 243 | const std::map<u128, Ticket>& GetPersonalizedTickets() const; |
| 174 | 244 | ||
| 175 | bool AddTicketCommon(TicketRaw raw); | 245 | bool AddTicketCommon(Ticket raw); |
| 176 | bool AddTicketPersonalized(TicketRaw raw); | 246 | bool AddTicketPersonalized(Ticket raw); |
| 177 | 247 | ||
| 178 | private: | 248 | private: |
| 179 | std::map<KeyIndex<S128KeyType>, Key128> s128_keys; | 249 | std::map<KeyIndex<S128KeyType>, Key128> s128_keys; |
| 180 | std::map<KeyIndex<S256KeyType>, Key256> s256_keys; | 250 | std::map<KeyIndex<S256KeyType>, Key256> s256_keys; |
| 181 | 251 | ||
| 182 | // Map from rights ID to ticket | 252 | // Map from rights ID to ticket |
| 183 | std::map<u128, TicketRaw> common_tickets; | 253 | std::map<u128, Ticket> common_tickets; |
| 184 | std::map<u128, TicketRaw> personal_tickets; | 254 | std::map<u128, Ticket> personal_tickets; |
| 185 | 255 | ||
| 186 | std::array<std::array<u8, 0xB0>, 0x20> encrypted_keyblobs{}; | 256 | std::array<std::array<u8, 0xB0>, 0x20> encrypted_keyblobs{}; |
| 187 | std::array<std::array<u8, 0x90>, 0x20> keyblobs{}; | 257 | std::array<std::array<u8, 0x90>, 0x20> keyblobs{}; |
| @@ -216,11 +286,11 @@ std::array<u8, 0x90> DecryptKeyblob(const std::array<u8, 0xB0>& encrypted_keyblo | |||
| 216 | std::optional<Key128> DeriveSDSeed(); | 286 | std::optional<Key128> DeriveSDSeed(); |
| 217 | Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& keys); | 287 | Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& keys); |
| 218 | 288 | ||
| 219 | std::vector<TicketRaw> GetTicketblob(const FileUtil::IOFile& ticket_save); | 289 | std::vector<Ticket> GetTicketblob(const FileUtil::IOFile& ticket_save); |
| 220 | 290 | ||
| 221 | // Returns a pair of {rights_id, titlekey}. Fails if the ticket has no certificate authority (offset | 291 | // Returns a pair of {rights_id, titlekey}. Fails if the ticket has no certificate authority |
| 222 | // 0x140-0x144 is zero) | 292 | // (offset 0x140-0x144 is zero) |
| 223 | std::optional<std::pair<Key128, Key128>> ParseTicket(const TicketRaw& ticket, | 293 | std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket, |
| 224 | const RSAKeyPair<2048>& eticket_extended_key); | 294 | const RSAKeyPair<2048>& eticket_extended_key); |
| 225 | 295 | ||
| 226 | } // namespace Core::Crypto | 296 | } // namespace Core::Crypto |
diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp index d17fb778c..7e01f88b9 100644 --- a/src/core/hle/service/es/es.cpp +++ b/src/core/hle/service/es/es.cpp | |||
| @@ -75,15 +75,15 @@ private: | |||
| 75 | const auto ticket = ctx.ReadBuffer(); | 75 | const auto ticket = ctx.ReadBuffer(); |
| 76 | const auto cert = ctx.ReadBuffer(1); | 76 | const auto cert = ctx.ReadBuffer(1); |
| 77 | 77 | ||
| 78 | if (ticket.size() < sizeof(Core::Crypto::TicketRaw)) { | 78 | if (ticket.size() < sizeof(Core::Crypto::Ticket)) { |
| 79 | LOG_ERROR(Service_ETicket, "The input buffer is not large enough!"); | 79 | LOG_ERROR(Service_ETicket, "The input buffer is not large enough!"); |
| 80 | IPC::ResponseBuilder rb{ctx, 2}; | 80 | IPC::ResponseBuilder rb{ctx, 2}; |
| 81 | rb.Push(ERROR_INVALID_ARGUMENT); | 81 | rb.Push(ERROR_INVALID_ARGUMENT); |
| 82 | return; | 82 | return; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | Core::Crypto::TicketRaw raw; | 85 | Core::Crypto::Ticket raw{}; |
| 86 | std::memcpy(raw.data(), ticket.data(), sizeof(Core::Crypto::TicketRaw)); | 86 | std::memcpy(&raw, ticket.data(), sizeof(Core::Crypto::Ticket)); |
| 87 | 87 | ||
| 88 | if (!keys.AddTicketPersonalized(raw)) { | 88 | if (!keys.AddTicketPersonalized(raw)) { |
| 89 | LOG_ERROR(Service_ETicket, "The ticket could not be imported!"); | 89 | LOG_ERROR(Service_ETicket, "The ticket could not be imported!"); |
| @@ -203,7 +203,7 @@ private: | |||
| 203 | 203 | ||
| 204 | IPC::ResponseBuilder rb{ctx, 4}; | 204 | IPC::ResponseBuilder rb{ctx, 4}; |
| 205 | rb.Push(RESULT_SUCCESS); | 205 | rb.Push(RESULT_SUCCESS); |
| 206 | rb.Push<u64>(ticket.size()); | 206 | rb.Push<u64>(ticket.GetSize()); |
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | void GetPersonalizedTicketSize(Kernel::HLERequestContext& ctx) { | 209 | void GetPersonalizedTicketSize(Kernel::HLERequestContext& ctx) { |
| @@ -219,7 +219,7 @@ private: | |||
| 219 | 219 | ||
| 220 | IPC::ResponseBuilder rb{ctx, 4}; | 220 | IPC::ResponseBuilder rb{ctx, 4}; |
| 221 | rb.Push(RESULT_SUCCESS); | 221 | rb.Push(RESULT_SUCCESS); |
| 222 | rb.Push<u64>(ticket.size()); | 222 | rb.Push<u64>(ticket.GetSize()); |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | void GetCommonTicketData(Kernel::HLERequestContext& ctx) { | 225 | void GetCommonTicketData(Kernel::HLERequestContext& ctx) { |
| @@ -233,8 +233,8 @@ private: | |||
| 233 | 233 | ||
| 234 | const auto ticket = keys.GetCommonTickets().at(rights_id); | 234 | const auto ticket = keys.GetCommonTickets().at(rights_id); |
| 235 | 235 | ||
| 236 | const auto write_size = std::min(ticket.size(), ctx.GetWriteBufferSize()); | 236 | const auto write_size = std::min(ticket.GetSize(), ctx.GetWriteBufferSize()); |
| 237 | ctx.WriteBuffer(ticket.data(), write_size); | 237 | ctx.WriteBuffer(&ticket, write_size); |
| 238 | 238 | ||
| 239 | IPC::ResponseBuilder rb{ctx, 4}; | 239 | IPC::ResponseBuilder rb{ctx, 4}; |
| 240 | rb.Push(RESULT_SUCCESS); | 240 | rb.Push(RESULT_SUCCESS); |
| @@ -252,8 +252,8 @@ private: | |||
| 252 | 252 | ||
| 253 | const auto ticket = keys.GetPersonalizedTickets().at(rights_id); | 253 | const auto ticket = keys.GetPersonalizedTickets().at(rights_id); |
| 254 | 254 | ||
| 255 | const auto write_size = std::min(ticket.size(), ctx.GetWriteBufferSize()); | 255 | const auto write_size = std::min(ticket.GetSize(), ctx.GetWriteBufferSize()); |
| 256 | ctx.WriteBuffer(ticket.data(), write_size); | 256 | ctx.WriteBuffer(&ticket, write_size); |
| 257 | 257 | ||
| 258 | IPC::ResponseBuilder rb{ctx, 4}; | 258 | IPC::ResponseBuilder rb{ctx, 4}; |
| 259 | rb.Push(RESULT_SUCCESS); | 259 | rb.Push(RESULT_SUCCESS); |