mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-06 04:01:44 +00:00
sept-secondary: reboot to clean state + grab keys from SE
This commit is contained in:
parent
f58f7c8a16
commit
c56561b234
10 changed files with 272 additions and 23 deletions
|
@ -148,6 +148,7 @@ SECTIONS
|
||||||
. = ALIGN(32);
|
. = ALIGN(32);
|
||||||
PROVIDE (__bss_end__ = ABSOLUTE(.));
|
PROVIDE (__bss_end__ = ABSOLUTE(.));
|
||||||
} >main :NONE
|
} >main :NONE
|
||||||
|
. = ALIGN(32);
|
||||||
__end__ = ABSOLUTE(.) ;
|
__end__ = ABSOLUTE(.) ;
|
||||||
|
|
||||||
/* ==================
|
/* ==================
|
||||||
|
|
|
@ -53,7 +53,8 @@ def main(argc, argv):
|
||||||
return 1
|
return 1
|
||||||
with open(argv[1], 'rb') as f:
|
with open(argv[1], 'rb') as f:
|
||||||
code = f.read()
|
code = f.read()
|
||||||
assert (len(code) & 0xF) == 0
|
if len(code) & 0xF:
|
||||||
|
code += '\x00'*(0x10 - (len(code) & 0xF))
|
||||||
# TODO: Support dev unit crypto
|
# TODO: Support dev unit crypto
|
||||||
with open(argv[2], 'wb') as f:
|
with open(argv[2], 'wb') as f:
|
||||||
f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.IV, 'THANKS_NVIDIA_<3'))
|
f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.IV, 'THANKS_NVIDIA_<3'))
|
||||||
|
|
|
@ -111,7 +111,7 @@ void display_init()
|
||||||
|
|
||||||
exec_cfg((uint32_t *)CAR_BASE, _display_config_1, 4);
|
exec_cfg((uint32_t *)CAR_BASE, _display_config_1, 4);
|
||||||
exec_cfg((uint32_t *)DI_BASE, _display_config_2, 94);
|
exec_cfg((uint32_t *)DI_BASE, _display_config_2, 94);
|
||||||
exec_cfg((uint32_t *)DSI_BASE, _display_config_3, 60);
|
exec_cfg((uint32_t *)DSI_BASE, _display_config_3, 61);
|
||||||
|
|
||||||
udelay(10000);
|
udelay(10000);
|
||||||
|
|
||||||
|
@ -149,8 +149,8 @@ void display_init()
|
||||||
|
|
||||||
udelay(20000);
|
udelay(20000);
|
||||||
|
|
||||||
exec_cfg((uint32_t *)DSI_BASE, _display_config_5, 21);
|
|
||||||
exec_cfg((uint32_t *)CAR_BASE, _display_config_6, 3);
|
exec_cfg((uint32_t *)CAR_BASE, _display_config_6, 3);
|
||||||
|
exec_cfg((uint32_t *)DSI_BASE, _display_config_5, 21);
|
||||||
|
|
||||||
MAKE_DI_REG(DC_DISP_DISP_CLOCK_CONTROL) = 4;
|
MAKE_DI_REG(DC_DISP_DISP_CLOCK_CONTROL) = 4;
|
||||||
exec_cfg((uint32_t *)DSI_BASE, _display_config_7, 10);
|
exec_cfg((uint32_t *)DSI_BASE, _display_config_7, 10);
|
||||||
|
|
|
@ -190,6 +190,7 @@
|
||||||
#define DC_WIN_WIN_OPTIONS 0x700
|
#define DC_WIN_WIN_OPTIONS 0x700
|
||||||
#define H_DIRECTION (1 << 0)
|
#define H_DIRECTION (1 << 0)
|
||||||
#define V_DIRECTION (1 << 2)
|
#define V_DIRECTION (1 << 2)
|
||||||
|
#define SCAN_COLUMN (1 << 4)
|
||||||
#define COLOR_EXPAND (1 << 6)
|
#define COLOR_EXPAND (1 << 6)
|
||||||
#define CSC_ENABLE (1 << 18)
|
#define CSC_ENABLE (1 << 18)
|
||||||
#define WIN_ENABLE (1 << 30)
|
#define WIN_ENABLE (1 << 30)
|
||||||
|
@ -237,6 +238,8 @@
|
||||||
#define V_DDA_INC(x) (((x) & 0xffff) << 16)
|
#define V_DDA_INC(x) (((x) & 0xffff) << 16)
|
||||||
|
|
||||||
#define DC_WIN_LINE_STRIDE 0x70A
|
#define DC_WIN_LINE_STRIDE 0x70A
|
||||||
|
#define LINE_STRIDE(x) (x)
|
||||||
|
#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16)
|
||||||
#define DC_WIN_DV_CONTROL 0x70E
|
#define DC_WIN_DV_CONTROL 0x70E
|
||||||
|
|
||||||
/* The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */
|
/* The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */
|
||||||
|
@ -347,6 +350,8 @@
|
||||||
|
|
||||||
#define DSI_PAD_CONTROL_4 0x52
|
#define DSI_PAD_CONTROL_4 0x52
|
||||||
|
|
||||||
|
#define DSI_INIT_SEQ_DATA_15 0x5F
|
||||||
|
|
||||||
typedef struct _cfg_op_t
|
typedef struct _cfg_op_t
|
||||||
{
|
{
|
||||||
uint32_t off;
|
uint32_t off;
|
||||||
|
|
|
@ -128,7 +128,7 @@ static const cfg_op_t _display_config_2[94] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
//DSI Init config.
|
//DSI Init config.
|
||||||
static const cfg_op_t _display_config_3[60] = {
|
static const cfg_op_t _display_config_3[61] = {
|
||||||
{DSI_WR_DATA, 0},
|
{DSI_WR_DATA, 0},
|
||||||
{DSI_INT_ENABLE, 0},
|
{DSI_INT_ENABLE, 0},
|
||||||
{DSI_INT_STATUS, 0},
|
{DSI_INT_STATUS, 0},
|
||||||
|
@ -137,6 +137,7 @@ static const cfg_op_t _display_config_3[60] = {
|
||||||
{DSI_INIT_SEQ_DATA_1, 0},
|
{DSI_INIT_SEQ_DATA_1, 0},
|
||||||
{DSI_INIT_SEQ_DATA_2, 0},
|
{DSI_INIT_SEQ_DATA_2, 0},
|
||||||
{DSI_INIT_SEQ_DATA_3, 0},
|
{DSI_INIT_SEQ_DATA_3, 0},
|
||||||
|
{DSI_INIT_SEQ_DATA_15, 0},
|
||||||
{DSI_DCS_CMDS, 0},
|
{DSI_DCS_CMDS, 0},
|
||||||
{DSI_PKT_SEQ_0_LO, 0},
|
{DSI_PKT_SEQ_0_LO, 0},
|
||||||
{DSI_PKT_SEQ_1_LO, 0},
|
{DSI_PKT_SEQ_1_LO, 0},
|
||||||
|
@ -288,7 +289,7 @@ static const cfg_op_t _display_config_7[10] = {
|
||||||
static const cfg_op_t _display_config_8[6] = {
|
static const cfg_op_t _display_config_8[6] = {
|
||||||
{0x18, 0},
|
{0x18, 0},
|
||||||
{2, 0xF3F10000},
|
{2, 0xF3F10000},
|
||||||
{0x16, 1},
|
{0x16, 0},
|
||||||
{0x18, 0},
|
{0x18, 0},
|
||||||
{0x18, 0x10010},
|
{0x18, 0x10010},
|
||||||
{0x17, 0x300}
|
{0x17, 0x300}
|
||||||
|
@ -474,10 +475,10 @@ static const cfg_op_t _display_config_13[16] = {
|
||||||
{DSI_PAD_CONTROL_1, 0},
|
{DSI_PAD_CONTROL_1, 0},
|
||||||
{DSI_PHY_TIMING_0, 0x6070601},
|
{DSI_PHY_TIMING_0, 0x6070601},
|
||||||
{DSI_PHY_TIMING_1, 0x40A0E05},
|
{DSI_PHY_TIMING_1, 0x40A0E05},
|
||||||
{DSI_PHY_TIMING_2, 0x30109},
|
{DSI_PHY_TIMING_2, 0x30118},
|
||||||
{DSI_BTA_TIMING, 0x190A14},
|
{DSI_BTA_TIMING, 0x190A14},
|
||||||
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) },
|
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) },
|
||||||
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)},
|
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
|
||||||
{DSI_TO_TALLY, 0},
|
{DSI_TO_TALLY, 0},
|
||||||
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
|
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
|
||||||
{DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
|
{DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
|
||||||
|
|
|
@ -186,9 +186,9 @@ void config_se_brom()
|
||||||
void nx_hwinit()
|
void nx_hwinit()
|
||||||
{
|
{
|
||||||
volatile tegra_car_t *car = car_get_regs();
|
volatile tegra_car_t *car = car_get_regs();
|
||||||
|
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||||
|
|
||||||
/* This stuff was handled by whatever loaded us. */
|
/* This stuff was handled by whatever loaded us. */
|
||||||
/*
|
|
||||||
config_se_brom();
|
config_se_brom();
|
||||||
|
|
||||||
AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F;
|
AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F;
|
||||||
|
@ -202,9 +202,6 @@ void nx_hwinit()
|
||||||
|
|
||||||
mc_enable();
|
mc_enable();
|
||||||
|
|
||||||
config_oscillators();
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Disable pinmux tristate input clamping. */
|
/* Disable pinmux tristate input clamping. */
|
||||||
APB_MISC_PP_PINMUX_GLOBAL_0 = 0;
|
APB_MISC_PP_PINMUX_GLOBAL_0 = 0;
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include "hwinit.h"
|
#include "hwinit.h"
|
||||||
#include "di.h"
|
#include "di.h"
|
||||||
|
#include "se.h"
|
||||||
|
#include "pmc.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
#include "fs_utils.h"
|
#include "fs_utils.h"
|
||||||
#include "stage2.h"
|
#include "stage2.h"
|
||||||
|
@ -34,6 +36,82 @@ extern void (*__program_exit_callback)(int rc);
|
||||||
|
|
||||||
static void *g_framebuffer;
|
static void *g_framebuffer;
|
||||||
|
|
||||||
|
static uint32_t g_tsec_root_key[0x4] = {0};
|
||||||
|
static uint32_t g_tsec_key[0x4] = {0};
|
||||||
|
|
||||||
|
static bool has_rebooted(void) {
|
||||||
|
return MAKE_REG32(0x4003FFFC) == 0xFAFAFAFA;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_has_rebooted(bool rebooted) {
|
||||||
|
MAKE_REG32(0x4003FFFC) = rebooted ? 0xFAFAFAFA : 0x00000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void exfiltrate_keys_and_reboot_if_needed(void) {
|
||||||
|
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||||
|
uint8_t *enc_se_state = (uint8_t *)0x4003E000;
|
||||||
|
uint8_t *dec_se_state = (uint8_t *)0x4003F000;
|
||||||
|
|
||||||
|
if (!has_rebooted()) {
|
||||||
|
|
||||||
|
|
||||||
|
/* Save the security engine context. */
|
||||||
|
se_get_regs()->_0x4 = 0x0;
|
||||||
|
se_set_in_context_save_mode(true);
|
||||||
|
se_save_context(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY, enc_se_state);
|
||||||
|
se_set_in_context_save_mode(false);
|
||||||
|
|
||||||
|
/* Decrypt the security engine context. */
|
||||||
|
|
||||||
|
/* Copy TSEC key from SOR1 registers. */
|
||||||
|
MAKE_REG32(0x4003FFC0) = pmc->secure_scratch4;
|
||||||
|
MAKE_REG32(0x4003FFC4) = pmc->secure_scratch5;
|
||||||
|
MAKE_REG32(0x4003FFC8) = pmc->secure_scratch6;
|
||||||
|
MAKE_REG32(0x4003FFCC) = pmc->secure_scratch7;
|
||||||
|
|
||||||
|
/* TODO: Master kek */
|
||||||
|
MAKE_REG32(0x4003FFD0) = 0;
|
||||||
|
MAKE_REG32(0x4003FFD4) = 0;
|
||||||
|
MAKE_REG32(0x4003FFD8) = 0;
|
||||||
|
MAKE_REG32(0x4003FFDC) = 0;
|
||||||
|
|
||||||
|
set_has_rebooted(true);
|
||||||
|
reboot_to_self();
|
||||||
|
} else {
|
||||||
|
/* Decrypt the security engine state. */
|
||||||
|
uint32_t ALIGN(16) context_key[4];
|
||||||
|
context_key[0] = pmc->secure_scratch4;
|
||||||
|
context_key[1] = pmc->secure_scratch5;
|
||||||
|
context_key[2] = pmc->secure_scratch6;
|
||||||
|
context_key[3] = pmc->secure_scratch7;
|
||||||
|
set_aes_keyslot(0xC, context_key, sizeof(context_key));
|
||||||
|
se_aes_128_cbc_decrypt(0xC, dec_se_state, 0x840, enc_se_state, 0x840);
|
||||||
|
|
||||||
|
/* Copy out tsec key + tsec root key. */
|
||||||
|
for (size_t i = 0; i < 0x10; i += 4) {
|
||||||
|
g_tsec_key[i/4] = MAKE_REG32((uintptr_t)(dec_se_state) + 0x1B0 + i);
|
||||||
|
g_tsec_root_key[i/4] = MAKE_REG32((uintptr_t)(dec_se_state) + 0x1D0 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the security engine state. */
|
||||||
|
for (size_t i = 0; i < 0x1000; i += 4) {
|
||||||
|
MAKE_REG32((uintptr_t)(enc_se_state) + i) = 0xCCCCCCCC;
|
||||||
|
MAKE_REG32((uintptr_t)(dec_se_state) + i) = 0xCCCCCCCC;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < 4; i++) {
|
||||||
|
context_key[i] = 0xCCCCCCCC;
|
||||||
|
}
|
||||||
|
pmc->secure_scratch4 = 0xCCCCCCCC;
|
||||||
|
pmc->secure_scratch5 = 0xCCCCCCCC;
|
||||||
|
pmc->secure_scratch6 = 0xCCCCCCCC;
|
||||||
|
pmc->secure_scratch7 = 0xCCCCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void setup_env(void) {
|
static void setup_env(void) {
|
||||||
g_framebuffer = (void *)0xC0000000;
|
g_framebuffer = (void *)0xC0000000;
|
||||||
|
|
||||||
|
@ -79,6 +157,9 @@ static void exit_callback(int rc) {
|
||||||
int main(void) {
|
int main(void) {
|
||||||
ScreenLogLevel log_level = SCREEN_LOG_LEVEL_MANDATORY;
|
ScreenLogLevel log_level = SCREEN_LOG_LEVEL_MANDATORY;
|
||||||
|
|
||||||
|
/* Extract keys from the security engine, which TSEC FW locked down. */
|
||||||
|
exfiltrate_keys_and_reboot_if_needed();
|
||||||
|
|
||||||
/* Override the global logging level. */
|
/* Override the global logging level. */
|
||||||
log_set_log_level(log_level);
|
log_set_log_level(log_level);
|
||||||
|
|
||||||
|
|
|
@ -580,6 +580,20 @@ void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, co
|
||||||
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
|
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void se_aes_128_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||||
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
|
if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) {
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY) | (0x000 << 16);
|
||||||
|
se->CRYPTO_REG = (keyslot << 24) | 0x66;
|
||||||
|
clear_aes_keyslot_iv(keyslot);
|
||||||
|
se->BLOCK_COUNT_REG = (src_size >> 4) - 1;
|
||||||
|
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
|
||||||
|
}
|
||||||
|
|
||||||
/* SHA256 Implementation. */
|
/* SHA256 Implementation. */
|
||||||
void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
|
void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
@ -647,3 +661,140 @@ void se_generate_random(unsigned int keyslot, void *dst, size_t size) {
|
||||||
se_perform_aes_block_operation(dst + aligned_size, size - aligned_size, NULL, 0);
|
se_perform_aes_block_operation(dst + aligned_size, size - aligned_size, NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot) {
|
||||||
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
|
if (dst_keyslot >= KEYSLOT_AES_MAX || rng_keyslot >= KEYSLOT_AES_MAX) {
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup Config. */
|
||||||
|
se->CONFIG_REG = (ALG_RNG | DST_KEYTAB);
|
||||||
|
se->CRYPTO_REG = (rng_keyslot << 24) | 0x108;
|
||||||
|
se->RNG_CONFIG_REG = 4;
|
||||||
|
se->BLOCK_COUNT_REG = 0;
|
||||||
|
|
||||||
|
/* Generate low part of key. */
|
||||||
|
se->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8);
|
||||||
|
trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0);
|
||||||
|
/* Generate high part of key. */
|
||||||
|
se->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8) | 1;
|
||||||
|
trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SE context save API. */
|
||||||
|
void se_set_in_context_save_mode(bool is_context_save_mode) {
|
||||||
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
|
uint32_t val = se->_0x0;
|
||||||
|
if (is_context_save_mode) {
|
||||||
|
val |= 0x10000;
|
||||||
|
} else {
|
||||||
|
val &= 0xFFFEFFFF;
|
||||||
|
}
|
||||||
|
se->_0x0 = val;
|
||||||
|
/* Perform a useless read from flags reg. */
|
||||||
|
(void)(se->FLAGS_REG);
|
||||||
|
}
|
||||||
|
|
||||||
|
void se_generate_srk(unsigned int srkgen_keyslot) {
|
||||||
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
|
se->CONFIG_REG = (ALG_RNG | DST_SRK);
|
||||||
|
se->CRYPTO_REG = (srkgen_keyslot << 24) | 0x108;
|
||||||
|
se->RNG_CONFIG_REG = 6;
|
||||||
|
se->BLOCK_COUNT_REG = 0;
|
||||||
|
trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void se_encrypt_with_srk(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||||
|
uint8_t output[0x80];
|
||||||
|
uint8_t *aligned_out = (uint8_t *)(((uintptr_t)output + 0x7F) & ~0x3F);
|
||||||
|
if (dst_size > 0x10) {
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst_size) {
|
||||||
|
trigger_se_blocking_op(OP_CTX_SAVE, aligned_out, dst_size, src, src_size);
|
||||||
|
memcpy(dst, aligned_out, dst_size);
|
||||||
|
} else {
|
||||||
|
trigger_se_blocking_op(OP_CTX_SAVE, aligned_out, 0, src, src_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void *dst) {
|
||||||
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
uint8_t _work_buf[0x80];
|
||||||
|
uint8_t *work_buf = (uint8_t *)(((uintptr_t)_work_buf + 0x7F) & ~0x3F);
|
||||||
|
|
||||||
|
/* Generate the SRK (context save encryption key). */
|
||||||
|
se_generate_random_key(srkgen_keyslot, rng_keyslot);
|
||||||
|
se_generate_srk(srkgen_keyslot);
|
||||||
|
|
||||||
|
se_generate_random(rng_keyslot, work_buf, 0x10);
|
||||||
|
|
||||||
|
/* Save random initial block. */
|
||||||
|
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY);
|
||||||
|
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_MEM);
|
||||||
|
se->BLOCK_COUNT_REG = 0;
|
||||||
|
se_encrypt_with_srk(dst, 0x10, work_buf, 0x10);
|
||||||
|
|
||||||
|
/* Save Sticky Bits. */
|
||||||
|
for (unsigned int i = 0; i < 0x2; i++) {
|
||||||
|
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_STICKY_BITS) | (i << CTX_SAVE_STICKY_BIT_INDEX_SHIFT);
|
||||||
|
se->BLOCK_COUNT_REG = 0;
|
||||||
|
se_encrypt_with_srk(dst + 0x10 + (i * 0x10), 0x10, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save AES Key Table. */
|
||||||
|
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
|
||||||
|
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_LOW_BITS);
|
||||||
|
se->BLOCK_COUNT_REG = 0;
|
||||||
|
se_encrypt_with_srk(dst + 0x30 + (i * 0x20), 0x10, NULL, 0);
|
||||||
|
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_HIGH_BITS);
|
||||||
|
se->BLOCK_COUNT_REG = 0;
|
||||||
|
se_encrypt_with_srk(dst + 0x40 + (i * 0x20), 0x10, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save AES Original IVs. */
|
||||||
|
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
|
||||||
|
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_ORIGINAL_IV);
|
||||||
|
se->BLOCK_COUNT_REG = 0;
|
||||||
|
se_encrypt_with_srk(dst + 0x230 + (i * 0x10), 0x10, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save AES Updated IVs */
|
||||||
|
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
|
||||||
|
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_UPDATED_IV);
|
||||||
|
se->BLOCK_COUNT_REG = 0;
|
||||||
|
se_encrypt_with_srk(dst + 0x330 + (i * 0x10), 0x10, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save RSA Keytable. */
|
||||||
|
uint8_t *rsa_ctx_out = (uint8_t *)dst + 0x430;
|
||||||
|
for (unsigned int rsa_key = 0; rsa_key < KEYSLOT_RSA_MAX; rsa_key++) {
|
||||||
|
for (unsigned int mod_exp = 0; mod_exp < 2; mod_exp++) {
|
||||||
|
for (unsigned int sub_block = 0; sub_block < 0x10; sub_block++) {
|
||||||
|
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_RSA) | ((2 * rsa_key + (1 - mod_exp)) << CTX_SAVE_RSA_KEY_INDEX_SHIFT) | (sub_block << CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT);
|
||||||
|
se->BLOCK_COUNT_REG = 0;
|
||||||
|
se_encrypt_with_srk(rsa_ctx_out, 0x10, NULL, 0);
|
||||||
|
rsa_ctx_out += 0x10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save "Known Pattern. " */
|
||||||
|
static const uint8_t context_save_known_pattern[0x10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
|
||||||
|
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_MEM);
|
||||||
|
se->BLOCK_COUNT_REG = 0;
|
||||||
|
se_encrypt_with_srk(dst + 0x830, 0x10, context_save_known_pattern, 0x10);
|
||||||
|
|
||||||
|
/* Save SRK into PMC registers. */
|
||||||
|
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_SRK);
|
||||||
|
se->BLOCK_COUNT_REG = 0;
|
||||||
|
se_encrypt_with_srk(work_buf, 0, NULL, 0);
|
||||||
|
se->CONFIG_REG = 0;
|
||||||
|
se_encrypt_with_srk(work_buf, 0, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -203,6 +203,7 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si
|
||||||
void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size);
|
void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size);
|
||||||
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||||
void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv);
|
void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv);
|
||||||
|
void se_aes_128_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||||
|
|
||||||
/* Hash API */
|
/* Hash API */
|
||||||
void se_calculate_sha256(void *dst, const void *src, size_t src_size);
|
void se_calculate_sha256(void *dst, const void *src, size_t src_size);
|
||||||
|
@ -216,4 +217,10 @@ bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const v
|
||||||
void se_initialize_rng(unsigned int keyslot);
|
void se_initialize_rng(unsigned int keyslot);
|
||||||
void se_generate_random(unsigned int keyslot, void *dst, size_t size);
|
void se_generate_random(unsigned int keyslot, void *dst, size_t size);
|
||||||
|
|
||||||
|
/* SE context save API. */
|
||||||
|
void se_generate_srk(unsigned int srkgen_keyslot);
|
||||||
|
void se_set_in_context_save_mode(bool is_context_save_mode);
|
||||||
|
void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot);
|
||||||
|
void se_save_context(unsigned int srk_keyslot, unsigned int rng_keyslot, void *dst);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,6 +33,11 @@ _start:
|
||||||
cmp r2, r3
|
cmp r2, r3
|
||||||
beq _relocation_loop_end
|
beq _relocation_loop_end
|
||||||
|
|
||||||
|
/* If we are relocating, we are not rebooting to ourselves. Note that. */
|
||||||
|
ldr r0, =0x4003FFFC
|
||||||
|
mov r1, #0x0
|
||||||
|
str r1, [r0]
|
||||||
|
|
||||||
ldr r4, =_relocation_loop_end
|
ldr r4, =_relocation_loop_end
|
||||||
mov r4, #0x1000
|
mov r4, #0x1000
|
||||||
mov r1, #0x0
|
mov r1, #0x0
|
||||||
|
|
Loading…
Reference in a new issue