Created
December 3, 2014 03:01
-
-
Save Subv/3e0cefdd3e267ce883a5 to your computer and use it in GitHub Desktop.
010 Editor Nintendo 3DS CIA Template
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//-------------------------------------- | |
//--- 010 Editor v5.0 Binary Template | |
// | |
// File: 3DSCIATemplate.bt | |
// Author: Subv | |
// Revision: 0.1 | |
// Purpose: Parsing .CIA files for the Nintendo 3DS | |
//-------------------------------------- | |
struct CIAFile | |
{ | |
struct CIAHeader | |
{ | |
int ArchiveHeaderSize<format=hex>; | |
short Type; | |
short Version; | |
int CertificateChainSize; | |
int TicketSize; | |
int TMDFileSize; | |
int MetaSize; | |
int64 ContentSize; | |
byte ContentIndex[0x2000]; | |
} Header; | |
byte Padding1[(64 - FTell() % 64) % 64]; | |
enum SignatureTypes | |
{ | |
RSA_4096_SHA1 = 0x010000, | |
RSA_2048_SHA1 = 0x010001, | |
ELLIPTIC_CURVE_SHA1 = 0x010002, | |
RSA_4096_SHA2 = 0x010003, | |
RSA_2048_SHA2 = 0x010004, | |
ECDSA_SHA2 = 0x010005 | |
}; | |
enum KeyTypes | |
{ | |
RSA_4096 = 0, | |
RSA_2048 = 1, | |
ELLIPTIC_CURVE = 2 | |
}; | |
struct SignatureDataStruct | |
{ | |
SignatureTypes SignatureType; | |
if (SignatureType == RSA_4096_SHA1 || SignatureType == RSA_4096_SHA2) | |
byte Signature[0x200 + 0x3C]<format=hex>; | |
else if (SignatureType == RSA_2048_SHA1 || SignatureType == RSA_2048_SHA2) | |
byte Signature[0x100 + 0x3C]<format=hex>; | |
else if (SignatureType == ELLIPTIC_CURVE_SHA1 || SignatureType == ECDSA_SHA2) | |
byte Signature[0x3C + 0x40]<format=hex>; | |
}; | |
BigEndian(); | |
struct CertificateStruct | |
{ | |
SignatureDataStruct SignatureData; | |
char Issuer[0x40]<format=hex>; | |
KeyTypes KeyType; | |
char Name[0x40]; | |
int Unknown; | |
if (KeyType == RSA_4096) | |
{ | |
byte Modulus[0x200]; | |
int PublicExponent; | |
byte Padding[0x34]; | |
} | |
else if (KeyType == RSA_2048) | |
{ | |
byte Modulus[0x100]; | |
int PublicExponent; | |
byte Padding[0x34]; | |
} | |
else if (KeyType == ELLIPTIC_CURVE) | |
{ | |
byte PublicKey[0x3C]; | |
byte Padding[0x3C]; | |
} | |
} Certificates[3] <optimize=false>; | |
Assert(sizeof(Certificates[0]) + sizeof(Certificates[1]) + sizeof(Certificates[2]) == Header.CertificateChainSize); | |
byte Padding2[(64 - FTell() % 64) % 64]; | |
struct TicketStructure | |
{ | |
SignatureDataStruct SignatureData; | |
char Issuer[0x40]; | |
byte ECCPublicKey[0x3C]; | |
byte Version; | |
byte CaCrlVersion; | |
byte SignerCrlVersion; | |
byte EncryptedTitleKey[0x10]; | |
byte Reserved0; | |
int64 TicketID; | |
int ConsoleID; | |
int64 TitleID; | |
byte Reserved1[0x2]; | |
short TicketTitleVersion; | |
byte Reserved2[0x8]; | |
byte LicenseType; | |
byte TicketCommonKeyYIndex; | |
byte Reserved3[0x2A]; | |
int EShopAccountID; | |
byte Reserved4; | |
byte Audit; | |
byte Reserved5[0x42]; | |
byte Limits[0x40]; | |
byte ContentIndex[0xAC]; | |
} Ticket; | |
Assert(sizeof(Ticket) == Header.TicketSize); | |
byte Padding3[(64 - FTell() % 64) % 64]; | |
struct TitleMetadata | |
{ | |
SignatureDataStruct SignatureData; | |
struct TMDHeader | |
{ | |
char SignatureIssuer[0x40]; | |
byte Version; | |
byte CACrlVersion; | |
byte SignerCrlVersion; | |
byte Reserved; | |
int64 SystemVersion; | |
int64 TitleID; | |
int TitleType; | |
short GroupID; | |
int SaveDataSize; | |
int SRLPrivateSaveDataSize; | |
int Reserved2; | |
byte SRLFlag; | |
byte Reserved3[0x31]; | |
int AccessRights<format=hex>; | |
short TitleVersion; | |
short ContentCount; | |
short BootContent; | |
short Padding; | |
byte ContentInfoRecordsHash[0x20]; | |
} Header; | |
struct ContentInfoRecord | |
{ | |
short ContentIndexOffset; | |
short ContentCommandCount; | |
byte Hash[0x20]; | |
} ContentInfoRecords[64]; | |
enum <short> ContentIndexes | |
{ | |
MainContent = 0, | |
HomeMenuManual = 1, | |
DLChildContainer = 2 | |
}; | |
struct ContentChunkRecord | |
{ | |
int ContentID; | |
ContentIndexes ContentIndex; | |
short ContentType; | |
int64 ContentSize; | |
byte Hash[0x20]; | |
} ContentChunkRecords[Header.ContentCount]; | |
} TMD; | |
Assert(sizeof(TMD) == Header.TMDFileSize); | |
byte Padding4[(64 - FTell() % 64) % 64]; | |
} CIA; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment