From f8718ae779bbdc6a3f514b5ce141515baa97e14f Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Tue, 16 Apr 2019 09:12:04 -0400 Subject: key_manager: Add structure for Ticket parsing --- src/core/crypto/key_manager.h | 96 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 13 deletions(-) (limited to 'src/core/crypto/key_manager.h') 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 @@ #include #include +#include "common/common_funcs.h" #include "common/common_types.h" #include "core/crypto/partition_data_manager.h" #include "core/file_sys/vfs_types.h" @@ -30,7 +31,76 @@ constexpr u64 TICKET_FILE_TITLEKEY_OFFSET = 0x180; using Key128 = std::array; using Key256 = std::array; using SHA256Hash = std::array; -using TicketRaw = std::array; + +enum class SignatureType { + RSA_4096_SHA1 = 0x10000, + RSA_2048_SHA1 = 0x10001, + ECDSA_SHA1 = 0x10002, + RSA_4096_SHA256 = 0x10003, + RSA_2048_SHA256 = 0x10004, + ECDSA_SHA256 = 0x10005, +}; + +u64 GetSignatureTypeDataSize(SignatureType type); +u64 GetSignatureTypePaddingSize(SignatureType type); + +enum class TitleKeyType : u8 { + Common = 0, + Personalized = 1, +}; + +struct TicketData { + std::array issuer; + union { + std::array title_key_block; + + struct { + Key128 title_key_common; + std::array title_key_common_pad; + }; + }; + + INSERT_PADDING_BYTES(0x1); + TitleKeyType type; + INSERT_PADDING_BYTES(0x3); + u8 revision; + INSERT_PADDING_BYTES(0xA); + u64 ticket_id; + u64 device_id; + std::array rights_id; + u32 account_id; + INSERT_PADDING_BYTES(0x14C); +}; +static_assert(sizeof(TicketData) == 0x2C0, "TicketData has incorrect size."); + +struct Ticket { + SignatureType sig_type; + union { + struct { + std::array sig_data; + INSERT_PADDING_BYTES(0x3C); + TicketData data; + } rsa_4096; + + struct { + std::array sig_data; + INSERT_PADDING_BYTES(0x3C); + TicketData data; + } rsa_2048; + + struct { + std::array sig_data; + INSERT_PADDING_BYTES(0x40); + TicketData data; + } ecdsa; + }; + + TicketData& GetData(); + const TicketData& GetData() const; + u64 GetSize() const; + + static Ticket SynthesizeCommon(Key128 title_key, std::array rights_id); +}; static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big."); static_assert(sizeof(Key256) == 32, "Key256 must be 256 bytes big."); @@ -158,8 +228,8 @@ public: static bool KeyFileExists(bool title); - // Call before using the sd seed to attempt to derive it if it dosen't exist. Needs system save - // 8*43 and the private file to exist. + // Call before using the sd seed to attempt to derive it if it dosen't exist. Needs system + // save 8*43 and the private file to exist. void DeriveSDSeedLazy(); bool BaseDeriveNecessary() const; @@ -169,19 +239,19 @@ public: void PopulateFromPartitionData(PartitionDataManager& data); - const std::map& GetCommonTickets() const; - const std::map& GetPersonalizedTickets() const; + const std::map& GetCommonTickets() const; + const std::map& GetPersonalizedTickets() const; - bool AddTicketCommon(TicketRaw raw); - bool AddTicketPersonalized(TicketRaw raw); + bool AddTicketCommon(Ticket raw); + bool AddTicketPersonalized(Ticket raw); private: std::map, Key128> s128_keys; std::map, Key256> s256_keys; // Map from rights ID to ticket - std::map common_tickets; - std::map personal_tickets; + std::map common_tickets; + std::map personal_tickets; std::array, 0x20> encrypted_keyblobs{}; std::array, 0x20> keyblobs{}; @@ -216,11 +286,11 @@ std::array DecryptKeyblob(const std::array& encrypted_keyblo std::optional DeriveSDSeed(); Loader::ResultStatus DeriveSDKeys(std::array& sd_keys, KeyManager& keys); -std::vector GetTicketblob(const FileUtil::IOFile& ticket_save); +std::vector GetTicketblob(const FileUtil::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> ParseTicket(const TicketRaw& ticket, +// Returns a pair of {rights_id, titlekey}. Fails if the ticket has no certificate authority +// (offset 0x140-0x144 is zero) +std::optional> ParseTicket(const Ticket& ticket, const RSAKeyPair<2048>& eticket_extended_key); } // namespace Core::Crypto -- cgit v1.2.3