diff options
Diffstat (limited to 'src/core/crypto/key_manager.h')
-rw-r--r-- | src/core/crypto/key_manager.h | 59 |
1 files changed, 42 insertions, 17 deletions
diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h index 8c864503b..2250eccec 100644 --- a/src/core/crypto/key_manager.h +++ b/src/core/crypto/key_manager.h @@ -7,6 +7,7 @@ #include <filesystem> #include <map> #include <optional> +#include <span> #include <string> #include <variant> @@ -29,8 +30,6 @@ enum class ResultStatus : u16; namespace Core::Crypto { -constexpr u64 TICKET_FILE_TITLEKEY_OFFSET = 0x180; - using Key128 = std::array<u8, 0x10>; using Key256 = std::array<u8, 0x20>; using SHA256Hash = std::array<u8, 0x20>; @@ -82,6 +81,7 @@ struct RSA4096Ticket { INSERT_PADDING_BYTES(0x3C); TicketData data; }; +static_assert(sizeof(RSA4096Ticket) == 0x500, "RSA4096Ticket has incorrect size."); struct RSA2048Ticket { SignatureType sig_type; @@ -89,6 +89,7 @@ struct RSA2048Ticket { INSERT_PADDING_BYTES(0x3C); TicketData data; }; +static_assert(sizeof(RSA2048Ticket) == 0x400, "RSA2048Ticket has incorrect size."); struct ECDSATicket { SignatureType sig_type; @@ -96,16 +97,41 @@ struct ECDSATicket { INSERT_PADDING_BYTES(0x40); TicketData data; }; +static_assert(sizeof(ECDSATicket) == 0x340, "ECDSATicket has incorrect size."); struct Ticket { - std::variant<RSA4096Ticket, RSA2048Ticket, ECDSATicket> data; - - SignatureType GetSignatureType() const; - TicketData& GetData(); - const TicketData& GetData() const; - u64 GetSize() const; - + std::variant<std::monostate, RSA4096Ticket, RSA2048Ticket, ECDSATicket> data; + + [[nodiscard]] bool IsValid() const; + [[nodiscard]] SignatureType GetSignatureType() const; + [[nodiscard]] TicketData& GetData(); + [[nodiscard]] const TicketData& GetData() const; + [[nodiscard]] u64 GetSize() const; + + /** + * Synthesizes a common ticket given a title key and rights ID. + * + * @param title_key Title key to store in the ticket. + * @param rights_id Rights ID the ticket is for. + * @return The synthesized common ticket. + */ static Ticket SynthesizeCommon(Key128 title_key, const std::array<u8, 0x10>& rights_id); + + /** + * Reads a ticket from a file. + * + * @param file File to read the ticket from. + * @return The read ticket. If the ticket data is invalid, Ticket::IsValid() will be false. + */ + static Ticket Read(const FileSys::VirtualFile& file); + + /** + * Reads a ticket from a memory buffer. + * + * @param raw_data Buffer to read the ticket from. + * @return The read ticket. If the ticket data is invalid, Ticket::IsValid() will be false. + */ + static Ticket Read(std::span<const u8> raw_data); }; static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big."); @@ -264,8 +290,7 @@ public: const std::map<u128, Ticket>& GetCommonTickets() const; const std::map<u128, Ticket>& GetPersonalizedTickets() const; - bool AddTicketCommon(Ticket raw); - bool AddTicketPersonalized(Ticket raw); + bool AddTicket(const Ticket& ticket); void ReloadKeys(); bool AreKeysLoaded() const; @@ -279,10 +304,12 @@ private: // Map from rights ID to ticket std::map<u128, Ticket> common_tickets; std::map<u128, Ticket> personal_tickets; + bool ticket_databases_loaded = false; std::array<std::array<u8, 0xB0>, 0x20> encrypted_keyblobs{}; std::array<std::array<u8, 0x90>, 0x20> keyblobs{}; std::array<u8, 576> eticket_extended_kek{}; + RSAKeyPair<2048> eticket_rsa_keypair{}; bool dev_mode; void LoadFromFile(const std::filesystem::path& file_path, bool is_title_keys); @@ -293,10 +320,13 @@ private: void DeriveGeneralPurposeKeys(std::size_t crypto_revision); - RSAKeyPair<2048> GetETicketRSAKey() const; + void DeriveETicketRSAKey(); void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0); void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0); + + /// Parses the title key section of a ticket. + std::optional<Key128> ParseTicketTitleKey(const Ticket& ticket); }; Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed); @@ -311,9 +341,4 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& ke std::vector<Ticket> GetTicketblob(const Common::FS::IOFile& ticket_save); -// Returns a pair of {rights_id, titlekey}. Fails if the ticket has no certificate authority -// (offset 0x140-0x144 is zero) -std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket, - const RSAKeyPair<2048>& eticket_extended_key); - } // namespace Core::Crypto |