CIA: Difference between revisions
 Sorry for the repost, just figured some stuff up...  | 
				Link00000000 (talk | contribs) m Add clarification for what TMD is  | 
				||
| (83 intermediate revisions by 15 users not shown) | |||
| Line 1: | Line 1: | ||
[[Category:File formats]]  | |||
CIA stands for '''C'''TR '''I'''mportable '''A'''rchive.   | == Overview ==  | ||
CIA stands for '''C'''TR '''I'''mportable '''A'''rchive. This format allows the installation of titles to the 3DS. CIA files and titles on [[Title list|Nintendo's CDN]] contain identical data. As a consequence, valid CIA files can be generated from CDN content. This also means CIA files can contain anything that titles on Nintendo's CDN can contain.   | |||
Under normal circumstances CIA files are used where downloading a title is impractical or not possible. Such as distributing a [[Download Play]] child, or installing forced Gamecard updates. Those CIA(s) are stored by the titles in question, in an auxiliary [[NCCH#CFA|CFA]] file.  | |||
Development Units, are capable of manually installing CIA files via the [[3DS Development Unit Software#Dev Menu|Dev Menu]].  | |||
== Format ==  | |||
This is the current version of the CIA format, it was finalised in late 2010. (Older versions of the CIA format can be viewed on the [[Talk:CIA|Talk]] page)  | |||
The CIA format has a similar structure to the [http://wiibrew.org/wiki/Wad WAD format].  | |||
The file is represented in little-endian.  | The file is represented in little-endian.  | ||
The data is aligned in 64 byte blocks (if a content ends at the middle of the block, the next content will begin from a new block).  | |||
=== CIA Header ===  | |||
{| class="wikitable" border="1"  | {| class="wikitable" border="1"  | ||
| Line 17: | Line 27: | ||
|  0x00  | |  0x00  | ||
|  0x04    | |  0x04    | ||
|  Archive Header Size (=0x2020 bytes  | |  Archive Header Size (Usually = 0x2020 bytes)  | ||
|-  | |-  | ||
|  0x04  | |  0x04  | ||
|    | |  0x02  | ||
|    | |  Type  | ||
|-  | |-  | ||
|  0x06  | |||
|  0x02  | |||
|  Version  | |||
|-   | |||
|  0x08        | |  0x08        | ||
|  0x04  | |  0x04  | ||
| Line 29: | Line 43: | ||
|  0x0C         | |  0x0C         | ||
|  0x04  | |  0x04  | ||
|  Ticket size  | |  [[Ticket]] size  | ||
|-  | |-  | ||
|  0x10        | |  0x10        | ||
|  0x04  | |  0x04  | ||
|  TMD file size  | |  [[TMD]] (Title Metadata) file size  | ||
|-  | |-  | ||
|  0x14        | |  0x14        | ||
|  0x04  | |  0x04  | ||
|    | |  Meta size (0 if no Meta data is present)  | ||
|-  | |-  | ||
|  0x18        | |  0x18        | ||
|    | |  0x08  | ||
|  Content   | |  Content size  | ||
|-  | |-  | ||
|    | |  0x20  | ||
|    | |  0x2000  | ||
|    | |  Content Index  | ||
|}  | |}  | ||
The order of the sections   | The order of the sections in the CIA file:  | ||
* certificate chain  | * certificate chain  | ||
* Ticket  | * Ticket  | ||
* TMD file data  | * TMD file data  | ||
*   | * Content file data  | ||
The data of the files is   | * Meta file data (Not a necessary component)   | ||
The contents (NCCH/SRL) are encrypted using 128-bit AES-CBC. The encryption uses the decrypted titlekey from the [[Ticket#Structure|ticket]], and the content index from the TMD padded with zeros as the IV.  | |||
=== Certificate Chain ===  | |||
There are three [[Certificates|certificates]] in this chain:  | |||
{| class="wikitable" border="1"  | |||
|-  | |||
!  CERTIFICATE  | |||
!  SIGNATURE TYPE  | |||
!  RETAIL CERT NAME  | |||
!  DEBUG CERT NAME  | |||
!  DESCRIPTION  | |||
|-  | |||
|  CA  | |||
|  RSA-4096  | |||
|  CA00000003  | |||
|  CA00000004  | |||
|  Used to verify the Ticket/TMD Certificates  | |||
|-  | |||
|  Ticket  | |||
|  RSA-2048  | |||
|  XS0000000c  | |||
|  XS00000009  | |||
|  Used to verify the Ticket signature  | |||
|-  | |||
|  TMD  | |||
|  RSA-2048  | |||
|  CP0000000b  | |||
|  CP0000000a  | |||
|  Used to verify the TMD signature  | |||
|}  | |||
The CA certificate is issued by 'Root', the public key for which is stored in NATIVE_FIRM.  | |||
=== Meta ===  | |||
The structure of this data is as follows:  | |||
{| class="wikitable" border="1"  | |||
|-  | |||
!  START  | |||
!  SIZE  | |||
!  DESCRIPTION  | |||
|-  | |||
|  0x00  | |||
|  0x180  | |||
|  Title ID dependency list - Taken from the application's [[NCCH/Extended Header|ExHeader]]  | |||
|-  | |||
|  0x180  | |||
|  0x180  | |||
|  Reserved  | |||
|-  | |||
|  0x300  | |||
|  0x4  | |||
|  Core Version  | |||
|-  | |||
|  0x304  | |||
|  0xFC  | |||
|  Reserved  | |||
|-  | |||
|  0x400  | |||
|  0x36C0  | |||
|  [[SMDH|Icon Data]](.ICN) - Taken from the application's [[ExeFS]]  | |||
|}  | |||
Obviously this section is not present in TWL CIA files, or any other CIA file which does not contain a [[NCCH#CXI|CXI]].  | |||
== Tools ==  | |||
* [https://github.com/3dshax/ctr/tree/master/ctrtool ctrtool] - Reading/Extraction of CIA files. This can only decrypt the title-key for development CIAs, since retail CIAs use the [[AES]] hardware key-scrambler for the common-key keyslot.  | |||
* [https://github.com/Tiger21820/ctr_toolkit/tree/master/make_cia make_cia] - Generating CIA files. Requires CommonKey and ticket/TMD RSA-2048 private exponents.  | |||
* [https://github.com/Tiger21820/ctr_toolkit/tree/master/make_cdn_cia make_cdn_cia] - (CMD)(Windows/Linux) Generates CIA files from CDN Content  | |||
* [[makerom]] - Tool which can be used to create NCCH, CCI, and CIA files.  | |||
== Title Key Encryption ==  | |||
The unencrypted Title Key is used to encrypt the data in a CIA. The encrypted Title Key of a CIA can be found at offset 0x1BF in a CIA's Ticket.  | |||
Each Title Key is encrypted with AES-CBC to get the encrypted Title Key.  | |||
To encrypt an unencrypted title key, you need:  | |||
* Common key (as byte array)  | |||
* Title ID (as ulong)  | |||
* (and of course the unencrypted title key you want to encrypt) (as byte array)  | |||
The title key encryption process starts by converting the ulong (Title ID) into a byte array using by retrieving the bytes of the Title ID using BitConverter.GetBytes().  | |||
If the converted bytes (title ID) are in Little Endian, reverse those bytes. (in C# it would be Array.Reverse(byte_array_from_bitconverter))  | |||
This process makes the Title Key encryption IV.  | |||
Next, after you've gotten your Title Key's IV, you can start your cryptography transformation. Using AESManaged, where:  | |||
Key  = Common Key  | |||
IV   = the byte array found in the conversion process above  | |||
Mode = CipherMode.CBC  | |||
Create the encryptor (AesManaged.CreateEncryptor(key, iv)) where the key and IV are both the same as above.  | |||
Then, create a CryptoStream and a MemoryStream. The Crypto stream should start with the arguments (memorystream, aes_transform_from_above, CryptoStreamMode.Write).  | |||
Write to the CryptoStream where buffer=unencrypted_titlekey, offset=0, and count=the length of the unencrypted title key.  | |||
Use FlushFinalBlock() on the CryptoStream.  | |||
Finally, then, the encrypted title key will be available from your memory   | |||
stream. (to output the calculated encrypted title key as a byte array, you can use memorystream.ToArray(), for example)  | |||
Example function: (C#)  | |||
<pre>  | |||
        public static byte[] EncryptMyTitleKey(byte[] commonKey, byte[] titleKey, ulong titleId)  | |||
        {  | |||
            // Make encryption IV  | |||
            byte[] titleidasbytes = new byte[0x10];  | |||
            for (int i = 0; i < 0x10; i++)  | |||
            {  | |||
                titleidasbytes[i] = 0;  | |||
            }  | |||
            byte[] bitBytes = BitConverter.GetBytes(titleId);  | |||
            if (BitConverter.IsLittleEndian)  | |||
            {  | |||
                Array.Reverse(bitBytes);  | |||
            }  | |||
            bitBytes.CopyTo(titleidasbytes, 0);  | |||
            // Encrypt  | |||
            ICryptoTransform transform = new AesManaged { Key = commonKey, IV = titleidasbytes, Mode = CipherMode.CBC }.CreateEncryptor(commonKey, titleidasbytes);  | |||
            MemoryStream memstream = new MemoryStream();  | |||
            CryptoStream cryptostream = new CryptoStream(memstream, transform, CryptoStreamMode.Write);  | |||
            cryptostream.Write(titleKey, 0, titleKey.Length);  | |||
            cryptostream.FlushFinalBlock();  | |||
            return memstream.ToArray();  | |||
        }  | |||
</pre>  | |||