Package1: Difference between revisions
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
Present on the firmware package titles (0100000000000819 and 010000000000081A) and installed into eMMC storage's [[#Flash_Filesystem#Boot_Partitions|boot partitions 0 and 1]], "package1" contains the first Switch bootloader to run under the NVIDIA boot processor (an ARM7TDMI called "BPMP", "BPMP-Lite", "AVP" or "COP"). | |||
The boot ROM validates, copies to IRAM and executes this package by parsing it's information block from the [[#BCT|BCT]]. | |||
The | |||
== | = Bootloader = | ||
Split into two main stages, the bootloader is responsible for setting up hardware, generate keys and prepare the main CPU ("CCPLEX"). | |||
== Stage 0 == | |||
The code for this stage is stored in plaintext inside the package. By looking into the BCT's bootloader0_info (normal) or bootloader1_info (safe mode), the boot ROM starts executing this stage at address 0x40010020 in IRAM. | |||
=== | === Initialization === | ||
The stack pointer is set. | |||
// Set the stack pointer | |||
* | *(u32 *)sp = 0x40008000; | ||
// Jump to main | |||
bootloader_main(); | |||
// Infinite loop | |||
deadlock(); | |||
=== | === Main === | ||
The bootloader poisons the exception vectors, cleans up memory (.bss and init_array), sets up hardware devices (including the security engine and fuses), does all the necessary checks, generates keys and finally decrypts and executes the next stage. | |||
// Poison all exception vectors | |||
*(u32 *)0x6000F200 = panic(); | |||
*(u32 *)0x6000F204 = panic(); | |||
*(u32 *)0x6000F208 = panic(); | |||
*(u32 *)0x6000F20C = panic(); | |||
*(u32 *)0x6000F210 = panic(); | |||
*(u32 *)0x6000F214 = panic(); | |||
*(u32 *)0x6000F218 = panic(); | |||
*(u32 *)0x6000F21C = panic(); | |||
u32 bss_addr_end = bss_addr_start; | |||
u32 bss_offset = 0; | |||
u32 bss_size = bss_addr_end - bss_addr_start; | |||
// Clear .bss region | |||
// Never happens due to bss_size being set to 0 | |||
while (bss_offset < bss_size) | |||
{ | |||
*(u32 *)bss_addr_start + bss_offset = 0; | |||
bss_offset += 0x04; | |||
} | |||
u32 init_array_addr_end = init_array_addr_start; | |||
u32 init_array_offset = init_array_addr_start; | |||
// Call init methods | |||
// Never happens due to init_array_addr_end being set to init_array_addr_start | |||
while (init_array_offset < init_array_addr_end) | |||
{ | |||
u32 init_method_offset = *(u32 *)init_array_offset; | |||
call_init_method(init_method_offset + init_array_offset); | |||
init_array_offset += 0x04; | |||
} | |||
// Setup I2S1, I2S2, I2S3, I2S4, DISPLAY and VIC | |||
enable_hw_devices(); | |||
// Program the SE clock and resets | |||
// Uses RST_DEVICES_V, CLK_OUT_ENB_V, CLK_SOURCE_SE and CLK_V_SE | |||
enable_se_clkrst(); | |||
// Set MISC_CLK_ENB | |||
// This makes fuse registers visible | |||
enable_misc_clk(0x01); | |||
// Read FUSE_SKU_INFO and compare with 0x83 | |||
check_sku(); | |||
// Check configuration fuses | |||
check_config_fuses(); | |||
u32 bct_iram_addr = 0x40000000; | |||
// Check bootloader version from BCT | |||
check_bootloader_ver(bct_iram_addr); | |||
// Check anti-downgrade fuses | |||
check_downgrade(); | |||
// Set FUSE_DIS_PGM | |||
// Disables fuse programming until next reboot | |||
disable_fuse_pgm(); | |||
// Setup memory controllers | |||
enable_mem(); | |||
// Setup the security engine's address | |||
set_se_addr(0x70012000); | |||
// Check SE global config | |||
check_se_status(); | |||
// Generate keys | |||
keygen(bct_iram_addr); | |||
u32 stage1_addr = 0x40013FE0; | |||
// Decrypt next stage | |||
stage1_addr = decrypt_stage1(stage1_addr); | |||
u32 stage1_sp = 0x40007000; | |||
// Set the stack pointer and jump to a stub responsible | |||
// for cleaning up and branching into the actual stage 1 | |||
exec_stage1_stub(stage1_addr, stage1_stub_addr, stage1_sp); | |||
return; | |||
==== Panic ==== | ==== Panic ==== | ||
If a panic occurs, all sensitive memory contents are cleared, the security engine and fuse programming are disabled and the boot processor is left in a halted state. | |||
// Clear all stack contents | |||
clear_stack(); | |||
// Terminate the security engine | |||
disable_se(); | |||
* | // Set FUSE_DIS_PGM | ||
// Disables fuse programming until next reboot | |||
disable_fuse_pgm(); | |||
// Clear temporary key storage memory | |||
clear_mem(); | |||
// Clear the stage 1 binary | |||
clear_stage1(); | |||
u32 FLOW_CTLR_HALT_COP_EVENTS = 0x60007004; | |||
u32 FLOW_MODE_STOP = 0x40000000; | |||
u32 HALT_COP_EVENT_JTAG = 0x10000000; | |||
// Halt the boot processor | |||
while (true) | |||
*(u32 *)FLOW_CTLR_HALT_COP_EVENTS = (FLOW_MODE_STOP | HALT_COP_EVENT_JTAG); | |||
=== | ==== Anti-downgrade ==== | ||
See [[Fuses#Anti-downgrade|Anti-downgrade]]. | |||
==== Key generation ==== | |||
After the security engine is ready and before decrypting the next stage, the bootloader initializes and generates several keys into hardware keyslots. | |||
For more details on the Switch's cryptosystem, please see [[#Cryptosystem|this page]]. | |||
==== | ===== Selection ===== | ||
Depending on [[Fuses#FUSE_RESERVED_ODM4|FUSE_RESERVED_ODM4]] and [[Fuses#FUSE_SPARE_BIT_5|FUSE_SPARE_BIT_5]] different static seeds are selected for key generation. | |||
// Initialize keyslots 0x0C and 0x0D as readable | |||
init_keyslot(0x0C, 0x15); | |||
init_keyslot(0x0D, 0x15); | |||
// Find the BCT's data address from IRAM header | |||
u32 bct_data_addr = *(u32 *)bct_imem_addr + 0x4C; | |||
u32 bct_customer_data_addr = *(u32 *)bct_data_addr + 0x450; | |||
// Wrapper to get unit type from FUSE_RESERVED_ODM4 | |||
// This tells if the device is retail or debug | |||
bool is_retail = is_unit_retail(); | |||
u32 master_static_seed_addr = 0; | |||
u32 master_static_seed_size = 0; | |||
if (is_retail) | |||
{ | |||
// Read FUSE_SPARE_BIT_5 | |||
// This tells which master key to use | |||
u32 master_key_ver = read_fuse_spare_bit_5(); | |||
// Invalid for retail | |||
if (!master_key_ver) | |||
panic(); | |||
else | |||
{ | |||
master_static_seed_addr = static_seed1_addr; | |||
master_static_seed_size = 0x10; | |||
// Generate retail keys | |||
generate_retail_keys(bct_customer_data_addr, static_seed_addr, static_seed_size); | |||
} | |||
} | |||
else | |||
{ | |||
// Read FUSE_SPARE_BIT_5 | |||
// This tells which master key to use | |||
u32 master_key_ver = read_fuse_spare_bit_5(); | |||
// Use debug key set | |||
if (!master_key_ver) | |||
{ | |||
// Read the first byte of the BCT RSA PSS signature | |||
u8 rsa_pss_1_byte = *(u8 *)bct_data_addr + 0x210; | |||
if (rsa_pss_1_byte == 0x11) | |||
{ | |||
master_static_seed_addr = static_seed6_addr; | |||
master_static_seed_size = 0x10; | |||
} | |||
else | |||
{ | |||
master_static_seed_addr = static_seed7_addr; | |||
master_static_seed_size = 0x10; | |||
} | |||
// Generate debug keys | |||
generate_debug_keys(static_seed_addr, static_seed_size); | |||
} | |||
else | |||
{ | |||
// Read the first byte of the BCT RSA PSS signature | |||
u8 rsa_pss_1_byte = *(u8 *)bct_data_addr + 0x210; | |||
if (rsa_pss_1_byte == 0x4F) // Different key as in retail mode | |||
{ | |||
master_static_seed_addr = static_seed0_addr; | |||
master_static_seed_size = 0x10; | |||
} | |||
else // Same key as in retail mode | |||
{ | |||
master_static_seed_addr = static_seed1_addr; | |||
master_static_seed_size = 0x10; | |||
} | |||
// Generate retail keys | |||
generate_retail_keys(bct_customer_data_addr, master_static_seed_addr, master_static_seed_size); | |||
} | |||
} | |||
// Initialize keyslots 0x0C and 0x0D as unreadable | |||
init_keyslot(0x0C, 0xFF); | |||
init_keyslot(0x0D, 0xFF); | |||
return; | |||
===== generate_retail_keys ===== | |||
In order to generate retail keys, the bootloader starts by initializing TSEC and grabbing it's [[TSEC#Device_key_generation|device key]]. Using static seeds and the SBK, the keyblob injected into the BCT's [[BCT#customer_data|customer_data]] is validated and decrypted. The resulting keys will then be used to generate the master static key and the master device key. | |||
See the pseudocode bellow for the detailed process. | |||
==== | u32 in_addr = 0; | ||
u32 in_size = 0; | |||
u32 out_addr = 0; | |||
u32 out_size = 0; | |||
u32 keyslot = 0; | |||
u32 keyslot_dst = 0; | |||
// Get the TSEC device key | |||
tsec_get_device_key(tsec_device_key_addr, 0x10); | |||
// Install the TSEC device key into keyslot 0x0D | |||
set_keyslot_data(0x0D, tsec_device_key_addr, 0x10); | |||
in_addr = static_seed2_addr; | |||
in_size = 0x10; | |||
out_addr = keyblob_device_key_addr; | |||
out_size = 0x10; | |||
keyslot = 0x0D; | |||
// Use the tsec_device_key (keyslot 0x0D) to decrypt the static_seed2 | |||
// This generates the keyblob_device_key | |||
aes_ecb_decrypt(out_addr, out_size, keyslot, in_addr, in_size); | |||
in_addr = keyblob_device_key_addr; | |||
in_size = 0x10; | |||
keyslot = 0x0E; | |||
keyslot_dst = 0x0D; | |||
// Use SBK (keyslot 0x0E) to further decrypt the | |||
// keyblob_device_key and install it into keyslot 0x0D | |||
// This will generate the keyblob_key | |||
decrypt_keyslot(keyslot_dst, keyslot, in_addr, in_size); | |||
// Clear SBK and SSK keyslots | |||
clear_keyslot(0x0E); | |||
clear_keyslot(0x0F); | |||
in_addr = static_seed4_addr; | |||
in_size = 0x10; | |||
keyslot = 0x0D; | |||
keyslot_dst = 0x0B; | |||
// Use keyblob_key (keyslot 0x0D) to decrypt the | |||
// static_seed4_addr and install it to keyslot 0x0B | |||
// This will generate the bct_mac_key | |||
decrypt_keyslot(keyslot_dst, keyslot, in_addr, in_size); | |||
in_addr = bct_customer_data_addr + 0x10; | |||
in_size = 0xA0; | |||
out_addr = mac_addr; | |||
out_size = 0x10; | |||
keyslot = 0x0B; | |||
// Use the bct_mac_key (keyslot 0x0B) to generate | |||
// CMAC over bct_customer_data_addr + 0x10 | |||
aes_cmac(out_addr, out_size, keyslot, in_addr, in_size); | |||
// Comapre the generated hash with the first | |||
// 0x10 bytes of bct_customer_data | |||
bool match = safe_memcmp(mac_addr, bct_customer_data_addr, 0x10); | |||
// Hashes don't match | |||
if (!match) | |||
panic(); | |||
in_addr = bct_customer_data_addr + 0x20; | |||
in_size = 0x90; | |||
ctr_addr = bct_customer_data_addr + 0x10; | |||
ctr_size = 0x10; | |||
out_addr = dec_payload_addr; | |||
out_size = 0x90; | |||
keyslot = 0x0D; | |||
// AES-CTR decrypt | |||
// Use the keyblob_key (keyslot 0x0D) to decrypt bct_customer_data_addr + 0x20 | |||
// using bct_customer_data_addr + 0x10 as CTR | |||
aes_ctr_decrypt(out_addr, out_size, keyslot, in_addr, in_size, ctr_addr, ctr_size); | |||
// Install the last decrypted keyblob key into keyslot 0x0B | |||
// This is the pk11_key | |||
set_keyslot_data(0x0B, dec_payload_addr + 0x80, 0x10); | |||
// Install the first decrypted keyblob key into keyslot 0x0C | |||
// This is the master_static_kek | |||
set_keyslot_data(0x0C, dec_payload_addr, 0x10); | |||
// Clear out the decrypted data | |||
memclear(dec_payload_addr, 0x90); | |||
in_addr = master_static_seed_addr; | |||
in_size = master_static_seed_size; | |||
keyslot = 0x0C; | |||
keyslot_dst = 0x0C; | |||
// Use the master_static_kek (keyslot 0x0C) to decrypt | |||
// master_static_seed and install it into keyslot 0x0C | |||
// This will generate the master_static_key | |||
decrypt_keyslot(keyslot_dst, keyslot, in_addr, in_size); | |||
in_addr = static_seed3_addr; | |||
in_size = 0x10; | |||
keyslot = 0x0D; | |||
keyslot_dst = 0x0D; | |||
// Use keyblob_key (keyslot 0x0D) to decrypt | |||
// static_seed3_addr and install it into keyslot 0x0D | |||
// This will generate the master_device_key | |||
decrypt_keyslot(keyslot_dst, keyslot, in_addr, in_size); | |||
return; | |||
===== generate_debug_keys ===== | |||
In order to generate debug keys, the bootloader only uses static seeds, the SBK and the SSK. | |||
See the pseudocode bellow for the detailed process. | |||
u32 in_addr = 0; | |||
u32 in_size = 0; | |||
u32 keyslot = 0; | |||
u32 keyslot_dst = 0; | |||
in_addr = static_seed8_addr; | |||
in_size = 0x10; | |||
keyslot = 0x0E; | |||
keyslot_dst = 0x0B; | |||
// Use SBK (keyslot 0x0E) to decrypt the | |||
// static_seed8 and install it to keyslot 0x0B | |||
// This will generate debug_pk11_key | |||
decrypt_keyslot(keyslot_dst, keyslot, in_addr, in_size); | |||
in_addr = static_seed5_addr; | |||
in_size = 0x10; | |||
keyslot = 0x0E; | |||
keyslot_dst = 0x0C; | |||
// Use SBK (keyslot 0x0E) to decrypt the | |||
// static_seed5 and install it to keyslot 0x0C | |||
// This will generate debug_master_static_kek | |||
decrypt_keyslot(keyslot_dst, keyslot, in_addr, in_size); | |||
in_addr = static_seed9_addr; | |||
in_size = 0x10; | |||
keyslot = 0x0F; | |||
keyslot_dst = 0x0D; | |||
// Use SSK (keyslot 0x0F) to decrypt the | |||
// static_seed9 and install it to keyslot 0x0D | |||
// This will generate debug_keyblob_key | |||
decrypt_keyslot(keyslot_dst, keyslot, in_addr, in_size); | |||
// Clear SBK and SSK keyslots | |||
clear_keyslot(0x0E); | |||
clear_keyslot(0x0F); | |||
in_addr = master_static_seed_addr; | |||
in_size = master_static_seed_size; | |||
keyslot = 0x0C; | |||
keyslot_dst = 0x0C; | |||
// Use the debug_master_static_kek (keyslot 0x0C) to decrypt the | |||
// master_static_seed and install it to keyslot 0x0C | |||
// This will generate the master_static_key | |||
decrypt_keyslot(keyslot_dst, keyslot, in_addr, in_size); | |||
in_addr = static_seed3_addr; | |||
in_size = 0x10; | |||
keyslot = 0x0D; | |||
keyslot_dst = 0x0D; | |||
// Use debug_keyblob_key (keyslot 0x0D) to decrypt the | |||
// static_seed3 and install it to keyslot 0x0D | |||
// This will generate the master_device_key | |||
decrypt_keyslot(keyslot_dst, keyslot, in_addr, in_size); | |||
return; | |||
== | == Stage 1 == | ||
Known as "package1.1", the code for this stage is stored encrypted inside the package. When decrypted, this stage is encapsulated in a header. | |||
=== Header === | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 108: | Line 434: | ||
| 0x4 | | 0x4 | ||
| 4 | | 4 | ||
| | | Main size | ||
|- | |- | ||
| 0x8 | | 0x8 | ||
Line 116: | Line 442: | ||
| 0x10 | | 0x10 | ||
| 4 | | 4 | ||
| | | Section 0 size | ||
|- | |- | ||
| 0x14 | | 0x14 | ||
| 4 | | 4 | ||
| | | Section 0 offset | ||
|- | |- | ||
| 0x18 | | 0x18 | ||
| 4 | | 4 | ||
| | | Section 1 size | ||
|- | |- | ||
| 0x1C | | 0x1C | ||
| 4 | | 4 | ||
| | | Section 1 offset | ||
|} | |} | ||
= Changelog = | |||
== 3.0.0 == | |||
* The functions set_se_addr() and check_se_status() are now called right after enabling the security engine clocks and resets. | |||
See [[Switch_System_Flaws#Stage_1_Bootloader]]. | |||
* Keyslot 0x0A is now used instead of keyslot 0x0D for generating the master_device_key. |