TSEC Firmware: Difference between revisions
No edit summary  | 
				No edit summary  | 
				||
| Line 1,387: | Line 1,387: | ||
     set_excp_vec(entry_addr);  |      set_excp_vec(entry_addr);  | ||
     // Fill the top 0x500 bytes in DMEM with a pointer to trap function (just exits)  |      // Fill the top 0x500 bytes in DMEM with a pointer to trap function (just exits 3 times)  | ||
     for (int i = 0; i < 0x500; i += 0x04) {  |      for (int i = 0; i < 0x500; i += 0x04) {  | ||
         *(u32 *)i = (u32)trap_func();  |          *(u32 *)i = (u32)trap_func();  | ||
| Line 1,421: | Line 1,421: | ||
</pre>  | </pre>  | ||
[7.0.0+]  | [7.0.0+] Many changes were introduced to mitigate and prevent attacks.  | ||
<pre>  | |||
    // Recover the transfer base address from the stack  | |||
    u32 xfer_ext_base_addr = *(u32 *)scratch_data_addr;  | |||
    // Return the TLB entry that covers the virtual address  | |||
    u32 tlb_entry = vtlb(xfer_ext_base_addr);  | |||
    // Clear Falcon CPU control  | |||
    *(u32 *)FALCON_CPUCTL = 0;  | |||
    // Halt if the external page is marked as secret  | |||
    if ((tlb_entry & 0x4000000) != 0)  | |||
        exit();  | |||
    // Read data segment size from IO space  | |||
    u32 data_seg_size = *(u32 *)FALCON_HWCFG;  | |||
    data_seg_size >>= 0x01;  | |||
    data_seg_size &= 0xFF00;  | |||
    // Set the stack pointer  | |||
    $sp = data_seg_size;  | |||
    // Fill all DMEM with a pointer to a trap function (just exits 3 times)  | |||
    for (int i = 0; i < data_seg_size; i += 0x04) {  | |||
        *(u32 *)i = (u32)trap_func();  | |||
    }  | |||
    // Initialize the TRNG and generate random data in DMEM  | |||
    init_rnd();  | |||
    // Issue a randomized delay and return a random value  | |||
    u32 rnd_val = rnd_delay(0xFF);  | |||
    // Enable and test SMMU bypassing in the TFBIF  | |||
    tfbif_smmu_cfg(0x01);  | |||
    // Issue a randomized delay and return a random value  | |||
    rnd_val = rnd_delay(0xFF);  | |||
    // Test SMMU bypassing in the TFBIF  | |||
    tfbif_smmu_cfg(0x00);  | |||
    // Issue a randomized delay and return a random value  | |||
    rnd_val = rnd_delay(0xFF);  | |||
    // Test SMMU bypassing in the TFBIF  | |||
    tfbif_smmu_cfg(0x00);  | |||
    // Fill SE keyslots 12 and 13 with random data  | |||
    se_set_keyslot_rnd();  | |||
    // Test randomized offsets for read/write integrity in MC, FUSE, IRAM and TZRAM  | |||
    u32 test_res = test_mc_fuse_iram_tzram();  | |||
    if (test_res != 0xAAAAAAAA)  | |||
    {  | |||
        // Fill SE keyslots 12 and 13 with random data  | |||
        se_set_keyslot_rnd();  | |||
        // Clear the entire DMEM region and every crypto register  | |||
        clear_dmem_and_crypto();  | |||
        // Halt 5 times for no good reason  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
    }  | |||
    // Try to detect virtualization by enabling and disabling random CAR devices  | |||
    test_res = test_car();  | |||
    if (test_res != 0xAAAAAAAA)  | |||
    {  | |||
        // Fill SE keyslots 12 and 13 with random data  | |||
        se_set_keyslot_rnd();  | |||
        // Clear the entire DMEM region and every crypto register  | |||
        clear_dmem_and_crypto();  | |||
        // Halt 5 times for no good reason  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
    }  | |||
    // Test memory transfer integrity  | |||
    test_res = test_mem_xfer();  | |||
    if (test_res != 0xAAAAAAAA)  | |||
    {  | |||
        // Fill SE keyslots 12 and 13 with random data  | |||
        se_set_keyslot_rnd();  | |||
        // Clear the entire DMEM region and every crypto register  | |||
        clear_dmem_and_crypto();  | |||
        // Halt 5 times for no good reason  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
    }  | |||
    // Set FLOW_MODE_WAITEVENT in FLOW_CTLR_HALT_COP_EVENTS_0  | |||
    halt_bpmp();  | |||
    // Initialize the CCPLEX  | |||
    ccplex_init();  | |||
    // Check if SE is ready  | |||
    u32 se_status = check_se_status();  | |||
    if (se_status != 0)  | |||
    {  | |||
        // Fill SE keyslots 12 and 13 with random data  | |||
        se_set_keyslot_rnd();  | |||
        // Clear the entire DMEM region and every crypto register  | |||
        clear_dmem_and_crypto();  | |||
        // Halt 5 times for no good reason  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
    }  | |||
    // Load the TSEC key from SOR1 registers into DMEM  | |||
    sor1_get_key();  | |||
    // Initialize CAR registers  | |||
    car_init();  | |||
    // Check certain CAR, PMC and FUSE registers  | |||
    test_car_pmc_fuse();  | |||
    // Try to detect virtualization by enabling and disabling random CAR devices  | |||
    test_res = test_car();  | |||
    if (test_res != 0xAAAAAAAA)  | |||
    {  | |||
        // Fill SE keyslots 12 and 13 with random data  | |||
        se_set_keyslot_rnd();  | |||
        // Clear the entire DMEM region and every crypto register  | |||
        clear_dmem_and_crypto();  | |||
        // Halt 5 times for no good reason  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
    }  | |||
    // Ensure FUSE_SKU_INFO is 0x83  | |||
    test_fuse_sku_info();  | |||
    // Try to detect virtualization using MC_SMMU_AVPC_ASID and FUSE_ECO_RESERVE_0  | |||
    test_smmu_fuse();  | |||
    // Test MC_IRAM_BOM and MC_IRAM_TOM  | |||
    test_res = test_mc_iram_aperture();  | |||
    if (test_res != 0xAAAAAAAA)  | |||
    {  | |||
        // Fill SE keyslots 12 and 13 with random data  | |||
        se_set_keyslot_rnd();  | |||
        // Clear the entire DMEM region and every crypto register  | |||
        clear_dmem_and_crypto();  | |||
        // Halt 5 times for no good reason  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
    }  | |||
    // Check certain CAR, PMC and FUSE registers  | |||
    test_car_pmc_fuse();  | |||
    // Test memory transfer integrity  | |||
    test_res = test_mem_xfer();  | |||
    if (test_res != 0xAAAAAAAA)  | |||
    {  | |||
        // Fill SE keyslots 12 and 13 with random data  | |||
        se_set_keyslot_rnd();  | |||
        // Clear the entire DMEM region and every crypto register  | |||
        clear_dmem_and_crypto();  | |||
        // Halt 5 times for no good reason  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
    }  | |||
    // Try to detect virtualization using MC_SMMU_AVPC_ASID and FUSE_ECO_RESERVE_0  | |||
    test_smmu_fuse();  | |||
    // Test MC_IRAM_BOM and MC_IRAM_TOM  | |||
    test_res = test_mc_iram_aperture();  | |||
    if (test_res != 0xAAAAAAAA)  | |||
    {  | |||
        // Fill SE keyslots 12 and 13 with random data  | |||
        se_set_keyslot_rnd();  | |||
        // Clear the entire DMEM region and every crypto register  | |||
        clear_dmem_and_crypto();  | |||
        // Halt 5 times for no good reason  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
    }  | |||
    // Test SMMU bypassing in the TFBIF  | |||
    tfbif_smmu_cfg(0x00);  | |||
    // Decrypt Package1  | |||
    decrypt_pk11();  | |||
    // Write TSEC root key to SE keyslot 0x0D  | |||
    se_set_keyslot_13();  | |||
    // Write TSEC key to SE keyslot 0x0C  | |||
    se_set_keyslot_12();  | |||
    // Clear the cauth signature  | |||
    csigclr();  | |||
    // Check certain CAR, PMC and FUSE registers  | |||
    test_car_pmc_fuse();  | |||
    // Test memory transfer integrity  | |||
    test_res = test_mem_xfer();  | |||
    if (test_res != 0xAAAAAAAA)  | |||
    {  | |||
        // Fill SE keyslots 12 and 13 with random data  | |||
        se_set_keyslot_rnd();  | |||
        // Clear the entire DMEM region and every crypto register  | |||
        clear_dmem_and_crypto();  | |||
        // Halt 5 times for no good reason  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
    }  | |||
    // Try to detect virtualization using MC_SMMU_AVPC_ASID and FUSE_ECO_RESERVE_0  | |||
    test_smmu_fuse();  | |||
    // Test randomized offsets for read/write integrity in MC, FUSE, IRAM and TZRAM  | |||
    test_res = test_mc_fuse_iram_tzram();  | |||
    if (test_res != 0xAAAAAAAA)  | |||
    {  | |||
        // Fill SE keyslots 12 and 13 with random data  | |||
        se_set_keyslot_rnd();  | |||
        // Clear the entire DMEM region and every crypto register  | |||
        clear_dmem_and_crypto();  | |||
        // Halt 5 times for no good reason  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
    }  | |||
    // Test MC_IRAM_BOM and MC_IRAM_TOM  | |||
    test_res = test_mc_iram_aperture();  | |||
    if (test_res != 0xAAAAAAAA)  | |||
    {  | |||
        // Fill SE keyslots 12 and 13 with random data  | |||
        se_set_keyslot_rnd();  | |||
        // Clear the entire DMEM region and every crypto register  | |||
        clear_dmem_and_crypto();  | |||
        // Halt 5 times for no good reason  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
    }  | |||
    // Test SMMU bypassing in the TFBIF  | |||
    tfbif_smmu_cfg(0x00);  | |||
    // Parse Package1 header and return entry address  | |||
    u32 entry_addr = parse_pk11();  | |||
    // Set the exception vectors  | |||
    set_excp_vec(entry_addr);  | |||
    // Fill the top 0x500 bytes in DMEM with a pointer to trap function (just exits)  | |||
    for (int i = 0; i < 0x500; i += 0x04) {  | |||
        *(u32 *)i = (u32)trap_func();  | |||
    }  | |||
    // Clear all crypto registers  | |||
    cxor($c0, $c0);  | |||
    cxor($c1, $c1);  | |||
    cxor($c2, $c2);  | |||
    cxor($c3, $c3);  | |||
    cxor($c4, $c4);  | |||
    cxor($c5, $c5);  | |||
    cxor($c6, $c6);  | |||
    cxor($c7, $c7);  | |||
    // Take SCP out of lockdown  | |||
    unlock_scp();  | |||
    // Test memory transfer integrity  | |||
    test_res = test_mem_xfer();  | |||
    if (test_res != 0xAAAAAAAA)  | |||
    {  | |||
        // Fill SE keyslots 12 and 13 with random data  | |||
        se_set_keyslot_rnd();  | |||
        // Clear the entire DMEM region and every crypto register  | |||
        clear_dmem_and_crypto();  | |||
        // Halt 5 times for no good reason  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
    }  | |||
    // Try to detect virtualization using MC_SMMU_AVPC_ASID and FUSE_ECO_RESERVE_0  | |||
    test_smmu_fuse();  | |||
    // Test MC_IRAM_BOM and MC_IRAM_TOM  | |||
    test_res = test_mc_iram_aperture();  | |||
    if (test_res != 0xAAAAAAAA)  | |||
    {  | |||
        // Fill SE keyslots 12 and 13 with random data  | |||
        se_set_keyslot_rnd();  | |||
        // Clear the entire DMEM region and every crypto register  | |||
        clear_dmem_and_crypto();  | |||
        // Halt 5 times for no good reason  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
        exit();  | |||
    }  | |||
    // Test SMMU bypassing in the TFBIF  | |||
    tfbif_smmu_cfg(0x00);  | |||
    // Clear FLOW_CTLR_HALT_COP_EVENTS_0  | |||
    resume_bpmp();  | |||
    // Clear the entire DMEM region and every crypto register  | |||
    clear_dmem_and_crypto();  | |||
    // Halt 5 times for no good reason  | |||
    exit();  | |||
    exit();  | |||
    exit();  | |||
    exit();  | |||
    exit();  | |||
    return;  | |||
</pre>  | |||
== Key data ==  | == Key data ==  | ||