mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-02-14 21:33:08 +00:00
473 lines
24 KiB
C#
473 lines
24 KiB
C#
using System.Text;
|
|
using SabreTools.Models.N3DS;
|
|
|
|
namespace BinaryObjectScanner.Printing
|
|
{
|
|
public static class CIA
|
|
{
|
|
public static void Print(StringBuilder builder, SabreTools.Models.N3DS.CIA cia)
|
|
{
|
|
builder.AppendLine("CIA Archive Information:");
|
|
builder.AppendLine("-------------------------");
|
|
builder.AppendLine();
|
|
|
|
Print(builder, cia.Header);
|
|
Print(builder, cia.CertificateChain);
|
|
Print(builder, cia.Ticket);
|
|
Print(builder, cia.TMDFileData);
|
|
Print(builder, cia.Partitions);
|
|
Print(builder, cia.MetaData);
|
|
}
|
|
|
|
#if NET48
|
|
private static void Print(StringBuilder builder, CIAHeader header)
|
|
#else
|
|
private static void Print(StringBuilder builder, CIAHeader? header)
|
|
#endif
|
|
{
|
|
builder.AppendLine(" CIA Header Information:");
|
|
builder.AppendLine(" -------------------------");
|
|
if (header == null)
|
|
{
|
|
builder.AppendLine(" No CIA header");
|
|
builder.AppendLine();
|
|
return;
|
|
}
|
|
|
|
builder.AppendLine(header.HeaderSize, " Header size");
|
|
builder.AppendLine(header.Type, " Type");
|
|
builder.AppendLine(header.Version, " Version");
|
|
builder.AppendLine(header.CertificateChainSize, " Certificate chain size");
|
|
builder.AppendLine(header.TicketSize, " Ticket size");
|
|
builder.AppendLine(header.TMDFileSize, " TMD file size");
|
|
builder.AppendLine(header.MetaSize, " Meta size");
|
|
builder.AppendLine(header.ContentSize, " Content size");
|
|
builder.AppendLine(header.ContentIndex, " Content index");
|
|
builder.AppendLine();
|
|
}
|
|
|
|
#if NET48
|
|
private static void Print(StringBuilder builder, Certificate[] certificateChain)
|
|
#else
|
|
private static void Print(StringBuilder builder, Certificate?[]? certificateChain)
|
|
#endif
|
|
{
|
|
builder.AppendLine(" Certificate Chain Information:");
|
|
builder.AppendLine(" -------------------------");
|
|
if (certificateChain == null || certificateChain.Length == 0)
|
|
{
|
|
builder.AppendLine(" No certificates, expected 3");
|
|
builder.AppendLine();
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < certificateChain.Length; i++)
|
|
{
|
|
var certificate = certificateChain[i];
|
|
|
|
string certificateName = string.Empty;
|
|
switch (i)
|
|
{
|
|
case 0: certificateName = " (CA)"; break;
|
|
case 1: certificateName = " (Ticket)"; break;
|
|
case 2: certificateName = " (TMD)"; break;
|
|
}
|
|
|
|
builder.AppendLine($" Certificate {i}{certificateName}");
|
|
if (certificate == null)
|
|
{
|
|
builder.AppendLine(" [NULL]");
|
|
continue;
|
|
}
|
|
|
|
builder.AppendLine($" Signature type: {certificate.SignatureType} (0x{certificate.SignatureType:X})");
|
|
builder.AppendLine(certificate.SignatureSize, " Signature size");
|
|
builder.AppendLine(certificate.PaddingSize, " Padding size");
|
|
builder.AppendLine(certificate.Signature, " Signature");
|
|
builder.AppendLine(certificate.Padding, " Padding");
|
|
builder.AppendLine(certificate.Issuer, " Issuer");
|
|
builder.AppendLine($" Key type: {certificate.KeyType} (0x{certificate.KeyType:X})");
|
|
builder.AppendLine(certificate.Name, " Name");
|
|
builder.AppendLine(certificate.ExpirationTime, " Expiration time");
|
|
switch (certificate.KeyType)
|
|
{
|
|
case PublicKeyType.RSA_4096:
|
|
case PublicKeyType.RSA_2048:
|
|
builder.AppendLine(certificate.RSAModulus, " Modulus");
|
|
builder.AppendLine(certificate.RSAPublicExponent, " Public exponent");
|
|
builder.AppendLine(certificate.RSAPadding, " Padding");
|
|
break;
|
|
case PublicKeyType.EllipticCurve:
|
|
builder.AppendLine(certificate.ECCPublicKey, " Public key");
|
|
builder.AppendLine(certificate.ECCPadding, " Padding");
|
|
break;
|
|
}
|
|
}
|
|
builder.AppendLine();
|
|
}
|
|
|
|
#if NET48
|
|
private static void Print(StringBuilder builder, Ticket ticket)
|
|
#else
|
|
private static void Print(StringBuilder builder, Ticket? ticket)
|
|
#endif
|
|
{
|
|
builder.AppendLine(" Ticket Information:");
|
|
builder.AppendLine(" -------------------------");
|
|
if (ticket == null)
|
|
{
|
|
builder.AppendLine(" No ticket");
|
|
builder.AppendLine();
|
|
return;
|
|
}
|
|
|
|
builder.AppendLine($" Signature type: {ticket.SignatureType} (0x{ticket.SignatureType:X})");
|
|
builder.AppendLine(ticket.SignatureSize, " Signature size");
|
|
builder.AppendLine(ticket.PaddingSize, " Padding size");
|
|
builder.AppendLine(ticket.Signature, " Signature");
|
|
builder.AppendLine(ticket.Padding, " Padding");
|
|
builder.AppendLine(ticket.Issuer, " Issuer");
|
|
builder.AppendLine(ticket.ECCPublicKey, " ECC public key");
|
|
builder.AppendLine(ticket.Version, " Version");
|
|
builder.AppendLine(ticket.CaCrlVersion, " CaCrlVersion");
|
|
builder.AppendLine(ticket.SignerCrlVersion, " SignerCrlVersion");
|
|
builder.AppendLine(ticket.TitleKey, " Title key");
|
|
builder.AppendLine(ticket.Reserved1, " Reserved 1");
|
|
builder.AppendLine(ticket.TicketID, " Ticket ID");
|
|
builder.AppendLine(ticket.ConsoleID, " Console ID");
|
|
builder.AppendLine(ticket.TitleID, " Title ID");
|
|
builder.AppendLine(ticket.Reserved2, " Reserved 2");
|
|
builder.AppendLine(ticket.TicketTitleVersion, " Ticket title version");
|
|
builder.AppendLine(ticket.Reserved3, " Reserved 3");
|
|
builder.AppendLine(ticket.LicenseType, " License type");
|
|
builder.AppendLine(ticket.CommonKeyYIndex, " Common key Y index");
|
|
builder.AppendLine(ticket.Reserved4, " Reserved 4");
|
|
builder.AppendLine(ticket.eShopAccountID, " eShop Account ID");
|
|
builder.AppendLine(ticket.Reserved5, " Reserved 5");
|
|
builder.AppendLine(ticket.Audit, " Audit");
|
|
builder.AppendLine(ticket.Reserved6, " Reserved 6");
|
|
builder.AppendLine(" Limits:");
|
|
if (ticket.Limits == null || ticket.Limits.Length == 0)
|
|
{
|
|
builder.AppendLine(" No limits");
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < ticket.Limits.Length; i++)
|
|
{
|
|
builder.AppendLine(ticket.Limits[i], $" Limit {i}");
|
|
}
|
|
}
|
|
builder.AppendLine(ticket.ContentIndexSize, " Content index size");
|
|
builder.AppendLine(ticket.ContentIndex, " Content index");
|
|
builder.AppendLine();
|
|
|
|
builder.AppendLine(" Ticket Certificate Chain Information:");
|
|
builder.AppendLine(" -------------------------");
|
|
if (ticket.CertificateChain == null || ticket.CertificateChain.Length == 0)
|
|
{
|
|
builder.AppendLine(" No certificates, expected 2");
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < ticket.CertificateChain.Length; i++)
|
|
{
|
|
var certificate = ticket.CertificateChain[i];
|
|
|
|
string certificateName = string.Empty;
|
|
switch (i)
|
|
{
|
|
case 0: certificateName = " (Ticket)"; break;
|
|
case 1: certificateName = " (CA)"; break;
|
|
}
|
|
|
|
builder.AppendLine($" Certificate {i}{certificateName}");
|
|
if (certificate == null)
|
|
{
|
|
builder.AppendLine(" [NULL]");
|
|
continue;
|
|
}
|
|
|
|
builder.AppendLine($" Signature type: {certificate.SignatureType} (0x{certificate.SignatureType:X})");
|
|
builder.AppendLine(certificate.SignatureSize, " Signature size");
|
|
builder.AppendLine(certificate.PaddingSize, " Padding size");
|
|
builder.AppendLine(certificate.Signature, " Signature");
|
|
builder.AppendLine(certificate.Padding, " Padding");
|
|
builder.AppendLine(certificate.Issuer, " Issuer");
|
|
builder.AppendLine($" Key type: {certificate.KeyType} (0x{certificate.KeyType:X})");
|
|
builder.AppendLine(certificate.Name, " Name");
|
|
builder.AppendLine(certificate.ExpirationTime, " Expiration time");
|
|
switch (certificate.KeyType)
|
|
{
|
|
case PublicKeyType.RSA_4096:
|
|
case PublicKeyType.RSA_2048:
|
|
builder.AppendLine(certificate.RSAModulus, " Modulus");
|
|
builder.AppendLine(certificate.RSAPublicExponent, " Public exponent");
|
|
builder.AppendLine(certificate.RSAPadding, " Padding");
|
|
break;
|
|
case PublicKeyType.EllipticCurve:
|
|
builder.AppendLine(certificate.ECCPublicKey, " Public key");
|
|
builder.AppendLine(certificate.ECCPadding, " Padding");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
builder.AppendLine();
|
|
}
|
|
|
|
#if NET48
|
|
private static void Print(StringBuilder builder, TitleMetadata tmd)
|
|
#else
|
|
private static void Print(StringBuilder builder, TitleMetadata? tmd)
|
|
#endif
|
|
{
|
|
builder.AppendLine(" Title Metadata Information:");
|
|
builder.AppendLine(" -------------------------");
|
|
if (tmd == null)
|
|
{
|
|
builder.AppendLine(" No title metadata");
|
|
builder.AppendLine();
|
|
return;
|
|
}
|
|
|
|
builder.AppendLine($" Signature type: {tmd.SignatureType} (0x{tmd.SignatureType:X})");
|
|
builder.AppendLine(tmd.SignatureSize, " Signature size");
|
|
builder.AppendLine(tmd.PaddingSize, " Padding size");
|
|
builder.AppendLine(tmd.Signature, " Signature");
|
|
builder.AppendLine(tmd.Padding1, " Padding 1");
|
|
builder.AppendLine(tmd.Issuer, " Issuer");
|
|
builder.AppendLine(tmd.Version, " Version");
|
|
builder.AppendLine(tmd.CaCrlVersion, " CaCrlVersion");
|
|
builder.AppendLine(tmd.SignerCrlVersion, " SignerCrlVersion");
|
|
builder.AppendLine(tmd.Reserved1, " Reserved 1");
|
|
builder.AppendLine(tmd.SystemVersion, " System version");
|
|
builder.AppendLine(tmd.TitleID, " Title ID");
|
|
builder.AppendLine(tmd.TitleType, " Title type");
|
|
builder.AppendLine(tmd.GroupID, " Group ID");
|
|
builder.AppendLine(tmd.SaveDataSize, " Save data size");
|
|
builder.AppendLine(tmd.SRLPrivateSaveDataSize, " SRL private save data size");
|
|
builder.AppendLine(tmd.Reserved2, " Reserved 2");
|
|
builder.AppendLine(tmd.SRLFlag, " SRL flag");
|
|
builder.AppendLine(tmd.Reserved3, " Reserved 3");
|
|
builder.AppendLine(tmd.AccessRights, " Access rights");
|
|
builder.AppendLine(tmd.TitleVersion, " Title version");
|
|
builder.AppendLine(tmd.ContentCount, " Content count");
|
|
builder.AppendLine(tmd.BootContent, " Boot content");
|
|
builder.AppendLine(tmd.Padding2, " Padding 2");
|
|
builder.AppendLine(tmd.SHA256HashContentInfoRecords, " SHA-256 hash of the content info records");
|
|
builder.AppendLine();
|
|
|
|
builder.AppendLine(" Ticket Content Info Records Information:");
|
|
builder.AppendLine(" -------------------------");
|
|
if (tmd.ContentInfoRecords == null || tmd.ContentInfoRecords.Length == 0)
|
|
{
|
|
builder.AppendLine(" No content info records, expected 64");
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < tmd.ContentInfoRecords.Length; i++)
|
|
{
|
|
var contentInfoRecord = tmd.ContentInfoRecords[i];
|
|
builder.AppendLine($" Content Info Record {i}");
|
|
if (contentInfoRecord == null)
|
|
{
|
|
builder.AppendLine(" [NULL]");
|
|
continue;
|
|
}
|
|
|
|
builder.AppendLine(contentInfoRecord.ContentIndexOffset, " Content index offset");
|
|
builder.AppendLine(contentInfoRecord.ContentCommandCount, " Content command count");
|
|
builder.AppendLine(contentInfoRecord.UnhashedContentRecordsSHA256Hash, $" SHA-256 hash of the next {contentInfoRecord.ContentCommandCount} records not hashed");
|
|
}
|
|
}
|
|
builder.AppendLine();
|
|
|
|
builder.AppendLine(" Ticket Content Chunk Records Information:");
|
|
builder.AppendLine(" -------------------------");
|
|
if (tmd.ContentChunkRecords == null || tmd.ContentChunkRecords.Length == 0)
|
|
{
|
|
builder.AppendLine($" No content chunk records, expected {tmd.ContentCount}");
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < tmd.ContentChunkRecords.Length; i++)
|
|
{
|
|
var contentChunkRecord = tmd.ContentChunkRecords[i];
|
|
builder.AppendLine($" Content Chunk Record {i}");
|
|
if (contentChunkRecord == null)
|
|
{
|
|
builder.AppendLine(" [NULL]");
|
|
continue;
|
|
}
|
|
|
|
builder.AppendLine(contentChunkRecord.ContentId, " Content ID");
|
|
builder.AppendLine($" Content index: {contentChunkRecord.ContentIndex} (0x{contentChunkRecord.ContentIndex:X})");
|
|
builder.AppendLine($" Content type: {contentChunkRecord.ContentType} (0x{contentChunkRecord.ContentType:X})");
|
|
builder.AppendLine(contentChunkRecord.ContentSize, " Content size");
|
|
builder.AppendLine(contentChunkRecord.SHA256Hash, " SHA-256 hash");
|
|
}
|
|
}
|
|
builder.AppendLine();
|
|
|
|
builder.AppendLine(" Ticket Certificate Chain Information:");
|
|
builder.AppendLine(" -------------------------");
|
|
if (tmd.CertificateChain == null || tmd.CertificateChain.Length == 0)
|
|
{
|
|
builder.AppendLine(" No certificates, expected 2");
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < tmd.CertificateChain.Length; i++)
|
|
{
|
|
var certificate = tmd.CertificateChain[i];
|
|
|
|
string certificateName = string.Empty;
|
|
switch (i)
|
|
{
|
|
case 0: certificateName = " (TMD)"; break;
|
|
case 1: certificateName = " (CA)"; break;
|
|
}
|
|
|
|
builder.AppendLine($" Certificate {i}{certificateName}");
|
|
if (certificate == null)
|
|
{
|
|
builder.AppendLine(" [NULL]");
|
|
continue;
|
|
}
|
|
|
|
builder.AppendLine($" Signature type: {certificate.SignatureType} (0x{certificate.SignatureType:X})");
|
|
builder.AppendLine(certificate.SignatureSize, " Signature size");
|
|
builder.AppendLine(certificate.PaddingSize, " Padding size");
|
|
builder.AppendLine(certificate.Signature, " Signature");
|
|
builder.AppendLine(certificate.Padding, " Padding");
|
|
builder.AppendLine(certificate.Issuer, " Issuer");
|
|
builder.AppendLine($" Key type: {certificate.KeyType} (0x{certificate.KeyType:X})");
|
|
builder.AppendLine(certificate.Name, " Name");
|
|
builder.AppendLine(certificate.ExpirationTime, " Expiration time");
|
|
switch (certificate.KeyType)
|
|
{
|
|
case PublicKeyType.RSA_4096:
|
|
case PublicKeyType.RSA_2048:
|
|
builder.AppendLine(certificate.RSAModulus, " Modulus");
|
|
builder.AppendLine(certificate.RSAPublicExponent, " Public exponent");
|
|
builder.AppendLine(certificate.RSAPadding, " Padding");
|
|
break;
|
|
case PublicKeyType.EllipticCurve:
|
|
builder.AppendLine(certificate.ECCPublicKey, " Public key");
|
|
builder.AppendLine(certificate.ECCPadding, " Padding");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
builder.AppendLine();
|
|
}
|
|
|
|
#if NET48
|
|
private static void Print(StringBuilder builder, NCCHHeader[] partitions)
|
|
#else
|
|
private static void Print(StringBuilder builder, NCCHHeader?[]? partitions)
|
|
#endif
|
|
{
|
|
builder.AppendLine(" NCCH Partition Header Information:");
|
|
builder.AppendLine(" -------------------------");
|
|
if (partitions == null || partitions.Length == 0)
|
|
{
|
|
builder.AppendLine(" No NCCH partition headers");
|
|
builder.AppendLine();
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < partitions.Length; i++)
|
|
{
|
|
var partitionHeader = partitions[i];
|
|
builder.AppendLine($" NCCH Partition Header {i}");
|
|
if (partitionHeader == null)
|
|
{
|
|
builder.AppendLine(" [NULL]");
|
|
continue;
|
|
}
|
|
|
|
if (partitionHeader.MagicID == string.Empty)
|
|
{
|
|
builder.AppendLine(" Empty partition, no data can be parsed");
|
|
continue;
|
|
}
|
|
else if (partitionHeader.MagicID != Constants.NCCHMagicNumber)
|
|
{
|
|
builder.AppendLine(" Unrecognized partition data, no data can be parsed");
|
|
continue;
|
|
}
|
|
|
|
builder.AppendLine(partitionHeader.RSA2048Signature, " RSA-2048 SHA-256 signature");
|
|
builder.AppendLine(partitionHeader.MagicID, " Magic ID");
|
|
builder.AppendLine(partitionHeader.ContentSizeInMediaUnits, " Content size in media units");
|
|
builder.AppendLine(partitionHeader.PartitionId, " Partition ID");
|
|
builder.AppendLine(partitionHeader.MakerCode, " Maker code");
|
|
builder.AppendLine(partitionHeader.Version, " Version");
|
|
builder.AppendLine(partitionHeader.VerificationHash, " Verification hash");
|
|
builder.AppendLine(partitionHeader.ProgramId, " Program ID");
|
|
builder.AppendLine(partitionHeader.Reserved1, " Reserved 1");
|
|
builder.AppendLine(partitionHeader.LogoRegionHash, " Logo region SHA-256 hash");
|
|
builder.AppendLine(partitionHeader.ProductCode, " Product code");
|
|
builder.AppendLine(partitionHeader.ExtendedHeaderHash, " Extended header SHA-256 hash");
|
|
builder.AppendLine(partitionHeader.ExtendedHeaderSizeInBytes, " Extended header size in bytes");
|
|
builder.AppendLine(partitionHeader.Reserved2, " Reserved 2");
|
|
builder.AppendLine(" Flags:");
|
|
if (partitionHeader.Flags == null)
|
|
{
|
|
builder.AppendLine(" [NULL]");
|
|
}
|
|
else
|
|
{
|
|
builder.AppendLine(partitionHeader.Flags.Reserved0, " Reserved 0");
|
|
builder.AppendLine(partitionHeader.Flags.Reserved1, " Reserved 1");
|
|
builder.AppendLine(partitionHeader.Flags.Reserved2, " Reserved 2");
|
|
builder.AppendLine($" Crypto method: {partitionHeader.Flags.CryptoMethod} (0x{partitionHeader.Flags.CryptoMethod:X})");
|
|
builder.AppendLine($" Content platform: {partitionHeader.Flags.ContentPlatform} (0x{partitionHeader.Flags.ContentPlatform:X})");
|
|
builder.AppendLine($" Content type: {partitionHeader.Flags.MediaPlatformIndex} (0x{partitionHeader.Flags.MediaPlatformIndex:X})");
|
|
builder.AppendLine(partitionHeader.Flags.ContentUnitSize, " Content unit size");
|
|
builder.AppendLine($" Bitmasks: {partitionHeader.Flags.BitMasks} (0x{partitionHeader.Flags.BitMasks:X})");
|
|
}
|
|
builder.AppendLine(partitionHeader.PlainRegionOffsetInMediaUnits, " Plain region offset, in media units");
|
|
builder.AppendLine(partitionHeader.PlainRegionSizeInMediaUnits, " Plain region size, in media units");
|
|
builder.AppendLine(partitionHeader.LogoRegionOffsetInMediaUnits, " Logo region offset, in media units");
|
|
builder.AppendLine(partitionHeader.LogoRegionSizeInMediaUnits, " Logo region size, in media units");
|
|
builder.AppendLine(partitionHeader.ExeFSOffsetInMediaUnits, " ExeFS offset, in media units");
|
|
builder.AppendLine(partitionHeader.ExeFSSizeInMediaUnits, " ExeFS size, in media units");
|
|
builder.AppendLine(partitionHeader.ExeFSHashRegionSizeInMediaUnits, " ExeFS hash region offset, in media units");
|
|
builder.AppendLine(partitionHeader.Reserved3, " Reserved 3");
|
|
builder.AppendLine(partitionHeader.RomFSOffsetInMediaUnits, " RomFS offset, in media units");
|
|
builder.AppendLine(partitionHeader.RomFSSizeInMediaUnits, " RomFS size, in media units");
|
|
builder.AppendLine(partitionHeader.RomFSHashRegionSizeInMediaUnits, " RomFS hash region offset, in media units");
|
|
builder.AppendLine(partitionHeader.Reserved4, " Reserved 4");
|
|
builder.AppendLine(partitionHeader.ExeFSSuperblockHash, " ExeFS superblock SHA-256 hash");
|
|
builder.AppendLine(partitionHeader.RomFSSuperblockHash, " RomFS superblock SHA-256 hash");
|
|
}
|
|
builder.AppendLine();
|
|
}
|
|
|
|
#if NET48
|
|
private static void Print(StringBuilder builder, MetaData metaData)
|
|
#else
|
|
private static void Print(StringBuilder builder, MetaData? metaData)
|
|
#endif
|
|
{
|
|
builder.AppendLine(" Meta Data Information:");
|
|
builder.AppendLine(" -------------------------");
|
|
if (metaData == null)
|
|
{
|
|
builder.AppendLine(" No meta file data");
|
|
builder.AppendLine();
|
|
return;
|
|
}
|
|
|
|
builder.AppendLine(metaData.TitleIDDependencyList, " Title ID dependency list");
|
|
builder.AppendLine(metaData.Reserved1, " Reserved 1");
|
|
builder.AppendLine(metaData.CoreVersion, " Core version");
|
|
builder.AppendLine(metaData.Reserved2, " Reserved 2");
|
|
builder.AppendLine(metaData.IconData, " Icon data");
|
|
builder.AppendLine();
|
|
}
|
|
|
|
}
|
|
} |