mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-27 04:36:04 +00:00
Exosphere: Fix extremely spooky Security Engine bugs, now makes it to the end of package2loader.
This commit is contained in:
parent
ac7ee45493
commit
366cc5e189
7 changed files with 45 additions and 24 deletions
|
@ -33,7 +33,7 @@ static bool g_has_booted_up = false;
|
|||
void bootup_misc_mmio(void) {
|
||||
/* Initialize Fuse registers. */
|
||||
fuse_init();
|
||||
|
||||
|
||||
/* Verify Security Engine sanity. */
|
||||
se_set_in_context_save_mode(false);
|
||||
/* TODO: se_verify_keys_unreadable(); */
|
||||
|
@ -82,6 +82,8 @@ void bootup_misc_mmio(void) {
|
|||
MC_SECURITY_CFG1_0 = 0;
|
||||
MC_SECURITY_CFG3_0 = 3;
|
||||
configure_default_carveouts();
|
||||
|
||||
|
||||
|
||||
/* Mark registers secure world only. */
|
||||
/* Mark SATA_AUX, DTV, QSPI, SE, SATA, LA secure only. */
|
||||
|
@ -111,14 +113,15 @@ void bootup_misc_mmio(void) {
|
|||
MAKE_MC_REG(0x230) = 0xFFFFFFFF;
|
||||
MAKE_MC_REG(0x234) = 0xFFFFFFFF;
|
||||
MAKE_MC_REG(0xB98) = 0xFFFFFFFF;
|
||||
MAKE_MC_REG(0x038) = 0;
|
||||
MAKE_MC_REG(0x038) = 0xE;
|
||||
MAKE_MC_REG(0x03C) = 0;
|
||||
MAKE_MC_REG(0x0E0) = 0;
|
||||
MAKE_MC_REG(0x0E4) = 0;
|
||||
MAKE_MC_REG(0x0E8) = 0;
|
||||
MAKE_MC_REG(0x0EC) = 0;
|
||||
MAKE_MC_REG(0x0F0) = 0;
|
||||
MAKE_MC_REG(0x0F4) = 0;
|
||||
MAKE_MC_REG(0x9E0) = 0;
|
||||
MAKE_MC_REG(0x9E4) = 0;
|
||||
MAKE_MC_REG(0x9E8) = 0;
|
||||
MAKE_MC_REG(0x9EC) = 0;
|
||||
MAKE_MC_REG(0x9F0) = 0;
|
||||
MAKE_MC_REG(0x9F4) = 0;
|
||||
MAKE_MC_REG(0x01C) = 0;
|
||||
MAKE_MC_REG(0x020) = 0;
|
||||
MAKE_MC_REG(0x014) = 0x30000030;
|
||||
MAKE_MC_REG(0x018) = 0x2800003F;
|
||||
|
@ -129,7 +132,7 @@ void bootup_misc_mmio(void) {
|
|||
(void)(MAKE_MC_REG(0x014));
|
||||
MAKE_MC_REG(0x010) = 1;
|
||||
(void)(MAKE_MC_REG(0x014));
|
||||
|
||||
|
||||
/* Clear RESET Vector, setup CPU Secure Boot RESET Vectors. */
|
||||
uint32_t reset_vec = TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN);
|
||||
EVP_CPU_RESET_VECTOR_0 = 0;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
/* TODO: What should this be, for release? */
|
||||
#define EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG EXOSPHERE_TARGET_FIRMWARE_100
|
||||
#define EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG 1
|
||||
|
||||
#define MAILBOX_BASE_PHYS (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX))
|
||||
|
||||
|
|
|
@ -58,6 +58,10 @@ static void setup_se(void) {
|
|||
|
||||
/* Perform some sanity initialization. */
|
||||
volatile security_engine_t *p_security_engine = get_security_engine();
|
||||
p_security_engine->_0x0 &= 0xFFFEFFFF; /* Clear bit 16. */
|
||||
(void)(SECURITY_ENGINE->FLAGS_REG);
|
||||
__dsb_sy();
|
||||
|
||||
p_security_engine->_0x4 = 0;
|
||||
p_security_engine->AES_KEY_READ_DISABLE_REG = 0;
|
||||
p_security_engine->RSA_KEY_READ_DISABLE_REG = 0;
|
||||
|
@ -107,6 +111,7 @@ static void setup_se(void) {
|
|||
|
||||
/* Generate test vector for our keys. */
|
||||
se_generate_stored_vector();
|
||||
|
||||
}
|
||||
|
||||
static void setup_boot_config(void) {
|
||||
|
@ -178,7 +183,8 @@ static void verify_header_signature(package2_header_t *header) {
|
|||
}
|
||||
|
||||
/* This is normally only allowed on dev units, but we'll allow it anywhere. */
|
||||
if (bootconfig_is_package2_unsigned() == 0 && se_rsa2048_pss_verify(header->signature, 0x100, modulus, 0x100, header->encrypted_header, 0x100) == 0) {
|
||||
bool is_unsigned = EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG || bootconfig_is_package2_unsigned();
|
||||
if (!is_unsigned && se_rsa2048_pss_verify(header->signature, 0x100, modulus, 0x100, header->encrypted_header, 0x100) == 0) {
|
||||
panic(0xF0000001); /* Invalid PK21 signature. */
|
||||
}
|
||||
}
|
||||
|
@ -191,6 +197,7 @@ static bool validate_package2_metadata(package2_meta_t *metadata) {
|
|||
if (metadata->magic != MAGIC_PK21) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Package2 size, version number is stored XORed in header CTR. */
|
||||
/* Nintendo, what the fuck? */
|
||||
|
@ -246,13 +253,14 @@ static bool validate_package2_metadata(package2_meta_t *metadata) {
|
|||
}
|
||||
}
|
||||
|
||||
bool check_hash = EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG == 0;
|
||||
/* Validate section hashes. */
|
||||
if (metadata->section_sizes[section]) {
|
||||
void *section_data = (void *)((uint8_t *)NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS + sizeof(package2_header_t) + cur_section_offset);
|
||||
uint8_t calculated_hash[0x20];
|
||||
flush_dcache_range((uint8_t *)section_data, (uint8_t *)section_data + metadata->section_sizes[section]);
|
||||
se_calculate_sha256(calculated_hash, section_data, metadata->section_sizes[section]);
|
||||
if (memcmp(calculated_hash, metadata->section_hashes[section], sizeof(metadata->section_hashes[section])) != 0) {
|
||||
if (check_hash && memcmp(calculated_hash, metadata->section_hashes[section], sizeof(metadata->section_hashes[section])) != 0) {
|
||||
return false;
|
||||
}
|
||||
cur_section_offset += metadata->section_sizes[section];
|
||||
|
@ -288,6 +296,7 @@ static uint32_t decrypt_and_validate_header(package2_header_t *header) {
|
|||
memcpy(metadata.ctr, header->metadata.ctr, sizeof(header->metadata.ctr));
|
||||
/* See if this is the correct key. */
|
||||
if (validate_package2_metadata(&metadata)) {
|
||||
se_calculate_sha256(metadata.ctr, &header->metadata, sizeof(package2_meta_t));
|
||||
header->metadata = metadata;
|
||||
return mkey_rev;
|
||||
}
|
||||
|
@ -446,7 +455,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
|
|||
flush_dcache_range((uint8_t *)NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS, (uint8_t *)NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS + sizeof(header));
|
||||
memcpy(&header, NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS, sizeof(header));
|
||||
flush_dcache_range((uint8_t *)&header, (uint8_t *)&header + sizeof(header));
|
||||
|
||||
|
||||
/* Perform signature checks. */
|
||||
/* Special exosphere patching enable: All-zeroes signature + decrypted header implies unsigned and decrypted package2. */
|
||||
if (header.signature[0] == 0 && memcmp(header.signature, header.signature + 1, sizeof(header.signature) - 1) == 0 && header.metadata.magic == MAGIC_PK21) {
|
||||
|
@ -457,7 +466,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
|
|||
|
||||
/* Decrypt header, get key revision required. */
|
||||
uint32_t package2_mkey_rev = decrypt_and_validate_header(&header);
|
||||
|
||||
|
||||
/* Copy hash, if necessary. */
|
||||
if (bootconfig_is_recovery_boot()) {
|
||||
bootconfig_set_package2_hash_for_recovery(NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS, get_package2_size(&header.metadata));
|
||||
|
@ -477,8 +486,6 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
|
|||
indentity_unmap_dram();
|
||||
|
||||
/* Synchronize with NX BOOTLOADER. */
|
||||
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_FINISHED);
|
||||
|
||||
if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) {
|
||||
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_FINISHED_4X);
|
||||
setup_4x_mmio();
|
||||
|
@ -490,5 +497,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
|
|||
set_version_specific_smcs();
|
||||
|
||||
/* Update SCR_EL3 depending on value in Bootconfig. */
|
||||
set_extabt_serror_taken_to_el3(bootconfig_take_extabt_serror_to_el3());
|
||||
set_extabt_serror_taken_to_el3(bootconfig_take_extabt_serror_to_el3());
|
||||
strcpy((void *)MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM), (void *)"PK2LOADED");
|
||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ void ll_init(se_ll_t *ll, void *buffer, size_t size) {
|
|||
ll->addr_info.address = 0;
|
||||
ll->addr_info.size = 0;
|
||||
}
|
||||
|
||||
|
||||
flush_dcache_range((uint8_t *)ll, (uint8_t *)ll + sizeof(*ll));
|
||||
}
|
||||
|
||||
|
@ -452,17 +452,20 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v
|
|||
|
||||
ll_init(&in_ll, (void *)src, src_size);
|
||||
ll_init(&out_ll, dst, dst_size);
|
||||
|
||||
__dsb_sy();
|
||||
|
||||
/* Set the LLs. */
|
||||
SECURITY_ENGINE->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll);
|
||||
SECURITY_ENGINE->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll);
|
||||
|
||||
|
||||
/* Set registers for operation. */
|
||||
SECURITY_ENGINE->ERR_STATUS_REG = SECURITY_ENGINE->ERR_STATUS_REG;
|
||||
SECURITY_ENGINE->INT_STATUS_REG = SECURITY_ENGINE->INT_STATUS_REG;
|
||||
SECURITY_ENGINE->OPERATION_REG = op;
|
||||
|
||||
while (!(SECURITY_ENGINE->INT_STATUS_REG & 0x10)) { /* Wait a while */ }
|
||||
|
||||
se_check_for_error();
|
||||
}
|
||||
|
||||
|
@ -659,14 +662,14 @@ void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
|
|||
SECURITY_ENGINE->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
|
||||
SECURITY_ENGINE->SHA_CONFIG_REG = 1;
|
||||
SECURITY_ENGINE->SHA_MSG_LENGTH_REG = (unsigned int)(src_size << 3);
|
||||
SECURITY_ENGINE->_0x208 = 0;
|
||||
SECURITY_ENGINE->_0x20C = 0;
|
||||
SECURITY_ENGINE->_0x210 = 0;
|
||||
SECURITY_ENGINE->SHA_MSG_LEFT_REG = 0;
|
||||
SECURITY_ENGINE->_0x218 = (unsigned int)(src_size << 3);
|
||||
SECURITY_ENGINE->SHA_MSG_LEFT_REG = (unsigned int)(src_size << 3);
|
||||
SECURITY_ENGINE->_0x218 = 0;
|
||||
SECURITY_ENGINE->_0x21C = 0;
|
||||
SECURITY_ENGINE->_0x220 = 0;
|
||||
SECURITY_ENGINE->_0x224 = 0;
|
||||
|
||||
|
||||
/* Trigger the operation. */
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, src, src_size);
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ typedef struct security_engine {
|
|||
unsigned char _0x74[0x18C];
|
||||
unsigned int SHA_CONFIG_REG;
|
||||
unsigned int SHA_MSG_LENGTH_REG;
|
||||
unsigned int _0x208;
|
||||
unsigned int _0x20C;
|
||||
unsigned int _0x210;
|
||||
unsigned int SHA_MSG_LEFT_REG;
|
||||
|
@ -110,7 +111,7 @@ typedef struct security_engine {
|
|||
unsigned char _0x228[0x5C];
|
||||
unsigned int AES_KEY_READ_DISABLE_REG;
|
||||
unsigned int AES_KEYSLOT_FLAGS[0x10];
|
||||
unsigned char _0x2C4[0x3C];
|
||||
unsigned char _0x2C8[0x38];
|
||||
unsigned int _0x300;
|
||||
unsigned int CRYPTO_REG;
|
||||
unsigned int CRYPTO_CTR_REG[4];
|
||||
|
|
|
@ -201,7 +201,7 @@ __jump_to_main_cold:
|
|||
bl get_pk2ldr_stack_address
|
||||
mov sp, x0
|
||||
|
||||
mov x0, x19
|
||||
mov x0, x20
|
||||
bl load_package2
|
||||
|
||||
mov w0, #3 /* use core3 stack temporarily */
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "utils.h"
|
||||
#include "se.h"
|
||||
#include "fuse.h"
|
||||
|
@ -12,10 +13,13 @@ __attribute__ ((noreturn)) void panic(uint32_t code) {
|
|||
APBDEV_PMC_SCRATCH200_0 = code;
|
||||
}
|
||||
|
||||
strcpy((void *)MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM), (void *)"PANIC");
|
||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10;
|
||||
/* TODO: Custom Panic Driver, which displays to screen without rebooting. */
|
||||
/* For now, just use NX BOOTLOADER's panic. */
|
||||
fuse_disable_programming();
|
||||
APBDEV_PMC_CRYPTO_OP_0 = 1; /* Disable all SE operations. */
|
||||
while (1) { }
|
||||
watchdog_reboot();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue