diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index afc35dd93..6e1620bc1 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -18,7 +18,6 @@ #include "utils.h" #include "memory_map.h" - #include "bootup.h" #include "cpu_context.h" #include "package2.h" @@ -38,7 +37,6 @@ extern void *__start_cold_addr; extern size_t __bin_size; - static const uint8_t new_device_key_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { {0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.x New Device Key Source. */ {0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C}, /* 5.x New Device Key Source. */ @@ -85,15 +83,15 @@ static void setup_se(void) { intr_initialize_gic_nonsecure(); /* 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); + volatile tegra_se_t *se = se_get_regs(); + se->_0x0 &= 0xFFFEFFFF; /* Clear bit 16. */ + (void)(se->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; - p_security_engine->_0x0 &= 0xFFFFFFFB; + se->_0x4 = 0; + se->AES_KEY_READ_DISABLE_REG = 0; + se->RSA_KEY_READ_DISABLE_REG = 0; + se->_0x0 &= 0xFFFFFFFB; /* Currently unknown what each flag does. */ for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) { @@ -139,8 +137,7 @@ static void setup_se(void) { set_aes_keyslot_flags(KEYSLOT_SWITCH_SESSIONKEY, 0xFF); /* Generate test vector for our keys. */ - se_generate_stored_vector(); - + se_generate_stored_vector(); } static void setup_boot_config(void) { @@ -169,7 +166,6 @@ static void package2_crypt_ctr(unsigned int master_key_rev, void *dst, size_t ds se_aes_ctr_crypt(KEYSLOT_SWITCH_PACKAGE2KEY, dst, dst_size, src, src_size, ctr, ctr_size); } - static void verify_header_signature(package2_header_t *header) { const uint8_t *modulus; @@ -506,7 +502,8 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { randomcache_init(); /* memclear the initial copy of Exosphere running in IRAM (relocated to TZRAM by earlier code). */ - //memset((void *)reloc_list->reloc_base, 0, reloc_list->loaded_bin_size); + /* memset((void *)reloc_list->reloc_base, 0, reloc_list->loaded_bin_size); */ + /* Let NX Bootloader know that we're running. */ MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 1; diff --git a/exosphere/src/se.c b/exosphere/src/se.c index 058a13735..80cc350ec 100644 --- a/exosphere/src/se.c +++ b/exosphere/src/se.c @@ -36,9 +36,8 @@ static unsigned int g_se_exp_sizes[KEYSLOT_RSA_MAX]; static bool g_se_generated_vector = false; static uint8_t g_se_stored_test_vector[0x10]; - /* Initialize a SE linked list. */ -void ll_init(se_ll_t *ll, void *buffer, size_t size) { +void ll_init(volatile se_ll_t *ll, void *buffer, size_t size) { ll->num_entries = 0; /* 1 Entry. */ if (buffer != NULL) { @@ -62,7 +61,7 @@ void set_security_engine_callback(unsigned int (*callback)(void)) { /* Fires on Security Engine operation completion. */ void se_operation_completed(void) { - SECURITY_ENGINE->INT_ENABLE_REG = 0; + se_get_regs()->INT_ENABLE_REG = 0; if (g_se_callback != NULL) { g_se_callback(); g_se_callback = NULL; @@ -70,13 +69,14 @@ void se_operation_completed(void) { } void se_check_error_status_reg(void) { - if (SECURITY_ENGINE->ERR_STATUS_REG) { + if (se_get_regs()->ERR_STATUS_REG) { generic_panic(); } } void se_check_for_error(void) { - if (SECURITY_ENGINE->INT_STATUS_REG & 0x10000 || SECURITY_ENGINE->FLAGS_REG & 3 || SECURITY_ENGINE->ERR_STATUS_REG) { + volatile tegra_se_t *se = se_get_regs(); + if (se->INT_STATUS_REG & 0x10000 || se->FLAGS_REG & 3 || se->ERR_STATUS_REG) { generic_panic(); } } @@ -86,12 +86,11 @@ void se_trigger_interrupt(void) { } void se_verify_flags_cleared(void) { - if (SECURITY_ENGINE->FLAGS_REG & 3) { + if (se_get_regs()->FLAGS_REG & 3) { generic_panic(); } } - void se_generate_test_vector(void *vector) { /* TODO: Implement real test vector generation. */ memset(vector, 0, 0x10); @@ -122,23 +121,27 @@ void se_generate_stored_vector(void) { /* Set the flags for an AES keyslot. */ void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } /* Misc flags. */ if (flags & ~0x80) { - SECURITY_ENGINE->AES_KEYSLOT_FLAGS[keyslot] = ~flags; + se->AES_KEYSLOT_FLAGS[keyslot] = ~flags; } /* Disable keyslot reads. */ if (flags & 0x80) { - SECURITY_ENGINE->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot); + se->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot); } } /* Set the flags for an RSA keyslot. */ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_RSA_MAX) { generic_panic(); } @@ -146,28 +149,32 @@ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) { /* Misc flags. */ if (flags & ~0x80) { /* TODO: Why are flags assigned this way? */ - SECURITY_ENGINE->RSA_KEYSLOT_FLAGS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7; + se->RSA_KEYSLOT_FLAGS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7; } /* Disable keyslot reads. */ if (flags & 0x80) { - SECURITY_ENGINE->RSA_KEY_READ_DISABLE_REG &= ~(1 << keyslot); + se->RSA_KEY_READ_DISABLE_REG &= ~(1 << keyslot); } } void clear_aes_keyslot(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } /* Zero out the whole keyslot and IV. */ for (unsigned int i = 0; i < 0x10; i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = 0; + se->AES_KEYTABLE_ADDR = (keyslot << 4) | i; + se->AES_KEYTABLE_DATA = 0; } } void clear_rsa_keyslot(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_RSA_MAX) { generic_panic(); } @@ -175,40 +182,44 @@ void clear_rsa_keyslot(unsigned int keyslot) { /* Zero out the whole keyslot. */ for (unsigned int i = 0; i < 0x40; i++) { /* Select Keyslot Modulus[i] */ - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = 0; + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40; + se->RSA_KEYTABLE_DATA = 0; } for (unsigned int i = 0; i < 0x40; i++) { /* Select Keyslot Expontent[i] */ - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = 0; + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; + se->RSA_KEYTABLE_DATA = 0; } } void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) { generic_panic(); } for (size_t i = 0; i < (key_size >> 2); i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = read32le(key, 4 * i); + se->AES_KEYTABLE_ADDR = (keyslot << 4) | i; + se->AES_KEYTABLE_DATA = read32le(key, 4 * i); } } void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) { generic_panic(); } for (size_t i = 0; i < (modulus_size >> 2); i++) { - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4); + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i; + se->RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4); } for (size_t i = 0; i < (exp_size >> 2); i++) { - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4); + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; + se->RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4); } g_se_modulus_sizes[keyslot] = modulus_size; @@ -216,48 +227,56 @@ void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_ } void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) { generic_panic(); } for (size_t i = 0; i < (iv_size >> 2); i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = read32le(iv, 4 * i); + se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; + se->AES_KEYTABLE_DATA = read32le(iv, 4 * i); } } void clear_aes_keyslot_iv(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } for (size_t i = 0; i < (0x10 >> 2); i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = 0; + se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; + se->AES_KEYTABLE_DATA = 0; } } void set_se_ctr(const void *ctr) { for (unsigned int i = 0; i < 4; i++) { - SECURITY_ENGINE->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); + se_get_regs()->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); } } void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSIZE_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) { generic_panic(); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB); - SECURITY_ENGINE->CRYPTO_REG = keyslot_src << 24; - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; - SECURITY_ENGINE->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; + se->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB); + se->CRYPTO_REG = keyslot_src << 24; + se->BLOCK_COUNT_REG = 0; + se->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; flush_dcache_range(wrapped_key, (const uint8_t *)wrapped_key + wrapped_key_size); trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size); } void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, unsigned int crypt_config, bool encrypt, unsigned int (*callback)(void)) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } @@ -268,34 +287,34 @@ void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr, /* Setup Config register. */ if (encrypt) { - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); } else { - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); } /* Setup Crypto register. */ - SECURITY_ENGINE->CRYPTO_REG = crypt_config | (keyslot << 24) | (encrypt << 8); + se->CRYPTO_REG = crypt_config | (keyslot << 24) | (encrypt << 8); /* Mark this encryption as insecure -- this makes the SE not a secure busmaster. */ - SECURITY_ENGINE->CRYPTO_REG |= 0x80000000; + se->CRYPTO_REG |= 0x80000000; /* Appropriate number of blocks. */ - SECURITY_ENGINE->BLOCK_COUNT_REG = (size >> 4) - 1; + se->BLOCK_COUNT_REG = (size >> 4) - 1; /* Set the callback, for after the async operation. */ set_security_engine_callback(callback); /* Enable SE Interrupt firing for async op. */ - SECURITY_ENGINE->INT_ENABLE_REG = 0x10; + se->INT_ENABLE_REG = 0x10; /* Setup Input/Output lists */ - SECURITY_ENGINE->IN_LL_ADDR_REG = in_ll_paddr; - SECURITY_ENGINE->OUT_LL_ADDR_REG = out_ll_paddr; + se->IN_LL_ADDR_REG = in_ll_paddr; + se->OUT_LL_ADDR_REG = out_ll_paddr; /* 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 = 1; + se->ERR_STATUS_REG = se->ERR_STATUS_REG; + se->INT_STATUS_REG = se->INT_STATUS_REG; + se->OPERATION_REG = 1; /* Ensure writes go through. */ __dsb_ish(); @@ -303,7 +322,7 @@ void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr, void se_aes_ctr_crypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *ctr, unsigned int (*callback)(void)) { /* Unknown what this write does, but official code writes it for CTR mode. */ - SECURITY_ENGINE->_0x80C = 1; + se_get_regs()->SPARE_0 = 1; set_se_ctr(ctr); se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x81E, true, callback); } @@ -318,8 +337,8 @@ void se_aes_cbc_decrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, ui se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x66, false, callback); } - void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*callback)(void)) { + volatile tegra_se_t *se = se_get_regs(); uint8_t stack_buf[KEYSIZE_RSA_MAX]; if (keyslot >= KEYSLOT_RSA_MAX || size > KEYSIZE_RSA_MAX) { @@ -331,24 +350,24 @@ void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*cal stack_buf[i] = *((uint8_t *)buf + size - i - 1); } - - SECURITY_ENGINE->CONFIG_REG = (ALG_RSA | DST_RSAREG); - SECURITY_ENGINE->RSA_CONFIG = keyslot << 24; - SECURITY_ENGINE->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; - SECURITY_ENGINE->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; + se->CONFIG_REG = (ALG_RSA | DST_RSAREG); + se->RSA_CONFIG = keyslot << 24; + se->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; + se->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; set_security_engine_callback(callback); /* Enable SE Interrupt firing for async op. */ - SECURITY_ENGINE->INT_ENABLE_REG = 0x10; + se->INT_ENABLE_REG = 0x10; flush_dcache_range(stack_buf, stack_buf + KEYSIZE_RSA_MAX); trigger_se_rsa_op(stack_buf, size); - while (!(SECURITY_ENGINE->INT_STATUS_REG & 2)) { /* Wait a while */ } + while (!(se->INT_STATUS_REG & 2)) { /* Wait a while */ } } void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); uint8_t stack_buf[KEYSIZE_RSA_MAX]; if (keyslot >= KEYSLOT_RSA_MAX || src_size > KEYSIZE_RSA_MAX || dst_size > KEYSIZE_RSA_MAX) { @@ -360,11 +379,10 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co stack_buf[i] = *((uint8_t *)src + src_size - i - 1); } - SECURITY_ENGINE->CONFIG_REG = (ALG_RSA | DST_RSAREG); - SECURITY_ENGINE->RSA_CONFIG = keyslot << 24; - SECURITY_ENGINE->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; - SECURITY_ENGINE->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; - + se->CONFIG_REG = (ALG_RSA | DST_RSAREG); + se->RSA_CONFIG = keyslot << 24; + se->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; + se->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; flush_dcache_range(stack_buf, stack_buf + KEYSIZE_RSA_MAX); trigger_se_blocking_op(OP_START, NULL, 0, stack_buf, src_size); @@ -382,7 +400,7 @@ void se_get_exp_mod_output(void *buf, size_t size) { /* Copy endian swapped output. */ while (num_dwords) { - *p_out = read32be(SECURITY_ENGINE->RSA_OUTPUT, offset); + *p_out = read32be(se_get_regs()->RSA_OUTPUT, offset); offset += 4; p_out--; num_dwords--; @@ -447,22 +465,25 @@ bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const v void trigger_se_rsa_op(void *buf, size_t size) { + volatile tegra_se_t *se = se_get_regs(); se_ll_t in_ll; + ll_init(&in_ll, (void *)buf, size); /* Set the input LL. */ - SECURITY_ENGINE->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll); + se->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_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 = 1; + se->ERR_STATUS_REG = se->ERR_STATUS_REG; + se->INT_STATUS_REG = se->INT_STATUS_REG; + se->OPERATION_REG = 1; /* Ensure writes go through. */ __dsb_ish(); } void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); se_ll_t in_ll; se_ll_t out_ll; @@ -472,20 +493,19 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v __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); + se->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll); + se->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; + se->ERR_STATUS_REG = se->ERR_STATUS_REG; + se->INT_STATUS_REG = se->INT_STATUS_REG; + se->OPERATION_REG = op; - while (!(SECURITY_ENGINE->INT_STATUS_REG & 0x10)) { /* Wait a while */ } + while (!(se->INT_STATUS_REG & 0x10)) { /* Wait a while */ } se_check_for_error(); } - /* Secure AES Functionality. */ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) { uint8_t block[0x10] = {0}; @@ -501,7 +521,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, flush_dcache_range(block, block + sizeof(block)); /* Trigger AES operation. */ - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se_get_regs()->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block)); /* Copy output data into dst. */ @@ -512,6 +532,8 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, } 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) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) { generic_panic(); } @@ -526,15 +548,15 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo unsigned int num_blocks = src_size >> 4; /* Unknown what this write does, but official code writes it for CTR mode. */ - SECURITY_ENGINE->_0x80C = 1; - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x91E; + se->SPARE_0 = 1; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x91E; set_se_ctr(ctr); /* Handle any aligned blocks. */ size_t aligned_size = (size_t)num_blocks << 4; if (aligned_size) { - SECURITY_ENGINE->BLOCK_COUNT_REG = num_blocks - 1; + se->BLOCK_COUNT_REG = num_blocks - 1; trigger_se_blocking_op(OP_START, dst, dst_size, src, aligned_size); } @@ -553,13 +575,15 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo } void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { generic_panic(); } /* Set configuration high (256-bit vs 128-bit) based on parameter. */ - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16); - SECURITY_ENGINE->CRYPTO_REG = keyslot << 24 | 0x100; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16); + se->CRYPTO_REG = keyslot << 24 | 0x100; flush_dcache_range((uint8_t *)src, (uint8_t *)src + 0x10); se_perform_aes_block_operation(dst, 0x10, src, 0x10); flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + 0x10); @@ -576,12 +600,14 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si void se_aes_ecb_decrypt_block(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 || dst_size != 0x10 || src_size != 0x10) { generic_panic(); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = keyslot << 24; + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); + se->CRYPTO_REG = keyslot << 24; flush_dcache_range((uint8_t *)src, (uint8_t *)src + 0x10); se_perform_aes_block_operation(dst, 0x10, src, 0x10); flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + 0x10); @@ -600,6 +626,8 @@ void shift_left_xor_rb(uint8_t *key) { } void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } @@ -616,17 +644,16 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con shift_left_xor_rb(derived_key); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | (0x145); + se->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16); + se->CRYPTO_REG = (keyslot << 24) | (0x145); clear_aes_keyslot_iv(keyslot); - unsigned int num_blocks = (data_size + 0xF) >> 4; /* Handle aligned blocks. */ if (num_blocks > 1) { - SECURITY_ENGINE->BLOCK_COUNT_REG = num_blocks - 2; + se->BLOCK_COUNT_REG = num_blocks - 2; trigger_se_blocking_op(OP_START, NULL, 0, data, data_size); - SECURITY_ENGINE->CRYPTO_REG |= 0x80; + se->CRYPTO_REG |= 0x80; } /* Create final block. */ @@ -643,13 +670,13 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con } /* Perform last operation. */ - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->BLOCK_COUNT_REG = 0; flush_dcache_range(last_block, last_block + sizeof(last_block)); trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block)); /* Copy output CMAC. */ for (unsigned int i = 0; i < (cmac_size >> 2); i++) { - ((uint32_t *)cmac)[i] = read32le(SECURITY_ENGINE->HASH_RESULT_REG, i << 2); + ((uint32_t *)cmac)[i] = read32le(se->HASH_RESULT_REG, i << 2); } } @@ -661,42 +688,48 @@ void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_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) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) { generic_panic(); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x144; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16); + se->CRYPTO_REG = (keyslot << 24) | 0x144; set_aes_keyslot_iv(keyslot, iv, 0x10); - SECURITY_ENGINE->BLOCK_COUNT_REG = (src_size >> 4) - 1; + 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(); + /* Setup config for SHA256, size = BITS(src_size) */ - SECURITY_ENGINE->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG); - SECURITY_ENGINE->SHA_CONFIG_REG = 1; - SECURITY_ENGINE->SHA_MSG_LENGTH_REG = (uint32_t)(src_size << 3); - SECURITY_ENGINE->_0x208 = 0; - SECURITY_ENGINE->_0x20C = 0; - SECURITY_ENGINE->_0x210 = 0; - SECURITY_ENGINE->SHA_MSG_LEFT_REG = (uint32_t)(src_size << 3); - SECURITY_ENGINE->_0x218 = 0; - SECURITY_ENGINE->_0x21C = 0; - SECURITY_ENGINE->_0x220 = 0; + se->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG); + se->SHA_CONFIG_REG = 1; + se->SHA_MSG_LENGTH_REG = (uint32_t)(src_size << 3); + se->_0x208 = 0; + se->_0x20C = 0; + se->_0x210 = 0; + se->SHA_MSG_LEFT_REG = (uint32_t)(src_size << 3); + se->_0x218 = 0; + se->_0x21C = 0; + se->_0x220 = 0; /* Trigger the operation. */ trigger_se_blocking_op(OP_START, NULL, 0, src, src_size); /* Copy output hash. */ for (unsigned int i = 0; i < (0x20 >> 2); i++) { - ((uint32_t *)dst)[i] = read32be(SECURITY_ENGINE->HASH_RESULT_REG, i << 2); + ((uint32_t *)dst)[i] = read32be(se->HASH_RESULT_REG, i << 2); } } /* RNG API */ void se_initialize_rng(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } @@ -705,74 +738,80 @@ void se_initialize_rng(unsigned int keyslot) { /* This will be discarded, when done. */ uint8_t output_buf[0x10]; - SECURITY_ENGINE->RNG_SRC_CONFIG_REG = 3; /* Entropy enable + Entropy lock enable */ - SECURITY_ENGINE->RNG_RESEED_INTERVAL_REG = 70001; - SECURITY_ENGINE->CONFIG_REG = (ALG_RNG | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x108; - SECURITY_ENGINE->RNG_CONFIG_REG = 5; - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->RNG_SRC_CONFIG_REG = 3; /* Entropy enable + Entropy lock enable */ + se->RNG_RESEED_INTERVAL_REG = 70001; + se->CONFIG_REG = (ALG_RNG | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 5; + se->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, output_buf, 0x10, NULL, 0); } void se_generate_random(unsigned int keyslot, void *dst, size_t size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } uint32_t num_blocks = size >> 4; size_t aligned_size = num_blocks << 4; - SECURITY_ENGINE->CONFIG_REG = (ALG_RNG | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x108; - SECURITY_ENGINE->RNG_CONFIG_REG = 4; + se->CONFIG_REG = (ALG_RNG | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 4; if (num_blocks >= 1) { - SECURITY_ENGINE->BLOCK_COUNT_REG = num_blocks - 1; + se->BLOCK_COUNT_REG = num_blocks - 1; trigger_se_blocking_op(OP_START, dst, aligned_size, NULL, 0); } if (size > aligned_size) { se_perform_aes_block_operation(dst + aligned_size, size - aligned_size, NULL, 0); } - } - /* SE context save API. */ void se_set_in_context_save_mode(bool is_context_save_mode) { - uint32_t val = SECURITY_ENGINE->_0x0; + volatile tegra_se_t *se = se_get_regs(); + + uint32_t val = se->_0x0; if (is_context_save_mode) { val |= 0x10000; } else { val &= 0xFFFEFFFF; } - SECURITY_ENGINE->_0x0 = val; + se->_0x0 = val; /* Perform a useless read from flags reg. */ - (void)(SECURITY_ENGINE->FLAGS_REG); + (void)(se->FLAGS_REG); } 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. */ - SECURITY_ENGINE->CONFIG_REG = (ALG_RNG | DST_KEYTAB); - SECURITY_ENGINE->CRYPTO_REG = (rng_keyslot << 24) | 0x108; - SECURITY_ENGINE->RNG_CONFIG_REG = 4; - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + 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. */ - SECURITY_ENGINE->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8); + se->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8); trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0); /* Generate high part of key. */ - SECURITY_ENGINE->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8) | 1; + se->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8) | 1; trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0); } void se_generate_srk(unsigned int srkgen_keyslot) { - SECURITY_ENGINE->CONFIG_REG = (ALG_RNG | DST_SRK); - SECURITY_ENGINE->CRYPTO_REG = (srkgen_keyslot << 24) | 0x108; - SECURITY_ENGINE->RNG_CONFIG_REG = 6; - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + 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); } @@ -796,6 +835,7 @@ void se_encrypt_with_srk(void *dst, size_t dst_size, const void *src, size_t src } 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); @@ -808,39 +848,39 @@ void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void flush_dcache_range(work_buf, work_buf + 0x10); /* Save random initial block. */ - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_MEM); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + 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++) { - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_STICKY_BITS) | (i << CTX_SAVE_STICKY_BIT_INDEX_SHIFT); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + 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++) { - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_LOW_BITS); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + 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); - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_HIGH_BITS); - SECURITY_ENGINE->BLOCK_COUNT_REG = 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++) { - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_ORIGINAL_IV); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + 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++) { - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_UPDATED_IV); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + 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); } @@ -849,8 +889,8 @@ void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void 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++) { - SECURITY_ENGINE->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); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + 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; } @@ -859,14 +899,14 @@ void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void /* 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}; - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_MEM); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + 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. */ - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_SRK); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_SRK); + se->BLOCK_COUNT_REG = 0; se_encrypt_with_srk(work_buf, 0, NULL, 0); - SECURITY_ENGINE->CONFIG_REG = 0; + se->CONFIG_REG = 0; se_encrypt_with_srk(work_buf, 0, NULL, 0); } diff --git a/exosphere/src/se.h b/exosphere/src/se.h index 326602d26..54768d620 100644 --- a/exosphere/src/se.h +++ b/exosphere/src/se.h @@ -97,7 +97,7 @@ #define RSA_2048_BYTES 0x100 -typedef struct security_engine { +typedef struct { uint32_t _0x0; uint32_t _0x4; uint32_t OPERATION_REG; @@ -157,15 +157,13 @@ typedef struct security_engine { uint32_t FLAGS_REG; uint32_t ERR_STATUS_REG; uint32_t _0x808; - uint32_t _0x80C; + uint32_t SPARE_0; uint32_t _0x810; uint32_t _0x814; uint32_t _0x818; uint32_t _0x81C; uint8_t _0x820[0x17E0]; -} security_engine_t; - -static_assert(sizeof(security_engine_t) == 0x2000, "Mis-defined Security Engine Registers!"); +} tegra_se_t; typedef struct { uint32_t address; @@ -177,15 +175,10 @@ typedef struct { se_addr_info_t addr_info; /* This should really be an array...but for our use case it works. */ } se_ll_t; - -/* WIP, API subject to change. */ - -static inline volatile security_engine_t *get_security_engine(void) { - return (volatile security_engine_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_SE)); +static inline volatile tegra_se_t *se_get_regs(void) { + return (volatile tegra_se_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_SE)); } -#define SECURITY_ENGINE (get_security_engine()) - /* This function MUST be registered to fire on the appropriate interrupt. */ void se_operation_completed(void); @@ -209,7 +202,6 @@ void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_s void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size); void set_se_ctr(const void *ctr); - /* Insecure AES API */ void se_aes_ctr_crypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *ctr, unsigned int (*callback)(void)); void se_aes_cbc_encrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *iv, unsigned int (*callback)(void)); diff --git a/fusee/fusee-primary/src/i2c.c b/fusee/fusee-primary/src/i2c.c index 27063b3cd..aec946cf2 100644 --- a/fusee/fusee-primary/src/i2c.c +++ b/fusee/fusee-primary/src/i2c.c @@ -175,8 +175,7 @@ bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src i2c_load_config(regs); /* Config |= SEND; */ - regs->I2C_I2C_CNFG_0 |= 0x200; - + regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200); while (regs->I2C_I2C_STATUS_0 & 0x100) { /* Wait until not busy. */ @@ -203,8 +202,7 @@ bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_ i2c_load_config(regs); /* Config |= SEND; */ - regs->I2C_I2C_CNFG_0 |= 0x200; - + regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200); while (regs->I2C_I2C_STATUS_0 & 0x100) { /* Wait until not busy. */ diff --git a/fusee/fusee-primary/src/i2c.h b/fusee/fusee-primary/src/i2c.h index ec3efecc6..9399b0024 100644 --- a/fusee/fusee-primary/src/i2c.h +++ b/fusee/fusee-primary/src/i2c.h @@ -21,8 +21,8 @@ #include #include -#define I2C234_BASE 0x7000C000 -#define I2C56_BASE 0x7000D000 +#define I2C1234_BASE 0x7000C000 +#define I2C56_BASE 0x7000D000 #define I2C_1 0 #define I2C_2 1 @@ -82,10 +82,10 @@ typedef struct { uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0; } tegra_i2c_t; -#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x000)) -#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x400)) -#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x500)) -#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x700)) +#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x000)) +#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x400)) +#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x500)) +#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x700)) #define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000)) #define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100)) diff --git a/fusee/fusee-primary/src/se.c b/fusee/fusee-primary/src/se.c index b466bd80b..d4dbdc498 100644 --- a/fusee/fusee-primary/src/se.c +++ b/fusee/fusee-primary/src/se.c @@ -39,8 +39,7 @@ void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) { } void se_check_error_status_reg(void) { - volatile tegra_se_t *se = se_get_regs(); - if (se->ERR_STATUS_REG) { + if (se_get_regs()->ERR_STATUS_REG) { generic_panic(); } } @@ -53,8 +52,7 @@ void se_check_for_error(void) { } void se_verify_flags_cleared(void) { - volatile tegra_se_t *se = se_get_regs(); - if (se->FLAGS_REG & 3) { + if (se_get_regs()->FLAGS_REG & 3) { generic_panic(); } } @@ -193,9 +191,8 @@ void clear_aes_keyslot_iv(unsigned int keyslot) { } void set_se_ctr(const void *ctr) { - volatile tegra_se_t *se = se_get_regs(); for (unsigned int i = 0; i < 4; i++) { - se->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); + se_get_regs()->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); } } @@ -237,7 +234,6 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co } void se_get_exp_mod_output(void *buf, size_t size) { - volatile tegra_se_t *se = se_get_regs(); size_t num_dwords = (size >> 2); if (num_dwords < 1) { @@ -249,7 +245,7 @@ void se_get_exp_mod_output(void *buf, size_t size) { /* Copy endian swapped output. */ while (num_dwords) { - *p_out = read32be(se->RSA_OUTPUT, offset); + *p_out = read32be(se_get_regs()->RSA_OUTPUT, offset); offset += 4; p_out--; num_dwords--; @@ -330,10 +326,8 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v se_check_for_error(); } - /* Secure AES Functionality. */ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) { - volatile tegra_se_t *se = se_get_regs(); uint8_t block[0x10] = {0}; if (src_size > sizeof(block) || dst_size > sizeof(block)) { @@ -346,7 +340,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, } /* Trigger AES operation. */ - se->BLOCK_COUNT_REG = 0; + se_get_regs()->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block)); /* Copy output data into dst. */ @@ -407,7 +401,6 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0x202); } - void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { volatile tegra_se_t *se = se_get_regs(); @@ -535,7 +528,6 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con se->CRYPTO_REG = (keyslot << 24) | (0x145); clear_aes_keyslot_iv(keyslot); - unsigned int num_blocks = (data_size + 0xF) >> 4; /* Handle aligned blocks. */ if (num_blocks > 1) { diff --git a/fusee/fusee-primary/src/se.h b/fusee/fusee-primary/src/se.h index db692b9cf..64998621a 100644 --- a/fusee/fusee-primary/src/se.h +++ b/fusee/fusee-primary/src/se.h @@ -34,6 +34,9 @@ #define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE #define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF +/* This keyslot was added in 5.0.0. */ +#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA + #define KEYSLOT_AES_MAX 0x10 #define KEYSLOT_RSA_MAX 0x2 @@ -88,7 +91,7 @@ #define RSA_2048_BYTES 0x100 -typedef struct security_engine { +typedef struct { uint32_t _0x0; uint32_t _0x4; uint32_t OPERATION_REG; @@ -170,8 +173,6 @@ static inline volatile tegra_se_t *se_get_regs(void) { return (volatile tegra_se_t *)SE_BASE; } -/* This function MUST be registered to fire on the appropriate interrupt. */ - void se_check_error_status_reg(void); void se_check_for_error(void); void se_trigger_interrupt(void); diff --git a/fusee/fusee-secondary/linker.ld b/fusee/fusee-secondary/linker.ld index 0d7538c12..68d127842 100644 --- a/fusee/fusee-secondary/linker.ld +++ b/fusee/fusee-secondary/linker.ld @@ -6,6 +6,7 @@ PHDRS { crt0 PT_LOAD; chainloader PT_LOAD; + nxboot PT_LOAD; main PT_LOAD; } @@ -13,16 +14,17 @@ PHDRS MEMORY { main : ORIGIN = 0xF0000000, LENGTH = 0x10000000 + high_iram : ORIGIN = 0x40010000, LENGTH = 0x20000 low_iram : ORIGIN = 0x40003000, LENGTH = 0x8000 } SECTIONS { PROVIDE(__start__ = 0xF0000000); - PROVIDE(__stack_top__ = 0x40010000); - PROVIDE(__stack_bottom__ = 0x4000C000); - PROVIDE(__heap_start__ = 0xE0000000); - PROVIDE(__heap_end__ = 0xF0000000); + PROVIDE(__stack_top__ = 0x90020000); + PROVIDE(__stack_bottom__ = 0x90010000); + PROVIDE(__heap_start__ = 0x90020000); + PROVIDE(__heap_end__ = 0xA0020000); . = __start__; @@ -53,6 +55,27 @@ SECTIONS . = ALIGN(32); PROVIDE (__chainloader_end__ = ABSOLUTE(.)); } >low_iram :NONE + + .nxboot_loadable : + { + . = ALIGN(32); + PROVIDE (__nxboot_start__ = ABSOLUTE(.)); + PROVIDE (__nxboot_lma__ = LOADADDR(.nxboot_loadable)); + KEEP(*(.nxboot.text.start)) + nxboot_iram.o(.text*) + nxboot_iram.o(.rodata*) + nxboot_iram.o(.data*) + . = ALIGN(32); + } >high_iram AT>main :nxboot + + .nxboot_bss (NOLOAD) : + { + . = ALIGN(32); + PROVIDE (__nxboot_bss_start__ = ABSOLUTE(.)); + nxboot_iram.o(.bss* COMMON) + . = ALIGN(32); + PROVIDE (__nxboot_end__ = ABSOLUTE(.)); + } >high_iram :NONE .text : { diff --git a/fusee/fusee-secondary/src/i2c.c b/fusee/fusee-secondary/src/i2c.c index 27063b3cd..aec946cf2 100644 --- a/fusee/fusee-secondary/src/i2c.c +++ b/fusee/fusee-secondary/src/i2c.c @@ -175,8 +175,7 @@ bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src i2c_load_config(regs); /* Config |= SEND; */ - regs->I2C_I2C_CNFG_0 |= 0x200; - + regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200); while (regs->I2C_I2C_STATUS_0 & 0x100) { /* Wait until not busy. */ @@ -203,8 +202,7 @@ bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_ i2c_load_config(regs); /* Config |= SEND; */ - regs->I2C_I2C_CNFG_0 |= 0x200; - + regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200); while (regs->I2C_I2C_STATUS_0 & 0x100) { /* Wait until not busy. */ diff --git a/fusee/fusee-secondary/src/i2c.h b/fusee/fusee-secondary/src/i2c.h index ec3efecc6..9399b0024 100644 --- a/fusee/fusee-secondary/src/i2c.h +++ b/fusee/fusee-secondary/src/i2c.h @@ -21,8 +21,8 @@ #include #include -#define I2C234_BASE 0x7000C000 -#define I2C56_BASE 0x7000D000 +#define I2C1234_BASE 0x7000C000 +#define I2C56_BASE 0x7000D000 #define I2C_1 0 #define I2C_2 1 @@ -82,10 +82,10 @@ typedef struct { uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0; } tegra_i2c_t; -#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x000)) -#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x400)) -#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x500)) -#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x700)) +#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x000)) +#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x400)) +#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x500)) +#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x700)) #define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000)) #define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100)) diff --git a/fusee/fusee-secondary/src/init.c b/fusee/fusee-secondary/src/init.c index c061fc00c..3f043b77e 100644 --- a/fusee/fusee-secondary/src/init.c +++ b/fusee/fusee-secondary/src/init.c @@ -51,8 +51,11 @@ static void __program_init_newlib_hooks(void) { static void __program_move_additional_sections(void) { #if defined(FUSEE_STAGE1_SRC) || defined(FUSEE_STAGE2_SRC) extern uint8_t __chainloader_lma__[], __chainloader_start__[], __chainloader_bss_start__[], __chainloader_end__[]; + extern uint8_t __nxboot_lma__[], __nxboot_start__[], __nxboot_bss_start__[], __nxboot_end__[]; memcpy(__chainloader_start__, __chainloader_lma__, __chainloader_bss_start__ - __chainloader_start__); memset(__chainloader_bss_start__, 0, __chainloader_end__ - __chainloader_bss_start__); + memcpy(__nxboot_start__, __nxboot_lma__, __nxboot_bss_start__ - __nxboot_start__); + memset(__nxboot_bss_start__, 0, __nxboot_end__ - __nxboot_bss_start__); #endif } diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index 5c9107cdb..5048bd642 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -102,7 +102,8 @@ int main(int argc, void **argv) { g_do_nxboot = loader_ctx->chainload_entrypoint == 0; if (g_do_nxboot) { printf("Now performing nxboot.\n"); - nxboot_main(); + uint32_t boot_memaddr = nxboot_main(); + nxboot_finish(boot_memaddr); } else { /* TODO: What else do we want to do in terms of argc/argv? */ const char *path = get_loader_ctx()->file_paths_to_load[get_loader_ctx()->file_id_of_entrypoint]; diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 47cf293b8..6f91206ab 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -185,9 +185,8 @@ static void nxboot_move_bootconfig() { /* This is the main function responsible for booting Horizon. */ static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32]; -void nxboot_main(void) { +uint32_t nxboot_main(void) { volatile tegra_pmc_t *pmc = pmc_get_regs(); - volatile tegra_se_t *se = se_get_regs(); loader_ctx_t *loader_ctx = get_loader_ctx(); package2_header_t *package2; size_t package2_size; @@ -397,43 +396,6 @@ void nxboot_main(void) { } free(package2); - /* Clear used keyslots. */ - clear_aes_keyslot(KEYSLOT_SWITCH_PACKAGE2KEY); - clear_aes_keyslot(KEYSLOT_SWITCH_RNGKEY); - - /* Lock keyslots. */ - set_aes_keyslot_flags(KEYSLOT_SWITCH_MASTERKEY, 0xFF); - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { - set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF); - } else { - set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF); - } - - /* Finalize the GPU UCODE carveout. */ - mc_config_carveout_finalize(); - - /* Lock AES keyslots. */ - for (uint32_t i = 0; i < 16; i++) - set_aes_keyslot_flags(i, 0x15); - - /* Lock RSA keyslots. */ - for (uint32_t i = 0; i < 2; i++) - set_rsa_keyslot_flags(i, 1); - - /* Lock the Security Engine. */ - se->_0x4 = 0; - se->AES_KEY_READ_DISABLE_REG = 0; - se->RSA_KEY_READ_DISABLE_REG = 0; - se->_0x0 &= 0xFFFFFFFB; - - /* Boot up Exosphère. */ - MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0; - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2; - } else { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X; - } - printf("[NXBOOT]: Powering on the CCPLEX...\n"); /* Display splash screen. */ @@ -442,26 +404,6 @@ void nxboot_main(void) { /* Unmount everything. */ nxfs_unmount_all(); - /* Terminate the display. */ - display_end(); - - /* Boot CPU0. */ - cluster_boot_cpu0((uint32_t)exosphere_memaddr); - - /* Wait for Exosphère to wake up. */ - while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) { - udelay(1); - } - - /* Signal Exosphère. */ - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED; - } else { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X; - } - - /* Halt ourselves in waitevent state. */ - while (1) { - FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000; - } + /* Return the memory address for booting CPU0. */ + return (uint32_t)exosphere_memaddr; } diff --git a/fusee/fusee-secondary/src/nxboot.h b/fusee/fusee-secondary/src/nxboot.h index 7559a20a9..6a042ea2a 100644 --- a/fusee/fusee-secondary/src/nxboot.h +++ b/fusee/fusee-secondary/src/nxboot.h @@ -43,6 +43,7 @@ typedef struct { uint32_t boot_reason_state; } boot_reason_t; -void nxboot_main(void); +uint32_t nxboot_main(void); +void nxboot_finish(uint32_t boot_memaddr); #endif diff --git a/fusee/fusee-secondary/src/nxboot_iram.c b/fusee/fusee-secondary/src/nxboot_iram.c new file mode 100644 index 000000000..5e0a0ee6c --- /dev/null +++ b/fusee/fusee-secondary/src/nxboot_iram.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "cluster.h" +#include "di.h" +#include "exocfg.h" +#include "flow.h" +#include "mc.h" +#include "nxboot.h" +#include "se.h" +#include "timers.h" + +void nxboot_finish(uint32_t boot_memaddr) { + volatile tegra_se_t *se = se_get_regs(); + + /* Clear used keyslots. */ + clear_aes_keyslot(KEYSLOT_SWITCH_PACKAGE2KEY); + clear_aes_keyslot(KEYSLOT_SWITCH_RNGKEY); + + /* Lock keyslots. */ + set_aes_keyslot_flags(KEYSLOT_SWITCH_MASTERKEY, 0xFF); + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF); + } else { + set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF); + } + + /* Finalize the GPU UCODE carveout. */ + mc_config_carveout_finalize(); + + /* Lock AES keyslots. */ + for (uint32_t i = 0; i < 16; i++) + set_aes_keyslot_flags(i, 0x15); + + /* Lock RSA keyslots. */ + for (uint32_t i = 0; i < 2; i++) + set_rsa_keyslot_flags(i, 1); + + /* Lock the Security Engine. */ + se->_0x4 = 0; + se->AES_KEY_READ_DISABLE_REG = 0; + se->RSA_KEY_READ_DISABLE_REG = 0; + se->_0x0 &= 0xFFFFFFFB; + + /* Boot up Exosphère. */ + MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0; + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2; + } else { + MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X; + } + + /* Terminate the display. */ + display_end(); + + /* Boot CPU0. */ + cluster_boot_cpu0(boot_memaddr); + + /* Wait for Exosphère to wake up. */ + while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) { + udelay(1); + } + + /* Signal Exosphère. */ + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED; + } else { + MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X; + } + + /* Halt ourselves in waitevent state. */ + while (1) { + FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000; + } +} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/se.c b/fusee/fusee-secondary/src/se.c index b466bd80b..d4dbdc498 100644 --- a/fusee/fusee-secondary/src/se.c +++ b/fusee/fusee-secondary/src/se.c @@ -39,8 +39,7 @@ void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) { } void se_check_error_status_reg(void) { - volatile tegra_se_t *se = se_get_regs(); - if (se->ERR_STATUS_REG) { + if (se_get_regs()->ERR_STATUS_REG) { generic_panic(); } } @@ -53,8 +52,7 @@ void se_check_for_error(void) { } void se_verify_flags_cleared(void) { - volatile tegra_se_t *se = se_get_regs(); - if (se->FLAGS_REG & 3) { + if (se_get_regs()->FLAGS_REG & 3) { generic_panic(); } } @@ -193,9 +191,8 @@ void clear_aes_keyslot_iv(unsigned int keyslot) { } void set_se_ctr(const void *ctr) { - volatile tegra_se_t *se = se_get_regs(); for (unsigned int i = 0; i < 4; i++) { - se->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); + se_get_regs()->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); } } @@ -237,7 +234,6 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co } void se_get_exp_mod_output(void *buf, size_t size) { - volatile tegra_se_t *se = se_get_regs(); size_t num_dwords = (size >> 2); if (num_dwords < 1) { @@ -249,7 +245,7 @@ void se_get_exp_mod_output(void *buf, size_t size) { /* Copy endian swapped output. */ while (num_dwords) { - *p_out = read32be(se->RSA_OUTPUT, offset); + *p_out = read32be(se_get_regs()->RSA_OUTPUT, offset); offset += 4; p_out--; num_dwords--; @@ -330,10 +326,8 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v se_check_for_error(); } - /* Secure AES Functionality. */ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) { - volatile tegra_se_t *se = se_get_regs(); uint8_t block[0x10] = {0}; if (src_size > sizeof(block) || dst_size > sizeof(block)) { @@ -346,7 +340,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, } /* Trigger AES operation. */ - se->BLOCK_COUNT_REG = 0; + se_get_regs()->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block)); /* Copy output data into dst. */ @@ -407,7 +401,6 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0x202); } - void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { volatile tegra_se_t *se = se_get_regs(); @@ -535,7 +528,6 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con se->CRYPTO_REG = (keyslot << 24) | (0x145); clear_aes_keyslot_iv(keyslot); - unsigned int num_blocks = (data_size + 0xF) >> 4; /* Handle aligned blocks. */ if (num_blocks > 1) { diff --git a/fusee/fusee-secondary/src/se.h b/fusee/fusee-secondary/src/se.h index db692b9cf..64998621a 100644 --- a/fusee/fusee-secondary/src/se.h +++ b/fusee/fusee-secondary/src/se.h @@ -34,6 +34,9 @@ #define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE #define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF +/* This keyslot was added in 5.0.0. */ +#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA + #define KEYSLOT_AES_MAX 0x10 #define KEYSLOT_RSA_MAX 0x2 @@ -88,7 +91,7 @@ #define RSA_2048_BYTES 0x100 -typedef struct security_engine { +typedef struct { uint32_t _0x0; uint32_t _0x4; uint32_t OPERATION_REG; @@ -170,8 +173,6 @@ static inline volatile tegra_se_t *se_get_regs(void) { return (volatile tegra_se_t *)SE_BASE; } -/* This function MUST be registered to fire on the appropriate interrupt. */ - void se_check_error_status_reg(void); void se_check_for_error(void); void se_trigger_interrupt(void); diff --git a/fusee/fusee-secondary/src/splash_screen.c b/fusee/fusee-secondary/src/splash_screen.c index dd5085d79..172516c90 100644 --- a/fusee/fusee-secondary/src/splash_screen.c +++ b/fusee/fusee-secondary/src/splash_screen.c @@ -31,5 +31,5 @@ void display_splash_screen_bmp(const char *custom_splash_path) { /* TODO: Display the splash screen. It should be a pointer to a BMP, at this point. */ /* Display the splash screen for three seconds. */ - /* udelay(3000000); */ + udelay(3000000); } diff --git a/fusee/fusee-secondary/src/start.s b/fusee/fusee-secondary/src/start.s index e417cd80e..fcad0f23d 100644 --- a/fusee/fusee-secondary/src/start.s +++ b/fusee/fusee-secondary/src/start.s @@ -70,3 +70,12 @@ _start: relocate_and_chainload: ldr sp, =__stack_top__ b relocate_and_chainload_main + +.section .nxboot.text.start, "ax", %progbits +.arm +.align 5 +.global nxboot +.type nxboot, %function +nxboot: + ldr sp, =__stack_top__ + b nxboot_finish \ No newline at end of file