Package1: Difference between revisions
m →generate_retail_keys:  typo  | 
				 This one is really "Version" (see t186 cboot source)  | 
				||
| (9 intermediate revisions by 3 users not shown) | |||
| Line 4: | Line 4: | ||
= Format =  | = Format =  | ||
== Erista ==  | |||
This package is distributed as a plaintext initial bootloader (package1ldr) and a secondary encrypted blob ("PK11"). Execution starts at plaintext package1ldr which will set up hardware, generate keys and decrypt the next stage.  | This package is distributed as a plaintext initial bootloader (package1ldr) and a secondary encrypted blob ("PK11"). Execution starts at plaintext package1ldr which will set up hardware, generate keys and decrypt the next stage.  | ||
=== Header ===  | === Header ===  | ||
{| class="wikitable" border="1"  | {| class="wikitable" border="1"  | ||
|-  | |-  | ||
| Line 19: | Line 16: | ||
| 0x0  | | 0x0  | ||
| 0x4  | | 0x4  | ||
| Package1ldr hash (first four bytes of SHA256(package1ldr))  | | Package1ldr hash (first four bytes of SHA256(package1ldr))  | ||
|-  | |-  | ||
| 0x4  | | 0x4  | ||
| 0x4  | | 0x4  | ||
| Secure Monitor hash (first four bytes of SHA256(secure_monitor))  | | Secure Monitor hash (first four bytes of SHA256(secure_monitor))  | ||
|-  | |-  | ||
| 0x8  | | 0x8  | ||
| 0x4  | | 0x4  | ||
| NX Bootloader hash (first four bytes of SHA256(nx_bootloader))  | | NX Bootloader hash (first four bytes of SHA256(nx_bootloader))  | ||
|-  | |-  | ||
| 0xC  | | 0xC  | ||
| 0x4  | | 0x4  | ||
|   | | Build ID  | ||
|-  | |-  | ||
| 0x10  | | 0x10  | ||
| Line 38: | Line 35: | ||
|-  | |-  | ||
| 0x1E  | | 0x1E  | ||
|   | | 0x1  | ||
|   | | [7.0.0+] Key Generation  | ||
|-  | |-  | ||
| 0x1F  | |||
| 0x1  | |||
| Version  | |||
|}  | |}  | ||
=== Initialization ===  | === Package1ldr ===  | ||
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 (0x40010040 for 4.0.0+).  | |||
==== Initialization ====  | |||
The stack pointer is set.  | The stack pointer is set.  | ||
| Line 57: | Line 60: | ||
</syntaxhighlight>  | </syntaxhighlight>  | ||
=== Main ===  | ==== 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.  | 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.  | ||
| Line 97: | Line 100: | ||
  // Setup I2S1, I2S2, I2S3, I2S4, DISPLAY and VIC  |   // Setup I2S1, I2S2, I2S3, I2S4, DISPLAY and VIC  | ||
  mbist_workaround();  | |||
  // Program the SE clock and resets  |   // Program the SE clock and resets  | ||
| Line 151: | Line 154: | ||
</syntaxhighlight>  | </syntaxhighlight>  | ||
==== Panic ====  | [6.2.0+] The bootloader maintains most of its design, but passes execution to a [[TSEC]] payload and is left in an infinite loop.  | ||
<syntaxhighlight lang="c">  | |||
 // 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  | |||
 mbist_workaround();  | |||
 // 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);  | |||
 // Setup the security engine's address  | |||
 set_se_addr(0x70012000);  | |||
 // Check SE global config  | |||
 check_se_status();  | |||
 // 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();  | |||
 // Setup memory controllers  | |||
 enable_mem_ctl();  | |||
 // Clear SYS_CLK_DIVISOR  | |||
 *(u32 *)CLK_SOURCE_SYS = 0;  | |||
 // Place I2C5 in reset  | |||
 u32 rst_dev_h_val = *(u32 *)RST_DEVICES_H;  | |||
 rst_dev_h_val &= ~(0x8000);  | |||
 rst_dev_h_val |= 0x8000;  | |||
 *(u32 *)RST_DEVICES_H = rst_dev_h_val;  | |||
 // Program the HOST1X clock and resets  | |||
 // Uses RST_DEVICES_L, CLK_OUT_ENB_L, CLK_SOURCE_HOST1X and CLK_L_HOST1X  | |||
 enable_host1x_clkrst();  | |||
 // Program the TSEC clock and resets  | |||
 // Uses RST_DEVICES_U, CLK_OUT_ENB_U, CLK_SOURCE_TSEC and CLK_U_TSEC  | |||
 enable_tsec_clkrst();  | |||
 // Program the SOR_SAFE clock and resets  | |||
 // Uses RST_DEVICES_Y, CLK_OUT_ENB_Y and CLK_Y_SOR_SAFE  | |||
 enable_sor_safe_clkrst();  | |||
 // Program the SOR0 clock and resets  | |||
 // Uses RST_DEVICES_X, CLK_OUT_ENB_X and CLK_X_SOR0  | |||
 enable_sor0_clkrst();  | |||
 // Program the SOR1 clock and resets  | |||
 // Uses RST_DEVICES_X, CLK_OUT_ENB_X, CLK_SOURCE_SOR1 and CLK_X_SOR1  | |||
 enable_sor1_clkrst();  | |||
 // Program the KFUSE clock resets  | |||
 // Uses RST_DEVICES_H, CLK_OUT_ENB_H and CLK_H_KFUSE  | |||
 enable_kfuse_clkrst();  | |||
 // Clear the Falcon DMA control register  | |||
 *(u32 *)FALCON_DMACTL = 0;  | |||
 // Enable Falcon IRQs  | |||
 *(u32 *)FALCON_IRQMSET = 0xFFF2;  | |||
 // Enable Falcon IRQs  | |||
 *(u32 *)FALCON_IRQDEST = 0xFFF0;  | |||
 // Enable Falcon interfaces  | |||
 *(u32 *)FALCON_ITFEN = 0x03;  | |||
 // Wait for Falcon's DMA engine to be idle  | |||
 wait_flcn_dma_idle();  | |||
 // Set DMA transfer base address to 0x40010E00>> 0x08  | |||
 *(u32 *)FALCON_DMATRFBASE = 0x40010E;  | |||
 u32 trf_mode = 0;     // A value of 0 sets FALCON_DMATRFCMD_IMEM  | |||
 u32 dst_offset = 0;  | |||
 u32 src_offset = 0;  | |||
 // Load code into Falcon (0x100 bytes at a time)  | |||
 while (src_offset < 0x2900)  | |||
 {  | |||
    flcn_load_firm(trf_mode, src_offset, dst_offset);  | |||
    src_offset += 0x100;  | |||
    dst_offset += 0x100;  | |||
 }  | |||
 // Set magic value in host1x scratch space  | |||
 *(u32 *)0x50003300 = 0x34C2E1DA;  | |||
 // Clear Falcon scratch1 MMIO  | |||
 *(u32 *)FALCON_SCRATCH1 = 0;  | |||
 // Set Falcon boot key version in scratch0 MMIO  | |||
 *(u32 *)FALCON_SCRATCH0 = 0x01;  | |||
 // Set Falcon's boot vector address  | |||
 *(u32 *)FALCON_BOOTVEC = 0;  | |||
 // Signal Falcon's CPU  | |||
 *(u32 *)FALCON_CPUCTL = 0x02;  | |||
 // Infinite loop  | |||
 deadlock();  | |||
</syntaxhighlight>  | |||
===== 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.  | 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.  | ||
| Line 170: | Line 327: | ||
  // Clear the PK11 blob from memory  |   // Clear the PK11 blob from memory  | ||
  clear_pk11_blob();  |   clear_pk11_blob();  | ||
  // Halt the boot processor  |   // Halt the boot processor  | ||
| Line 180: | Line 333: | ||
</syntaxhighlight>  | </syntaxhighlight>  | ||
==== Anti-downgrade ====  | ===== Anti-downgrade =====  | ||
See [[Fuses#Anti-downgrade|Anti-downgrade]].  | See [[Fuses#Anti-downgrade|Anti-downgrade]].  | ||
==== Memory controllers ====  | ===== Memory controllers =====  | ||
After disabling fuse programming, the bootloader configures the EMC and MEM/MC. It additionally disables QSPI resets and programs a special aperture designed for AHB redirected access to IRAM.  | After disabling fuse programming, the bootloader configures the EMC and MEM/MC. It additionally disables QSPI resets and programs a special aperture designed for AHB redirected access to IRAM.  | ||
<syntaxhighlight lang="c">  | <syntaxhighlight lang="c">    | ||
  // Initialize EMC's clock source  |   // Initialize EMC's clock source  | ||
  u32 emc_clk_src_val = *(u32 *)PERIPH_CLK_SOURCE_EMC;  |   u32 emc_clk_src_val = *(u32 *)PERIPH_CLK_SOURCE_EMC;  | ||
| Line 246: | Line 390: | ||
</syntaxhighlight>  | </syntaxhighlight>  | ||
==== Key generation ====  | [6.2.0+] MC_IRAM_TOM is now set to 0x80000000 to allow TSEC to access IRAM and all MMIO.  | ||
===== Key generation =====  | |||
After the security engine is ready and before decrypting the next stage, the bootloader initializes and generates several keys into hardware keyslots.  | 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]].  | For more details on the Switch's cryptosystem, please see [[Cryptosystem|this page]].  | ||
===== Selection =====  | [6.2.0+] The key generation process was moved into an encrypted [[TSEC]] payload.  | ||
====== 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.  | 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.  | ||
| Line 341: | Line 489: | ||
</syntaxhighlight>  | </syntaxhighlight>  | ||
===== generate_retail_keys =====  | ====== generate_retail_keys ======  | ||
In order to generate retail keys, the bootloader starts by initializing TSEC and grabbing it's [[TSEC#  | In order to generate retail keys, the bootloader starts by initializing TSEC and grabbing it's [[TSEC#TSEC_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.  | See the pseudocode bellow for the detailed process.  | ||
| Line 459: | Line 607: | ||
</syntaxhighlight>  | </syntaxhighlight>  | ||
===== generate_debug_keys =====  | ====== generate_debug_keys ======  | ||
In order to generate debug keys, the bootloader only uses static seeds, the SBK and the SSK.  | In order to generate debug keys, the bootloader only uses static seeds, the SBK and the SSK.  | ||
| Line 527: | Line 675: | ||
</syntaxhighlight>  | </syntaxhighlight>  | ||
== Package1 (PK11) ==  | === Package1 (PK11) ===  | ||
This blob is stored encrypted inside the package and is decrypted by package1ldr.  | This blob is stored encrypted inside the package and is decrypted by package1ldr.  | ||
=== Encryption ===  | ==== Encryption ====  | ||
The encrypted blob is prepended with it's CTR and total image size. After checking the image's size against an hardcoded value (can change on firmware updates), the image is AES-CTR decrypted and the keyslot used for decryption is immediately cleared.  | The encrypted blob is prepended with it's CTR and total image size. After checking the image's size against an hardcoded value (can change on firmware updates), the image is AES-CTR decrypted and the keyslot used for decryption is immediately cleared.  | ||
| Line 578: | Line 726: | ||
</syntaxhighlight>  | </syntaxhighlight>  | ||
=== Header ===  | ==== Header ====  | ||
When decrypted, the blob is encapsulated in the following header.  | When decrypted, the blob is encapsulated in the following header.  | ||
| Line 622: | Line 770: | ||
What each section is used for may vary per system-version.  | What each section is used for may vary per system-version.  | ||
=== Section 0 ===  | ==== Section 0 ====  | ||
This section contains the warmboot binary.  | This section contains the warmboot binary.  | ||
=== Section 1 ===  | ==== Section 1 ====  | ||
This section contains the NX bootloader, which is run after the initial bootloader in package1.  | This section contains the NX bootloader, which is run after the initial bootloader in package1.  | ||
=== Section 2 ===  | ==== Section 2 ====  | ||
This section contains the Secure Monitor binary.  | This section contains the Secure Monitor binary.  | ||
=   | == Mariko ==  | ||
This package is now distributed in a custom, signed and encrypted format.  | |||
{| class="wikitable" border="1"  | |||
|-  | |||
! Offset  | |||
! Size  | |||
! Description  | |||
|-  | |||
| 0x0  | |||
| 0x110  | |||
| Cryptographic signature  | |||
  0x0000: CryptoHash (empty)  | |||
  0x0010: RsaPssSig  | |||
|-  | |||
| 0x110  | |||
| 0x20  | |||
| Random block  | |||
|-  | |||
| 0x130  | |||
| 0x20  | |||
| SHA256 hash over package1 data  | |||
|-  | |||
| 0x150  | |||
| 0x4  | |||
| Version  | |||
|-  | |||
| 0x154  | |||
| 0x4  | |||
| Length  | |||
|-  | |||
| 0x158  | |||
| 0x4  | |||
| LoadAddress  | |||
|-  | |||
| 0x15C  | |||
| 0x4  | |||
| EntryPoint  | |||
|-  | |||
| 0x160  | |||
| 0x10  | |||
| Reserved  | |||
|-  | |||
| 0x170  | |||
| Variable  | |||
| Package1 data  | |||
 0x0170: [[Package1#Header|Header]]  | |||
 0x0190: Body (encrypted)  | |||
|}  | |||