nstool
nstool copied to clipboard
[Feature] Add support for Personalised eTickets
About
NSTool doesn't currently support personalised tickets, these are generated for paid content usually, and are locked to the device they were downloaded on.
Can support for this please be added to:
- processing tickets directly
- implicitly processing tickets to decrypt NCAs
Technical Details
Ticket Data
Only the Ticket Body is different, for reference included here:
struct sTicketBody_v2
{
tc::bn::string<ticket::kIssuerSize> issuer;
std::array<byte_t, ticket::kEncTitleKeySize> enc_title_key;
byte_t format_version;
byte_t title_key_enc_type;
tc::bn::le16<uint16_t> ticket_version;
byte_t license_type;
byte_t common_key_id;
tc::bn::bitarray<sizeof(uint16_t)> property_mask;
std::array<byte_t, ticket::kReservedRegionSize> reserved_region; // explicitly reserved
tc::bn::le64<uint64_t> ticket_id;
tc::bn::le64<uint64_t> device_id;
std::array<byte_t, ticket::kRightsIdSize> rights_id;
tc::bn::le32<uint32_t> account_id;
tc::bn::le32<uint32_t> sect_total_size;
tc::bn::le32<uint32_t> sect_header_offset;
tc::bn::le16<uint16_t> sect_num;
tc::bn::le16<uint16_t> sect_entry_size;
};
When comparing personalised tickets with common tickets, these are the differences:
title_key_enc_type==1enc_title_keyhas anRSA2048-OAEP-SHA2256encryption layer on top of the regularAES128-CBC, this RSA key is device specific, and is required- No label is used for the OAEP layer.
account_idshould be non-zero- I believe this links it to the originating Nintendo Account
device_idshould be non-zero- My understanding is each Nintendo Switch has it's own unique eTicket Personalisation RSA key
- The device ID links the ticket to originating Nintendo Switch, and may be usable for selecting the correct Device RSA key if multiple are loaded at once into NSTool Key Manager.
How does the user get the RSA key?
Currently if the user generates prod.keys using LockPick_RCM, the RSA Key Pair is dumped with the name eticket_rsa_keypair.
It appears to be the raw decrypted structure from the Switch OS:
{
std::array<byte_t, 0x100> private_exponent;
std::array<byte_t, 0x100> modulus;
std::array<byte_t, 0x004> public_exponent;
tc::bn::pad<0xC> reserved;
};