Changes

Jump to navigation Jump to search
1,486 bytes added ,  14:22, 28 July 2020
note discrepancy in endianness
[[Category:File formats]]'''Title metadata''' is a format used to store information about a title (a single standalone gameinstalled title, channelDLC, etc.) and all its installed contents, including which contents they consist of and their SHA1 SHA256 hashes.
[httphttps://gitbitbucket.daifukkat.suorg/trap15/?p=3dshax.git Code is available] by trap15 to parse the available information from the 3DS format of TMDs.
== Structure ==
 
All the data in the file represented in Big Endian, unless otherwise noted.
 
{| class="wikitable"
| align="center" style="background:#f0f0f0;"|'''Offset'''
| align="center" style="background:#f0f0f0;"|'''Size'''
| align="center" style="background:#f0f0f0;"|'''Description'''
|-
| 0x0||Y||Signature Data
|-
| Y ||0xC4||Header
|-
| 0xC4 + Y||0x24*64||Content Info Records.
|-
| 0x9C4 + Y||0x30*ContentCount||Content Chunk Records.
|}
 
Y denotes the total size of the "Signature Data" section and depends on the signature type.
 
=== Signature Data ===
The signature is of the header of the TMD.
{| class="wikitable"
| align="center" style="background:#f0f0f0;"|'''Offset'''
| align="center" style="background:#f0f0f0;"|'''Size'''
| align="center" style="background:#f0f0f0;"|'''Description'''
|-
| 0x0||0x4||Signature Type
|-
| 0x4 ||X||Signature
|-
| 0x4 + X|| ||Padding Aligning the signature data to 0x40 bytes
|}
 
==== Signature Type ====
{{Signature Types}}
The hash for the signature, is calculated over the header of the TMD
 
=== Header ===
 
{| class="wikitable"
|- align="center" style="background:#f0f0f0;"|'''Offset'''| align="center" style="background-color: #dddf0f0f0;"|'''Size'''! Start| align="center" style="background:#f0f0f0;"|'''Description'''! Length|-! Description| 0x0||0x40||Signature Issuer
|-
| 0x0000x40| 4| Signature type0x1||Version
|-
| 0x0040x41| *| Signature0x1||ca_crl_version
|-
| 0x1040x42| 60| Padding modulo 640x1||signer_crl_version
|-
| 0x1400x43| 64| Issuer0x1||Reserved
|-
| 0x1800x44| 1| 0x8||System Version
|-
| 0x1810x4C| 1| ca_crl_version0x8||Title ID
|-
| 0x1820x54| 1| signer_crl_version0x4||Title Type
|-
| 0x1830x58| 1| Padding modulo 640x2||Group ID
|-
| 0x1840x5A| 8| System Version0x4||Save Data Size in Little Endian (Bytes) (Also SRL Public Save Data Size)
|-
| 0x18C0x5E| 8| Title ID0x4||SRL Private Save Data Size in Little Endian (Bytes)
|-
| 0x1940x62| 4| Title type0x4||Reserved
|-
| 0x1980x66| 2| Group ID0x1||SRL Flag
|-
| 0x19A0x67| 62| reserved0x31||Reserved
|-
| 0x1D80x98||0x4| 4| Access rightsRights
|-
| 0x1DC0x9C||0x2| 2| Title versionVersion
|-
| 0x1DE0x9E| 2| Number of contents0x02||Content Count
|-
| 0x1E00xA0| 64| 0x2||Boot Content Records
|-
| 0x2200xA2||0x2| 40| Padding modulo 64
|-
| 0x2480xA4||0x20||SHA-256 Hash of the Content Info Records|} === Content Info Records === There are 64 of these records, usually only the first is used. {| 4class="wikitable"| Boot content-! Offset! Size! Description
|-
| 0x2520x00| 42| Banner contentContent index offset
|-
| 0x2560x02| 42| Banner sizeContent command count [k]
|-
| 0x2600x04| 320x20| HashSHA-256 hash of the next k content records that have not been hashed yet|}
|}=== Content chunk records ===There is one of these for each content contained in this title. (Determined by "Content Count" in the TMD Header).
=== Content Records ===
{| class="wikitable"
|-
! StartOffset! LengthSize
! Description
|-
| 0x00
| 4
| Content IDid
|-
| 0x04
| 322| Content index|-| 0x06| 2| Content type|-| 0x08| 8| Content size|-| 0x10| 0x20| SHA-256 Hashhash
|}
==== Content Index ====
This indicates the content type: {| class="wikitable" border="1"|-! Index! Content Type|-| 0000| Main Content (.[[NCCH#CXI|CXI]] for 3DS executable content/.[[NCCH#CFA|CFA]] for 3DS Data Archives/.SRL for TWL content)|-| 0001| Home Menu Manual (.[[NCCH#CFA|CFA]])|-| 0002| DLP Child Container (.[[NCCH#CFA|CFA]])|} This does not apply to DLC. ==== Content Type flags = Certificates ===
{| class="wikitable"
|-
! Start! LengthFlags
! Description
|-
| 0x0001| Encrypted|-| 2| Disc|-
| 4
| Signature typeCFM (abbreviation for?)
|-
| 0x0040x4000| *| SignatureOptional
|-
| 0x1040x8000| 64Shared| Issuer} == Certificate Chain ==If the TMD file is obtained from Nintendo's CDN, then it will have two [[Certificates|certificates]] appended at the end of the file: {| class="wikitable" border="1"
|-
| 0x124! CERTIFICATE| 4! SIGNATURE TYPE| Tag! RETAIL CERT NAME! DEBUG CERT NAME! DESCRIPTION
|-
| 0x128 TMD| 64 RSA-2048| Name CP0000000b| CP0000000a| Used to verify the TMD signature
|-
| 0x168 CA| RSA-4096| Key CA00000003| CA00000004| Used to verify the TMD Certificate
|}
 
The CA certificate is issued by 'Root', the public key for which is stored in NATIVE_FIRM.
== Example code application ==
<source lang="c">
typedef struct {
u32 cid; // content id
u8 hash[0x20]; // SHA-256 hash
} content_record; // size: 0x24 bytes
enum sig_type {
RSA_2048_SHA256 = 0x00010004,
RSA_4096_SHA1 = 0x00010000
};
typedef struct {
u32 sig_type;
u8 sig[*]; // * Signature size
u8 fill1[60];
u8 issuer[64]; // Root-CA%08x-CP%08x
u8 version;
u8 ca_crl_version;
u8 signer_crl_version;
u8 fill2;
u64 sys_version;
u64 title_id;
u32 title_type;
u16 group_id; // publisher
u8 reserved[62];
u32 access_rights;
u16 title_version;
u16 num_contents;
content_record contents[0x40];
u8 padding[0x28];
u32 boot_content;
u32 banner_content;
u32 banner_size;
u8 hash[0x20]; /* Huh? */
} tmd;
//The tmd is then followed by a chain of certificates, where each certificate is of Sorry I removed the general form typedef example struct { u32 sig_type; u8 sig[*]; // * Signature size u8 issuer[64]; u32 tag; // identifies what because it is being signed u8 name[64]; // name of thing being signed u8 key[..wrong.]; } certificate;
</source>
44

edits

Navigation menu