Changes

1,066 bytes added ,  20:18, 6 March 2015
Line 70: Line 70:  
== [[New_3DS]] FIRM ==
 
== [[New_3DS]] FIRM ==
 
For New3DS firmwares (NATIVE_FIRM, TWL_FIRM, ..), the ARM9 FIRM binary has an additional layer of crypto. At the end of each ARM9 binary, there's a plaintext loader. The format of the FIRM header is identical to regular 3DS FIRM(the RSA modulo is the same as regular 3DS too).
 
For New3DS firmwares (NATIVE_FIRM, TWL_FIRM, ..), the ARM9 FIRM binary has an additional layer of crypto. At the end of each ARM9 binary, there's a plaintext loader. The format of the FIRM header is identical to regular 3DS FIRM(the RSA modulo is the same as regular 3DS too).
 +
 +
Before checking 0x10000000 the loader main() does the following:
 +
* On [[9.5.0-22|9.5.0-X]]: executes a nop instruction with r0=0 and r1=<address of arm9binhdr+0x50>.
 +
* Clears bit6 in [[AES_Registers|REG_AESKEYCNT]].
    
If (u8*)0x10000000 bit 1 is clear (which means that this happens only on hard reboots), it does the following things:
 
If (u8*)0x10000000 bit 1 is clear (which means that this happens only on hard reboots), it does the following things:
* On [[9.5.0-22|9.5.0-X]]: executes a nop instruction with r0=0 and r1=<address of arm9binhdr+0x50>.
+
* Clears 0x200-bytes on the stack, then reads [[Flash_Filesystem|NAND]] sector 0x96(NAND image offset 0x12C00), with size 0x200-bytes into that stack buffer.
* Hashes data from the region [[IO|0x10012000-0x10012090]] using SHA256 via the [[SHA_Registers|SHA]] hardware.
+
* Checks u8 0x10000000 bit1 again, if it's set then it executes a panic function(set r0-r2=0, execute nop instruction, then execute instruction "bkpt 0x99"). Hashes data from the region [[IO_Registers|0x10012000-0x10012090]] using SHA256 via the [[SHA_Registers|SHA]] hardware.
* Initializes AES keyslot 0x11 keyX, keyY to the lower and higher portion of that hash, respectively. Due to the above hashed data, the keyX+keyY here are console-unique.
+
* Clears bit6 in [[AES_Registers|REG_AESKEYCNT]]. Initializes AES keyslot 0x11 keyX, keyY to the lower and higher portion of the above hash, respectively. Due to the above hashed data, the keyX+keyY here are console-unique.
* Reads [[Flash_Filesystem|NAND]] sector 0x96(NAND image offset 0x12C00), with size 0x200-bytes. Decrypts the first 0x10-byte block in that sector with keyslot 0x11 using AES-ECB. Then the normalkey, keyX, and keyY, for keyslot 0x11 are cleared to zero. Then it uses the output block to set the normalkey for keyslot 0x11.
+
* Decrypts the first 0x10-byte block in the above read NAND sector with keyslot 0x11 using AES-ECB. Then the normalkey, keyX, and keyY, for keyslot 0x11 are cleared to zero. Runs the TWL key-init/etc code which was originally in the ARM9-kernel, then writes 0x2 to [[CONFIG_Registers|REG_SYSPROT9]]. Then it uses the output block to set the normalkey for keyslot 0x11.
 
* Decrypts arm9_bin_buf+0 using keyslot 0x11 with AES-ECB, and initialises keyX for keyslot 0x15 with it.
 
* Decrypts arm9_bin_buf+0 using keyslot 0x11 with AES-ECB, and initialises keyX for keyslot 0x15 with it.
* Initialises KeyX for keyslots 0x18..0x1F with the output of decrypting a 0x10-byte block with AES-ECB using keyslot 0x11. This block sits 0xA0 before the end of the ARM9 binary, and has a SHA-256 of 219DA61289A1D8A85F403A8BC6EBA635269D72FE592EF97DED1D4F7BBDC789E6. The last byte in this 0x10-byte input block is increased by 0x01 after initializing each keyslot. These are New3DS-specific keys.
+
* Initialises KeyX for keyslots 0x18..0x1F with the output of decrypting a 0x10-byte block with AES-ECB using keyslot 0x11. Before doing the crypto each time, the loader sets the normal-key for keyslot 0x11 to the same one already decrypted on the stack. This block sits 0xA0 before the end of the ARM9 binary, and has a SHA-256 of 219DA61289A1D8A85F403A8BC6EBA635269D72FE592EF97DED1D4F7BBDC789E6. The last byte in this 0x10-byte input block is increased by 0x01 after initializing each keyslot. These are New3DS-specific keys.
* [[9.5.0-22|9.5.0-X]]: Decrypts the 0x10-byte block at arm9binhdr+0x60 with AES-ECB using keyslot 0x11, then sets the keyX for keyslot 0x16 to the output data. The normalkey, keyX, and keyY, for keyslot 0x11 are cleared to zero.
+
* [[9.5.0-22|9.5.0-X]]: Sets the normal-key for keyslot 0x11 to the same one already decrypted on the stack. Decrypts the 0x10-byte block at arm9binhdr+0x60 with AES-ECB using keyslot 0x11, then sets the keyX for keyslot 0x16 to the output data. The normalkey, keyX, and keyY, for keyslot 0x11 are cleared to zero.
    
When (u8*)0x10000000 bit 1 is set(which means this happens only when this loader runs again for firm-launch), the normalkey, keyX, and keyY, for keyslot 0x11 are cleared to zero.
 
When (u8*)0x10000000 bit 1 is set(which means this happens only when this loader runs again for firm-launch), the normalkey, keyX, and keyY, for keyslot 0x11 are cleared to zero.
   −
It sets KeyY for keyslot 0x15(0x16 with [[9.5.0-22|9.5.0-X]]) to arm9_bin_buf+16, the CTR to arm9_bin_buf+32 (both are unique for every version). It then proceeds to decrypt the binary with AES-CTR. When done, it decrypts arm9_bin_buf+64 using an hardcoded keyY for keyslot 0x15(0x16 with [[9.5.0-22|9.5.0-X]]) and makes sure it's all zeroes. If it is, it does some cleanup then it jumps to the entrypoint for the decrypted binary. Otherwise it will just loop forever.
+
It sets KeyY for keyslot 0x15(0x16 with [[9.5.0-22|9.5.0-X]]) to arm9_bin_buf+16, the CTR to arm9_bin_buf+32 (both are unique for every version). It then proceeds to decrypt the binary with AES-CTR. When done, it sets the normal-key for the keyslot used for binary decryption to zeros. It then decrypts arm9_bin_buf+64 using an hardcoded keyY for keyslot 0x15(0x16 with [[9.5.0-22|9.5.0-X]]), sets the normal-key for this keyslot to zeros again, then makes sure the output block is all zeroes. If it is, it does some cleanup then it jumps to the entrypoint for the decrypted binary. Otherwise it will clear the keyX, keyY, and normal-key for each of the keyslots initialized by this loader, do cleanup(same cleanup as when the decrypted block is all-zero) then just loop forever.
    
Thus, the ARM9 binary has the following header:
 
Thus, the ARM9 binary has the following header: