mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2025-01-03 11:11:14 +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
|
@ -83,6 +83,8 @@ void bootup_misc_mmio(void) {
|
||||||
MC_SECURITY_CFG3_0 = 3;
|
MC_SECURITY_CFG3_0 = 3;
|
||||||
configure_default_carveouts();
|
configure_default_carveouts();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Mark registers secure world only. */
|
/* Mark registers secure world only. */
|
||||||
/* Mark SATA_AUX, DTV, QSPI, SE, SATA, LA secure only. */
|
/* Mark SATA_AUX, DTV, QSPI, SE, SATA, LA secure only. */
|
||||||
APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 = APB_SSER0_SATA_AUX | APB_SSER0_DTV | APB_SSER0_QSPI | APB_SSER0_SE | APB_SSER0_SATA | APB_SSER0_LA;
|
APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 = APB_SSER0_SATA_AUX | APB_SSER0_DTV | APB_SSER0_QSPI | APB_SSER0_SE | APB_SSER0_SATA | APB_SSER0_LA;
|
||||||
|
@ -111,14 +113,15 @@ void bootup_misc_mmio(void) {
|
||||||
MAKE_MC_REG(0x230) = 0xFFFFFFFF;
|
MAKE_MC_REG(0x230) = 0xFFFFFFFF;
|
||||||
MAKE_MC_REG(0x234) = 0xFFFFFFFF;
|
MAKE_MC_REG(0x234) = 0xFFFFFFFF;
|
||||||
MAKE_MC_REG(0xB98) = 0xFFFFFFFF;
|
MAKE_MC_REG(0xB98) = 0xFFFFFFFF;
|
||||||
MAKE_MC_REG(0x038) = 0;
|
MAKE_MC_REG(0x038) = 0xE;
|
||||||
MAKE_MC_REG(0x03C) = 0;
|
MAKE_MC_REG(0x03C) = 0;
|
||||||
MAKE_MC_REG(0x0E0) = 0;
|
MAKE_MC_REG(0x9E0) = 0;
|
||||||
MAKE_MC_REG(0x0E4) = 0;
|
MAKE_MC_REG(0x9E4) = 0;
|
||||||
MAKE_MC_REG(0x0E8) = 0;
|
MAKE_MC_REG(0x9E8) = 0;
|
||||||
MAKE_MC_REG(0x0EC) = 0;
|
MAKE_MC_REG(0x9EC) = 0;
|
||||||
MAKE_MC_REG(0x0F0) = 0;
|
MAKE_MC_REG(0x9F0) = 0;
|
||||||
MAKE_MC_REG(0x0F4) = 0;
|
MAKE_MC_REG(0x9F4) = 0;
|
||||||
|
MAKE_MC_REG(0x01C) = 0;
|
||||||
MAKE_MC_REG(0x020) = 0;
|
MAKE_MC_REG(0x020) = 0;
|
||||||
MAKE_MC_REG(0x014) = 0x30000030;
|
MAKE_MC_REG(0x014) = 0x30000030;
|
||||||
MAKE_MC_REG(0x018) = 0x2800003F;
|
MAKE_MC_REG(0x018) = 0x2800003F;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
/* TODO: What should this be, for release? */
|
/* TODO: What should this be, for release? */
|
||||||
#define EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG EXOSPHERE_TARGET_FIRMWARE_100
|
#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))
|
#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. */
|
/* Perform some sanity initialization. */
|
||||||
volatile security_engine_t *p_security_engine = get_security_engine();
|
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->_0x4 = 0;
|
||||||
p_security_engine->AES_KEY_READ_DISABLE_REG = 0;
|
p_security_engine->AES_KEY_READ_DISABLE_REG = 0;
|
||||||
p_security_engine->RSA_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. */
|
/* Generate test vector for our keys. */
|
||||||
se_generate_stored_vector();
|
se_generate_stored_vector();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_boot_config(void) {
|
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. */
|
/* 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. */
|
panic(0xF0000001); /* Invalid PK21 signature. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,6 +198,7 @@ static bool validate_package2_metadata(package2_meta_t *metadata) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Package2 size, version number is stored XORed in header CTR. */
|
/* Package2 size, version number is stored XORed in header CTR. */
|
||||||
/* Nintendo, what the fuck? */
|
/* Nintendo, what the fuck? */
|
||||||
uint32_t package_size = metadata->ctr_dwords[0] ^ metadata->ctr_dwords[2] ^ metadata->ctr_dwords[3];
|
uint32_t package_size = metadata->ctr_dwords[0] ^ metadata->ctr_dwords[2] ^ metadata->ctr_dwords[3];
|
||||||
|
@ -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. */
|
/* Validate section hashes. */
|
||||||
if (metadata->section_sizes[section]) {
|
if (metadata->section_sizes[section]) {
|
||||||
void *section_data = (void *)((uint8_t *)NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS + sizeof(package2_header_t) + cur_section_offset);
|
void *section_data = (void *)((uint8_t *)NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS + sizeof(package2_header_t) + cur_section_offset);
|
||||||
uint8_t calculated_hash[0x20];
|
uint8_t calculated_hash[0x20];
|
||||||
flush_dcache_range((uint8_t *)section_data, (uint8_t *)section_data + metadata->section_sizes[section]);
|
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]);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
cur_section_offset += metadata->section_sizes[section];
|
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));
|
memcpy(metadata.ctr, header->metadata.ctr, sizeof(header->metadata.ctr));
|
||||||
/* See if this is the correct key. */
|
/* See if this is the correct key. */
|
||||||
if (validate_package2_metadata(&metadata)) {
|
if (validate_package2_metadata(&metadata)) {
|
||||||
|
se_calculate_sha256(metadata.ctr, &header->metadata, sizeof(package2_meta_t));
|
||||||
header->metadata = metadata;
|
header->metadata = metadata;
|
||||||
return mkey_rev;
|
return mkey_rev;
|
||||||
}
|
}
|
||||||
|
@ -477,8 +486,6 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
|
||||||
indentity_unmap_dram();
|
indentity_unmap_dram();
|
||||||
|
|
||||||
/* Synchronize with NX BOOTLOADER. */
|
/* Synchronize with NX BOOTLOADER. */
|
||||||
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_FINISHED);
|
|
||||||
|
|
||||||
if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) {
|
if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) {
|
||||||
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_FINISHED_4X);
|
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_FINISHED_4X);
|
||||||
setup_4x_mmio();
|
setup_4x_mmio();
|
||||||
|
@ -491,4 +498,6 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
|
||||||
|
|
||||||
/* Update SCR_EL3 depending on value in Bootconfig. */
|
/* 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -453,6 +453,8 @@ 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(&in_ll, (void *)src, src_size);
|
||||||
ll_init(&out_ll, dst, dst_size);
|
ll_init(&out_ll, dst, dst_size);
|
||||||
|
|
||||||
|
__dsb_sy();
|
||||||
|
|
||||||
/* Set the LLs. */
|
/* Set the LLs. */
|
||||||
SECURITY_ENGINE->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll);
|
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);
|
SECURITY_ENGINE->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll);
|
||||||
|
@ -463,6 +465,7 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v
|
||||||
SECURITY_ENGINE->OPERATION_REG = op;
|
SECURITY_ENGINE->OPERATION_REG = op;
|
||||||
|
|
||||||
while (!(SECURITY_ENGINE->INT_STATUS_REG & 0x10)) { /* Wait a while */ }
|
while (!(SECURITY_ENGINE->INT_STATUS_REG & 0x10)) { /* Wait a while */ }
|
||||||
|
|
||||||
se_check_for_error();
|
se_check_for_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,13 +662,13 @@ 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->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
|
||||||
SECURITY_ENGINE->SHA_CONFIG_REG = 1;
|
SECURITY_ENGINE->SHA_CONFIG_REG = 1;
|
||||||
SECURITY_ENGINE->SHA_MSG_LENGTH_REG = (unsigned int)(src_size << 3);
|
SECURITY_ENGINE->SHA_MSG_LENGTH_REG = (unsigned int)(src_size << 3);
|
||||||
|
SECURITY_ENGINE->_0x208 = 0;
|
||||||
SECURITY_ENGINE->_0x20C = 0;
|
SECURITY_ENGINE->_0x20C = 0;
|
||||||
SECURITY_ENGINE->_0x210 = 0;
|
SECURITY_ENGINE->_0x210 = 0;
|
||||||
SECURITY_ENGINE->SHA_MSG_LEFT_REG = 0;
|
SECURITY_ENGINE->SHA_MSG_LEFT_REG = (unsigned int)(src_size << 3);
|
||||||
SECURITY_ENGINE->_0x218 = (unsigned int)(src_size << 3);
|
SECURITY_ENGINE->_0x218 = 0;
|
||||||
SECURITY_ENGINE->_0x21C = 0;
|
SECURITY_ENGINE->_0x21C = 0;
|
||||||
SECURITY_ENGINE->_0x220 = 0;
|
SECURITY_ENGINE->_0x220 = 0;
|
||||||
SECURITY_ENGINE->_0x224 = 0;
|
|
||||||
|
|
||||||
/* Trigger the operation. */
|
/* Trigger the operation. */
|
||||||
trigger_se_blocking_op(OP_START, NULL, 0, src, src_size);
|
trigger_se_blocking_op(OP_START, NULL, 0, src, src_size);
|
||||||
|
|
|
@ -100,6 +100,7 @@ typedef struct security_engine {
|
||||||
unsigned char _0x74[0x18C];
|
unsigned char _0x74[0x18C];
|
||||||
unsigned int SHA_CONFIG_REG;
|
unsigned int SHA_CONFIG_REG;
|
||||||
unsigned int SHA_MSG_LENGTH_REG;
|
unsigned int SHA_MSG_LENGTH_REG;
|
||||||
|
unsigned int _0x208;
|
||||||
unsigned int _0x20C;
|
unsigned int _0x20C;
|
||||||
unsigned int _0x210;
|
unsigned int _0x210;
|
||||||
unsigned int SHA_MSG_LEFT_REG;
|
unsigned int SHA_MSG_LEFT_REG;
|
||||||
|
@ -110,7 +111,7 @@ typedef struct security_engine {
|
||||||
unsigned char _0x228[0x5C];
|
unsigned char _0x228[0x5C];
|
||||||
unsigned int AES_KEY_READ_DISABLE_REG;
|
unsigned int AES_KEY_READ_DISABLE_REG;
|
||||||
unsigned int AES_KEYSLOT_FLAGS[0x10];
|
unsigned int AES_KEYSLOT_FLAGS[0x10];
|
||||||
unsigned char _0x2C4[0x3C];
|
unsigned char _0x2C8[0x38];
|
||||||
unsigned int _0x300;
|
unsigned int _0x300;
|
||||||
unsigned int CRYPTO_REG;
|
unsigned int CRYPTO_REG;
|
||||||
unsigned int CRYPTO_CTR_REG[4];
|
unsigned int CRYPTO_CTR_REG[4];
|
||||||
|
|
|
@ -201,7 +201,7 @@ __jump_to_main_cold:
|
||||||
bl get_pk2ldr_stack_address
|
bl get_pk2ldr_stack_address
|
||||||
mov sp, x0
|
mov sp, x0
|
||||||
|
|
||||||
mov x0, x19
|
mov x0, x20
|
||||||
bl load_package2
|
bl load_package2
|
||||||
|
|
||||||
mov w0, #3 /* use core3 stack temporarily */
|
mov w0, #3 /* use core3 stack temporarily */
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
#include "fuse.h"
|
#include "fuse.h"
|
||||||
|
@ -12,10 +13,13 @@ __attribute__ ((noreturn)) void panic(uint32_t code) {
|
||||||
APBDEV_PMC_SCRATCH200_0 = 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. */
|
/* TODO: Custom Panic Driver, which displays to screen without rebooting. */
|
||||||
/* For now, just use NX BOOTLOADER's panic. */
|
/* For now, just use NX BOOTLOADER's panic. */
|
||||||
fuse_disable_programming();
|
fuse_disable_programming();
|
||||||
APBDEV_PMC_CRYPTO_OP_0 = 1; /* Disable all SE operations. */
|
APBDEV_PMC_CRYPTO_OP_0 = 1; /* Disable all SE operations. */
|
||||||
|
while (1) { }
|
||||||
watchdog_reboot();
|
watchdog_reboot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue