From 2779f5ef728866697ea8a9a446e4a2a1e324ffd0 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Mon, 27 Sep 2021 10:42:54 -0700 Subject: [PATCH] Better certificate chain reading --- NDecrypt/N3DS/Headers/CIAHeader.cs | 7 +++---- NDecrypt/N3DS/Headers/Ticket.cs | 27 ++++++++++++++++++++++++-- NDecrypt/N3DS/Headers/TitleMetadata.cs | 15 ++++++++++++++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/NDecrypt/N3DS/Headers/CIAHeader.cs b/NDecrypt/N3DS/Headers/CIAHeader.cs index 3a304c4..ab1351d 100644 --- a/NDecrypt/N3DS/Headers/CIAHeader.cs +++ b/NDecrypt/N3DS/Headers/CIAHeader.cs @@ -101,10 +101,9 @@ namespace NDecrypt.N3DS.Headers header.ContentSize = reader.ReadInt64(); header.CertificateChain = new Certificate[3]; - for (int i = 0; i < 3; i++) - { - header.CertificateChain[i] = Certificate.Read(reader); - } + header.CertificateChain[0] = Certificate.Read(reader); // CA + header.CertificateChain[1] = Certificate.Read(reader); // Ticket + header.CertificateChain[2] = Certificate.Read(reader); // TMD header.Ticket = Ticket.Read(reader, header.TicketSize); header.TMDFileData = TitleMetadata.Read(reader, header.TMDFileSize); diff --git a/NDecrypt/N3DS/Headers/Ticket.cs b/NDecrypt/N3DS/Headers/Ticket.cs index f9d9bd1..fd7c5b4 100644 --- a/NDecrypt/N3DS/Headers/Ticket.cs +++ b/NDecrypt/N3DS/Headers/Ticket.cs @@ -149,6 +149,13 @@ namespace NDecrypt.N3DS.Headers /// public byte[] Limits { get; private 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 int ContentIndexSize { get; private set; } + /// /// Content Index /// @@ -159,6 +166,14 @@ namespace NDecrypt.N3DS.Headers /// public byte[] ContentIndex { get; private set; } + /// + /// Certificate chain + /// + /// + /// https://www.3dbrew.org/wiki/Ticket#Certificate_Chain + /// + public Certificate[] CertificateChain { get; set; } + /// /// Read from a stream and get ticket, if possible /// @@ -214,9 +229,17 @@ namespace NDecrypt.N3DS.Headers tk.Audit = reader.ReadByte(); tk.Reserved6 = reader.ReadBytes(0x42); tk.Limits = reader.ReadBytes(0x40); + reader.ReadBytes(4); + tk.ContentIndexSize = reader.ReadInt32(); + reader.BaseStream.Seek(-8, SeekOrigin.Current); + tk.ContentIndex = reader.ReadBytes(tk.ContentIndexSize); - if (ticketSize - 0x164 > 0) - tk.ContentIndex = reader.ReadBytes(ticketSize - 0x164); + if (ticketSize - (0x164 + tk.ContentIndexSize) > 0) + { + tk.CertificateChain = new Certificate[2]; + tk.CertificateChain[0] = Certificate.Read(reader); // Ticket + tk.CertificateChain[1] = Certificate.Read(reader); // CA + } return tk; } diff --git a/NDecrypt/N3DS/Headers/TitleMetadata.cs b/NDecrypt/N3DS/Headers/TitleMetadata.cs index 5162b01..f52983b 100644 --- a/NDecrypt/N3DS/Headers/TitleMetadata.cs +++ b/NDecrypt/N3DS/Headers/TitleMetadata.cs @@ -136,6 +136,14 @@ namespace NDecrypt.N3DS.Headers /// public ContentChunkRecord[] ContentChunkRecords { get; private set; } + /// + /// Certificate chain + /// + /// + /// https://www.3dbrew.org/wiki/Title_metadata#Certificate_Chain + /// + public Certificate[] CertificateChain { get; set; } + /// /// Read from a stream and get ticket metadata, if possible /// @@ -203,6 +211,13 @@ namespace NDecrypt.N3DS.Headers tm.ContentChunkRecords[i] = ContentChunkRecord.Read(reader); } + if (metadataSize - (0xC4 + (64 * 0x24) + (tm.ContentCount * 0x30)) > 0) + { + tm.CertificateChain = new Certificate[2]; + tm.CertificateChain[0] = Certificate.Read(reader); // TMD + tm.CertificateChain[1] = Certificate.Read(reader); // CA + } + return tm; } catch