mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-17 17:36:44 +00:00
warmboot: start secmon_restore_to_tzram
This commit is contained in:
parent
4f9ecc9d50
commit
3924a2ef76
5 changed files with 520 additions and 3 deletions
|
@ -25,6 +25,7 @@
|
||||||
#include "cluster.h"
|
#include "cluster.h"
|
||||||
#include "flow.h"
|
#include "flow.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
#include "secmon.h"
|
||||||
|
|
||||||
void reboot(void) {
|
void reboot(void) {
|
||||||
/* Write MAIN_RST */
|
/* Write MAIN_RST */
|
||||||
|
@ -81,7 +82,7 @@ void lp0_entry_main(warmboot_metadata_t *meta) {
|
||||||
/* Initialize the CPU cluster. */
|
/* Initialize the CPU cluster. */
|
||||||
cluster_initialize_cpu();
|
cluster_initialize_cpu();
|
||||||
|
|
||||||
/* TODO: decrypt_restore_secmon_to_tzram(); */
|
secmon_restore_to_tzram(target_firmware);
|
||||||
|
|
||||||
/* Power on the CPU cluster. */
|
/* Power on the CPU cluster. */
|
||||||
cluster_power_on_cpu();
|
cluster_power_on_cpu();
|
||||||
|
@ -95,5 +96,3 @@ void lp0_entry_main(warmboot_metadata_t *meta) {
|
||||||
FLOW_CTLR_HALT_COP_EVENTS_0 = halt_val;
|
FLOW_CTLR_HALT_COP_EVENTS_0 = halt_val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
238
exosphere/lp0fw/src/se.c
Normal file
238
exosphere/lp0fw/src/se.c
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#include "lp0.h"
|
||||||
|
#include "se.h"
|
||||||
|
|
||||||
|
static void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||||
|
|
||||||
|
/* Initialize a SE linked list. */
|
||||||
|
static void __attribute__((__noinline__)) ll_init(volatile se_ll_t *ll, void *buffer, size_t size) {
|
||||||
|
ll->num_entries = 0; /* 1 Entry. */
|
||||||
|
|
||||||
|
if (buffer != NULL) {
|
||||||
|
ll->addr_info.address = (uint32_t) buffer;
|
||||||
|
ll->addr_info.size = (uint32_t) size;
|
||||||
|
} else {
|
||||||
|
ll->addr_info.address = 0;
|
||||||
|
ll->addr_info.size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void se_check_error_status_reg(void) {
|
||||||
|
if (se_get_regs()->ERR_STATUS_REG) {
|
||||||
|
reboot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void se_check_for_error(void) {
|
||||||
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
if (se->INT_STATUS_REG & 0x10000 || se->FLAGS_REG & 3 || se->ERR_STATUS_REG) {
|
||||||
|
reboot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void se_verify_flags_cleared(void) {
|
||||||
|
if (se_get_regs()->FLAGS_REG & 3) {
|
||||||
|
reboot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_aes_keyslot(unsigned int keyslot) {
|
||||||
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
|
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||||
|
reboot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zero out the whole keyslot and IV. */
|
||||||
|
for (unsigned int i = 0; i < 0x10; i++) {
|
||||||
|
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) {
|
||||||
|
reboot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zero out the whole keyslot. */
|
||||||
|
for (unsigned int i = 0; i < 0x40; i++) {
|
||||||
|
/* Select Keyslot Modulus[i] */
|
||||||
|
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] */
|
||||||
|
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||||
|
se->RSA_KEYTABLE_DATA = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_aes_keyslot_iv(unsigned int keyslot) {
|
||||||
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
|
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||||
|
reboot();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < (0x10 >> 2); i++) {
|
||||||
|
se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||||
|
se->AES_KEYTABLE_DATA = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
ll_init(&in_ll, (void *)src, src_size);
|
||||||
|
ll_init(&out_ll, dst, dst_size);
|
||||||
|
|
||||||
|
/* Set the LLs. */
|
||||||
|
se->IN_LL_ADDR_REG = (uint32_t)(&in_ll);
|
||||||
|
se->OUT_LL_ADDR_REG = (uint32_t) (&out_ll);
|
||||||
|
|
||||||
|
/* Set registers for operation. */
|
||||||
|
se->ERR_STATUS_REG = se->ERR_STATUS_REG;
|
||||||
|
se->INT_STATUS_REG = se->INT_STATUS_REG;
|
||||||
|
se->OPERATION_REG = op;
|
||||||
|
|
||||||
|
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};
|
||||||
|
|
||||||
|
if (src_size > sizeof(block) || dst_size > sizeof(block)) {
|
||||||
|
reboot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load src data into block. */
|
||||||
|
if (src_size != 0) {
|
||||||
|
memcpy(block, src, src_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Trigger AES operation. */
|
||||||
|
se_get_regs()->BLOCK_COUNT_REG = 0;
|
||||||
|
trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block));
|
||||||
|
|
||||||
|
/* Copy output data into dst. */
|
||||||
|
if (dst_size != 0) {
|
||||||
|
memcpy(dst, block, dst_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
reboot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set configuration high (256-bit vs 128-bit) based on parameter. */
|
||||||
|
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16);
|
||||||
|
se->CRYPTO_REG = keyslot << 24 | 0x100;
|
||||||
|
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
reboot();
|
||||||
|
}
|
||||||
|
|
||||||
|
se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY);
|
||||||
|
se->CRYPTO_REG = keyslot << 24;
|
||||||
|
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shift_left_xor_rb(uint8_t *key) {
|
||||||
|
uint8_t prev_high_bit = 0;
|
||||||
|
for (unsigned int i = 0; i < 0x10; i++) {
|
||||||
|
uint8_t cur_byte = key[0xF - i];
|
||||||
|
key[0xF - i] = (cur_byte << 1) | (prev_high_bit);
|
||||||
|
prev_high_bit = cur_byte >> 7;
|
||||||
|
}
|
||||||
|
if (prev_high_bit) {
|
||||||
|
key[0xF] ^= 0x87;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
reboot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate the derived key, to be XOR'd with final output block. */
|
||||||
|
uint8_t ALIGN(16) derived_key[0x10] = {0};
|
||||||
|
se_aes_ecb_encrypt_block(keyslot, derived_key, sizeof(derived_key), derived_key, sizeof(derived_key), config_high);
|
||||||
|
shift_left_xor_rb(derived_key);
|
||||||
|
if (data_size & 0xF) {
|
||||||
|
shift_left_xor_rb(derived_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
se->BLOCK_COUNT_REG = num_blocks - 2;
|
||||||
|
trigger_se_blocking_op(OP_START, NULL, 0, data, data_size);
|
||||||
|
se->CRYPTO_REG |= 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create final block. */
|
||||||
|
uint8_t ALIGN(16) last_block[0x10] = {0};
|
||||||
|
if (data_size & 0xF) {
|
||||||
|
memcpy(last_block, data + (data_size & ~0xF), data_size & 0xF);
|
||||||
|
last_block[data_size & 0xF] = 0x80; /* Last block = data || 100...0 */
|
||||||
|
} else if (data_size >= 0x10) {
|
||||||
|
memcpy(last_block, data + data_size - 0x10, 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < 0x10; i++) {
|
||||||
|
last_block[i] ^= derived_key[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform last operation. */
|
||||||
|
se->BLOCK_COUNT_REG = 0;
|
||||||
|
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] = ((volatile uint32_t *)se->HASH_RESULT_REG)[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) {
|
||||||
|
se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0x202);
|
||||||
|
}
|
187
exosphere/lp0fw/src/se.h
Normal file
187
exosphere/lp0fw/src/se.h
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXOSPHERE_WARMBOOT_BIN_SE_H
|
||||||
|
#define EXOSPHERE_WARMBOOT_BIN_SE_H
|
||||||
|
|
||||||
|
#define SE_BASE 0x70012000
|
||||||
|
#define MAKE_SE_REG(n) MAKE_REG32(SE_BASE + n)
|
||||||
|
|
||||||
|
#define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2
|
||||||
|
#define KEYSLOT_SWITCH_SRKGENKEY 0x8
|
||||||
|
#define KEYSLOT_SWITCH_PACKAGE2KEY 0x8
|
||||||
|
#define KEYSLOT_SWITCH_TEMPKEY 0x9
|
||||||
|
#define KEYSLOT_SWITCH_SESSIONKEY 0xA
|
||||||
|
#define KEYSLOT_SWITCH_RNGKEY 0xB
|
||||||
|
#define KEYSLOT_SWITCH_MASTERKEY 0xC
|
||||||
|
#define KEYSLOT_SWITCH_DEVICEKEY 0xD
|
||||||
|
|
||||||
|
/* This keyslot was added in 4.0.0. */
|
||||||
|
#define KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY 0xD
|
||||||
|
#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
|
||||||
|
|
||||||
|
#define KEYSIZE_AES_MAX 0x20
|
||||||
|
#define KEYSIZE_RSA_MAX 0x100
|
||||||
|
|
||||||
|
#define ALG_SHIFT (12)
|
||||||
|
#define ALG_DEC_SHIFT (8)
|
||||||
|
#define ALG_NOP (0 << ALG_SHIFT)
|
||||||
|
#define ALG_AES_ENC (1 << ALG_SHIFT)
|
||||||
|
#define ALG_AES_DEC ((1 << ALG_DEC_SHIFT) | ALG_NOP)
|
||||||
|
#define ALG_RNG (2 << ALG_SHIFT)
|
||||||
|
#define ALG_SHA (3 << ALG_SHIFT)
|
||||||
|
#define ALG_RSA (4 << ALG_SHIFT)
|
||||||
|
|
||||||
|
#define DST_SHIFT (2)
|
||||||
|
#define DST_MEMORY (0 << DST_SHIFT)
|
||||||
|
#define DST_HASHREG (1 << DST_SHIFT)
|
||||||
|
#define DST_KEYTAB (2 << DST_SHIFT)
|
||||||
|
#define DST_SRK (3 << DST_SHIFT)
|
||||||
|
#define DST_RSAREG (4 << DST_SHIFT)
|
||||||
|
|
||||||
|
#define ENCMODE_SHIFT (24)
|
||||||
|
#define DECMODE_SHIFT (16)
|
||||||
|
#define ENCMODE_SHA256 (5 << ENCMODE_SHIFT)
|
||||||
|
|
||||||
|
#define HASH_DISABLE (0x0)
|
||||||
|
#define HASH_ENABLE (0x1)
|
||||||
|
|
||||||
|
#define OP_ABORT 0
|
||||||
|
#define OP_START 1
|
||||||
|
#define OP_RESTART 2
|
||||||
|
#define OP_CTX_SAVE 3
|
||||||
|
#define OP_RESTART_IN 4
|
||||||
|
|
||||||
|
#define CTX_SAVE_SRC_SHIFT 29
|
||||||
|
#define CTX_SAVE_SRC_STICKY_BITS (0 << CTX_SAVE_SRC_SHIFT)
|
||||||
|
#define CTX_SAVE_SRC_KEYTABLE_AES (2 << CTX_SAVE_SRC_SHIFT)
|
||||||
|
#define CTX_SAVE_SRC_KEYTABLE_RSA (1 << CTX_SAVE_SRC_SHIFT)
|
||||||
|
#define CTX_SAVE_SRC_MEM (4 << CTX_SAVE_SRC_SHIFT)
|
||||||
|
#define CTX_SAVE_SRC_SRK (6 << CTX_SAVE_SRC_SHIFT)
|
||||||
|
|
||||||
|
#define CTX_SAVE_KEY_LOW_BITS 0
|
||||||
|
#define CTX_SAVE_KEY_HIGH_BITS 1
|
||||||
|
#define CTX_SAVE_KEY_ORIGINAL_IV 2
|
||||||
|
#define CTX_SAVE_KEY_UPDATED_IV 3
|
||||||
|
|
||||||
|
#define CTX_SAVE_STICKY_BIT_INDEX_SHIFT 24
|
||||||
|
#define CTX_SAVE_KEY_INDEX_SHIFT 8
|
||||||
|
#define CTX_SAVE_RSA_KEY_INDEX_SHIFT 16
|
||||||
|
#define CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT 12
|
||||||
|
|
||||||
|
#define RSA_2048_BYTES 0x100
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t _0x0;
|
||||||
|
uint32_t _0x4;
|
||||||
|
uint32_t OPERATION_REG;
|
||||||
|
uint32_t INT_ENABLE_REG;
|
||||||
|
uint32_t INT_STATUS_REG;
|
||||||
|
uint32_t CONFIG_REG;
|
||||||
|
uint32_t IN_LL_ADDR_REG;
|
||||||
|
uint32_t _0x1C;
|
||||||
|
uint32_t _0x20;
|
||||||
|
uint32_t OUT_LL_ADDR_REG;
|
||||||
|
uint32_t _0x28;
|
||||||
|
uint32_t _0x2C;
|
||||||
|
uint8_t HASH_RESULT_REG[0x20];
|
||||||
|
uint8_t _0x50[0x20];
|
||||||
|
uint32_t CONTEXT_SAVE_CONFIG_REG;
|
||||||
|
uint8_t _0x74[0x18C];
|
||||||
|
uint32_t SHA_CONFIG_REG;
|
||||||
|
uint32_t SHA_MSG_LENGTH_REG;
|
||||||
|
uint32_t _0x208;
|
||||||
|
uint32_t _0x20C;
|
||||||
|
uint32_t _0x210;
|
||||||
|
uint32_t SHA_MSG_LEFT_REG;
|
||||||
|
uint32_t _0x218;
|
||||||
|
uint32_t _0x21C;
|
||||||
|
uint32_t _0x220;
|
||||||
|
uint32_t _0x224;
|
||||||
|
uint8_t _0x228[0x58];
|
||||||
|
uint32_t AES_KEY_READ_DISABLE_REG;
|
||||||
|
uint32_t AES_KEYSLOT_FLAGS[0x10];
|
||||||
|
uint8_t _0x2C4[0x3C];
|
||||||
|
uint32_t _0x300;
|
||||||
|
uint32_t CRYPTO_REG;
|
||||||
|
uint32_t CRYPTO_CTR_REG[4];
|
||||||
|
uint32_t BLOCK_COUNT_REG;
|
||||||
|
uint32_t AES_KEYTABLE_ADDR;
|
||||||
|
uint32_t AES_KEYTABLE_DATA;
|
||||||
|
uint32_t _0x324;
|
||||||
|
uint32_t _0x328;
|
||||||
|
uint32_t _0x32C;
|
||||||
|
uint32_t CRYPTO_KEYTABLE_DST_REG;
|
||||||
|
uint8_t _0x334[0xC];
|
||||||
|
uint32_t RNG_CONFIG_REG;
|
||||||
|
uint32_t RNG_SRC_CONFIG_REG;
|
||||||
|
uint32_t RNG_RESEED_INTERVAL_REG;
|
||||||
|
uint8_t _0x34C[0xB4];
|
||||||
|
uint32_t RSA_CONFIG;
|
||||||
|
uint32_t RSA_KEY_SIZE_REG;
|
||||||
|
uint32_t RSA_EXP_SIZE_REG;
|
||||||
|
uint32_t RSA_KEY_READ_DISABLE_REG;
|
||||||
|
uint32_t RSA_KEYSLOT_FLAGS[2];
|
||||||
|
uint32_t _0x418;
|
||||||
|
uint32_t _0x41C;
|
||||||
|
uint32_t RSA_KEYTABLE_ADDR;
|
||||||
|
uint32_t RSA_KEYTABLE_DATA;
|
||||||
|
uint8_t RSA_OUTPUT[0x100];
|
||||||
|
uint8_t _0x528[0x2D8];
|
||||||
|
uint32_t FLAGS_REG;
|
||||||
|
uint32_t ERR_STATUS_REG;
|
||||||
|
uint32_t _0x808;
|
||||||
|
uint32_t SPARE_0;
|
||||||
|
uint32_t _0x810;
|
||||||
|
uint32_t _0x814;
|
||||||
|
uint32_t _0x818;
|
||||||
|
uint32_t _0x81C;
|
||||||
|
uint8_t _0x820[0x17E0];
|
||||||
|
} tegra_se_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t address;
|
||||||
|
uint32_t size;
|
||||||
|
} se_addr_info_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t num_entries; /* Set to total entries - 1 */
|
||||||
|
se_addr_info_t addr_info; /* This should really be an array...but for our use case it works. */
|
||||||
|
} se_ll_t;
|
||||||
|
|
||||||
|
static inline volatile tegra_se_t *se_get_regs(void) {
|
||||||
|
return (volatile tegra_se_t *)SE_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void se_check_error_status_reg(void);
|
||||||
|
void se_check_for_error(void);
|
||||||
|
|
||||||
|
void se_verify_flags_cleared(void);
|
||||||
|
|
||||||
|
void clear_aes_keyslot(unsigned int keyslot);
|
||||||
|
void clear_rsa_keyslot(unsigned int keyslot);
|
||||||
|
void clear_aes_keyslot_iv(unsigned int keyslot);
|
||||||
|
|
||||||
|
void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size);
|
||||||
|
|
||||||
|
#endif
|
67
exosphere/lp0fw/src/secmon.c
Normal file
67
exosphere/lp0fw/src/secmon.c
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#include "lp0.h"
|
||||||
|
#include "secmon.h"
|
||||||
|
#include "se.h"
|
||||||
|
#include "pmc.h"
|
||||||
|
|
||||||
|
/* "private" functions. */
|
||||||
|
static bool secmon_should_clear_aes_keyslot(unsigned int keyslot);
|
||||||
|
static void secmon_clear_unused_keyslots(void);
|
||||||
|
|
||||||
|
void secmon_restore_to_tzram(const uint32_t target_firmware) {
|
||||||
|
/* Newer warmboot binaries clear the untouched keyslots for safety. */
|
||||||
|
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_500) {
|
||||||
|
secmon_clear_unused_keyslots();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: stuff */
|
||||||
|
}
|
||||||
|
|
||||||
|
bool secmon_should_clear_aes_keyslot(unsigned int keyslot) {
|
||||||
|
static const uint8_t saved_keyslots[6] = {
|
||||||
|
KEYSLOT_SWITCH_LP0TZRAMKEY,
|
||||||
|
KEYSLOT_SWITCH_SESSIONKEY,
|
||||||
|
KEYSLOT_SWITCH_RNGKEY,
|
||||||
|
KEYSLOT_SWITCH_MASTERKEY,
|
||||||
|
KEYSLOT_SWITCH_DEVICEKEY,
|
||||||
|
KEYSLOT_SWITCH_4XOLDDEVICEKEY
|
||||||
|
};
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < sizeof(saved_keyslots)/sizeof(saved_keyslots[0]); i++) {
|
||||||
|
if (keyslot == saved_keyslots[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void secmon_clear_unused_keyslots(void) {
|
||||||
|
/* Clear unused keyslots. */
|
||||||
|
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
|
||||||
|
if (secmon_should_clear_aes_keyslot(i)) {
|
||||||
|
clear_aes_keyslot(i);
|
||||||
|
}
|
||||||
|
clear_aes_keyslot_iv(i);
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < KEYSLOT_RSA_MAX; i++) {
|
||||||
|
clear_rsa_keyslot(i);
|
||||||
|
}
|
||||||
|
}
|
26
exosphere/lp0fw/src/secmon.h
Normal file
26
exosphere/lp0fw/src/secmon.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXOSPHERE_WARMBOOT_BIN_SECMON_H
|
||||||
|
#define EXOSPHERE_WARMBOOT_BIN_SECMON_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
void secmon_restore_to_tzram(const uint32_t target_firmware);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue