diff --git a/sept/sept-secondary/linker.ld b/sept/sept-secondary/linker.ld index b442fd3b6..27dba8fc7 100644 --- a/sept/sept-secondary/linker.ld +++ b/sept/sept-secondary/linker.ld @@ -148,6 +148,7 @@ SECTIONS . = ALIGN(32); PROVIDE (__bss_end__ = ABSOLUTE(.)); } >main :NONE + . = ALIGN(32); __end__ = ABSOLUTE(.) ; /* ================== diff --git a/sept/sept-secondary/sept_sign.py b/sept/sept-secondary/sept_sign.py index f4903d142..c764a7598 100644 --- a/sept/sept-secondary/sept_sign.py +++ b/sept/sept-secondary/sept_sign.py @@ -53,7 +53,8 @@ def main(argc, argv): return 1 with open(argv[1], 'rb') as f: code = f.read() - assert (len(code) & 0xF) == 0 + if len(code) & 0xF: + code += '\x00'*(0x10 - (len(code) & 0xF)) # TODO: Support dev unit crypto 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')) diff --git a/sept/sept-secondary/src/di.c b/sept/sept-secondary/src/di.c index b6f8116c9..f3f76209b 100644 --- a/sept/sept-secondary/src/di.c +++ b/sept/sept-secondary/src/di.c @@ -111,7 +111,7 @@ void display_init() exec_cfg((uint32_t *)CAR_BASE, _display_config_1, 4); 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); @@ -149,8 +149,8 @@ void display_init() 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 *)DSI_BASE, _display_config_5, 21); MAKE_DI_REG(DC_DISP_DISP_CLOCK_CONTROL) = 4; exec_cfg((uint32_t *)DSI_BASE, _display_config_7, 10); diff --git a/sept/sept-secondary/src/di.h b/sept/sept-secondary/src/di.h index 4aa4f944d..5d667ecd2 100644 --- a/sept/sept-secondary/src/di.h +++ b/sept/sept-secondary/src/di.h @@ -190,6 +190,7 @@ #define DC_WIN_WIN_OPTIONS 0x700 #define H_DIRECTION (1 << 0) #define V_DIRECTION (1 << 2) +#define SCAN_COLUMN (1 << 4) #define COLOR_EXPAND (1 << 6) #define CSC_ENABLE (1 << 18) #define WIN_ENABLE (1 << 30) @@ -237,6 +238,8 @@ #define V_DDA_INC(x) (((x) & 0xffff) << 16) #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 /* 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_INIT_SEQ_DATA_15 0x5F + typedef struct _cfg_op_t { uint32_t off; diff --git a/sept/sept-secondary/src/di.inl b/sept/sept-secondary/src/di.inl index e438ca5cb..f842bfddc 100644 --- a/sept/sept-secondary/src/di.inl +++ b/sept/sept-secondary/src/di.inl @@ -128,7 +128,7 @@ static const cfg_op_t _display_config_2[94] = { }; //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_INT_ENABLE, 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_2, 0}, {DSI_INIT_SEQ_DATA_3, 0}, + {DSI_INIT_SEQ_DATA_15, 0}, {DSI_DCS_CMDS, 0}, {DSI_PKT_SEQ_0_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] = { {0x18, 0}, {2, 0xF3F10000}, - {0x16, 1}, + {0x16, 0}, {0x18, 0}, {0x18, 0x10010}, {0x17, 0x300} @@ -474,10 +475,10 @@ static const cfg_op_t _display_config_13[16] = { {DSI_PAD_CONTROL_1, 0}, {DSI_PHY_TIMING_0, 0x6070601}, {DSI_PHY_TIMING_1, 0x40A0E05}, - {DSI_PHY_TIMING_2, 0x30109}, + {DSI_PHY_TIMING_2, 0x30118}, {DSI_BTA_TIMING, 0x190A14}, {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_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}, diff --git a/sept/sept-secondary/src/hwinit.c b/sept/sept-secondary/src/hwinit.c index f959754de..655054791 100644 --- a/sept/sept-secondary/src/hwinit.c +++ b/sept/sept-secondary/src/hwinit.c @@ -186,25 +186,22 @@ void config_se_brom() void nx_hwinit() { volatile tegra_car_t *car = car_get_regs(); + volatile tegra_pmc_t *pmc = pmc_get_regs(); /* This stuff was handled by whatever loaded us. */ - /* - config_se_brom(); - - AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F; - pmc->scratch49 = (((pmc->scratch49 >> 1) << 1) & 0xFFFFFFFD); - - mbist_workaround(); - - clkrst_reboot(CARDEVICE_SE); - - fuse_init(); - - mc_enable(); - - config_oscillators(); - */ + config_se_brom(); + AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F; + pmc->scratch49 = (((pmc->scratch49 >> 1) << 1) & 0xFFFFFFFD); + + mbist_workaround(); + + clkrst_reboot(CARDEVICE_SE); + + fuse_init(); + + mc_enable(); + /* Disable pinmux tristate input clamping. */ APB_MISC_PP_PINMUX_GLOBAL_0 = 0; diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c index c5f6b2037..66c690c2d 100644 --- a/sept/sept-secondary/src/main.c +++ b/sept/sept-secondary/src/main.c @@ -19,6 +19,8 @@ #include "panic.h" #include "hwinit.h" #include "di.h" +#include "se.h" +#include "pmc.h" #include "timers.h" #include "fs_utils.h" #include "stage2.h" @@ -34,6 +36,82 @@ extern void (*__program_exit_callback)(int rc); 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) { g_framebuffer = (void *)0xC0000000; @@ -79,6 +157,9 @@ static void exit_callback(int rc) { int main(void) { 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. */ log_set_log_level(log_level); diff --git a/sept/sept-secondary/src/se.c b/sept/sept-secondary/src/se.c index d4dbdc498..09b46dbaa 100644 --- a/sept/sept-secondary/src/se.c +++ b/sept/sept-secondary/src/se.c @@ -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); } +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. */ void se_calculate_sha256(void *dst, const void *src, size_t src_size) { 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); } } + +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); +} + diff --git a/sept/sept-secondary/src/se.h b/sept/sept-secondary/src/se.h index 64998621a..fa3dc0191 100644 --- a/sept/sept-secondary/src/se.h +++ b/sept/sept-secondary/src/se.h @@ -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_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_128_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); /* Hash API */ 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_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 diff --git a/sept/sept-secondary/src/start.s b/sept/sept-secondary/src/start.s index 4cfa68003..b53b2aa44 100644 --- a/sept/sept-secondary/src/start.s +++ b/sept/sept-secondary/src/start.s @@ -32,6 +32,11 @@ _start: adr r3, _start cmp r2, r3 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 mov r4, #0x1000