#pragma warning disable IDE1006 // Naming Styles namespace SabreTools.Data.Models.N3DS { /// /// A format used to store an encrypted titlekey (using 128-Bit AES-CBC). /// With 3DS, the Ticket format was updated (now v1) from Wii/DSi format (v0). /// /// public sealed class Ticket { /// /// Signature Type /// public SignatureType SignatureType { get; set; } /// /// Signature size /// public ushort SignatureSize { get; set; } /// /// Padding size /// public byte PaddingSize { get; set; } /// /// Signature /// public byte[] Signature { get; set; } = []; /// /// Padding /// public byte[] Padding { get; set; } = []; /// /// Issuer /// public string? Issuer { get; set; } /// /// ECC PublicKey /// /// 0x3C bytes public byte[] ECCPublicKey { get; set; } = new byte[0x3C]; /// /// Version (For 3DS this is always 1) /// public byte Version { get; set; } /// /// CaCrlVersion /// public byte CaCrlVersion { get; set; } /// /// SignerCrlVersion /// public byte SignerCrlVersion { get; set; } /// /// TitleKey (normal-key encrypted using one of the common keyYs; see below) /// /// /// 0x10 bytes /// /// The titlekey is decrypted by using the AES engine with the ticket common-key keyslot. /// The keyY is selected through an index (ticket offset 0xB1) into a plaintext array /// of 6 keys ("common keyYs") stored in the data section of Process9. AES-CBC mode is used /// where the IV is the big-endian titleID. Note that on a retail unit index0 is a retail keyY, /// while on a dev-unit index0 is the dev common-key which is a normal-key. /// (On retail for these keyYs, the hardware key-scrambler is used) /// /// The titlekey is used to decrypt content downloaded from the CDN using 128-bit AES-CBC with /// the content index (as big endian u16, padded with trailing zeroes) as the IV. /// public byte[] TitleKey { get; set; } = new byte[0x10]; /// /// Reserved /// public byte Reserved1 { get; set; } /// /// TicketID /// public ulong TicketID { get; set; } /// /// ConsoleID /// public uint ConsoleID { get; set; } /// /// TitleID /// public ulong TitleID { get; set; } /// /// Reserved /// /// 2 bytes public byte[] Reserved2 { get; set; } = new byte[2]; /// /// Ticket title version /// /// /// The Ticket Title Version is generally the same as the title version stored in the /// Title Metadata. Although it doesn't have to match the TMD version to be valid. /// public ushort TicketTitleVersion { get; set; } /// /// Reserved /// /// 8 bytes public byte[] Reserved3 { get; set; } = new byte[8]; /// /// License Type /// public byte LicenseType { get; set; } /// /// Index to the common keyY used for this ticket, usually 0x1 for retail system titles /// public byte CommonKeyYIndex { get; set; } /// /// Reserved /// /// 0x2A bytes public byte[] Reserved4 { get; set; } = new byte[0x2A]; /// /// eShop Account ID? /// public uint eShopAccountID { get; set; } /// /// Reserved /// public byte Reserved5 { get; set; } /// /// Audit /// public byte Audit { get; set; } /// /// Reserved /// /// 0x42 bytes public byte[] Reserved6 { get; set; } = new byte[0x42]; /// /// Limits /// /// /// In demos, the first u32 in the "Limits" section is 0x4, then the second u32 is the max-playcount. /// public uint[] Limits { get; set; } = []; /// /// The Content Index of a ticket has its own size defined within itself, /// with seemingly a minimal of 20 bytes, the second u32 in big endian defines /// the full value of X. /// public uint ContentIndexSize { get; set; } /// /// Content Index /// public byte[] ContentIndex { get; set; } = []; /// /// Certificate chain /// /// /// https://www.3dbrew.org/wiki/Ticket#Certificate_Chain /// public Certificate[] CertificateChain { get; set; } = []; } }