Implement more SE context save functionality

This commit is contained in:
Michael Scire 2018-02-27 17:40:47 -08:00
parent 93634d08e3
commit a8a2f8c3f6
3 changed files with 69 additions and 7 deletions

View file

@ -60,7 +60,7 @@ void save_se_and_power_down_cpu(void) {
uint8_t *se_state_dst = (uint8_t *)(WARMBOOT_GET_RAM_SEGMENT_ADDRESS(WARMBOOT_RAM_SEGMENT_ID_SE_STATE));
se_check_error_status_reg();
se_set_in_context_save_mode(true);
se_save_context(KEYSLOT_SWITCH_SRKKEY, KEYSLOT_SWITCH_RNGKEY, se_state_dst);
se_save_context(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY, se_state_dst);
flush_dcache_range(se_state_dst, se_state_dst + 0x840);
APBDEV_PMC_SCRATCH43_0 = (uint32_t)(WARMBOOT_GET_RAM_SEGMENT_PA(WARMBOOT_RAM_SEGMENT_ID_SE_STATE));
se_set_in_context_save_mode(false);

View file

@ -534,7 +534,15 @@ 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) {
/* TODO */
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;
set_aes_keyslot_iv(keyslot, iv, 0x10);
SECURITY_ENGINE->BLOCK_COUNT_REG = (src_size >> 4) - 1;
trigger_se_blocking_op(1, dst, dst_size, src, src_size);
}
/* SHA256 Implementation. */
@ -603,13 +611,67 @@ void se_generate_random(unsigned int keyslot, void *dst, size_t size) {
/* SE context save API. */
void se_set_in_context_save_mode(bool is_context_save_mode) {
/* TODO */
uint32_t val = SECURITY_ENGINE->_0x0;
if (is_context_save_mode) {
val |= 0x10000;
} else {
val &= 0xFFFEFFFF;
}
SECURITY_ENGINE->_0x0 = val;
/* Perform a useless read from flags reg. */
(void)(SECURITY_ENGINE->FLAGS_REG);
}
void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot) {
/* TODO */
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;
/* Generate low part of key. */
SECURITY_ENGINE->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8);
trigger_se_blocking_op(1, NULL, 0, NULL, 0);
/* Generate high part of key. */
SECURITY_ENGINE->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8) | 1;
trigger_se_blocking_op(1, NULL, 0, NULL, 0);
}
void se_save_context(unsigned int srk_keyslot, unsigned int rng_keyslot, void *dst) {
/* TODO */
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;
trigger_se_blocking_op(1, 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 (src_size) {
flush_dcache_range((uint8_t *)src, (uint8_t *)src + src_size);
}
if (dst_size) {
flush_dcache_range(aligned_out, aligned_out + 0x10);
trigger_se_blocking_op(3, aligned_out, dst_size, src, src_size);
flush_dcache_range(aligned_out, aligned_out + 0x10);
memcpy(dst, aligned_out, dst_size);
} else {
trigger_se_blocking_op(3, aligned_out, 0, src, src_size);
}
}
void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void *dst) {
/* Generate the SRK (context save encryption key). */
se_generate_random_key(srkgen_keyslot, rng_keyslot);
se_generate_srk(srkgen_keyslot);
/* TODO: Encrypt SE context with SRK. */
}

View file

@ -10,7 +10,7 @@
/* Exosphere driver for the Tegra X1 security engine. */
#define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2
#define KEYSLOT_SWITCH_SRKKEY 0x8
#define KEYSLOT_SWITCH_SRKGENKEY 0x8
#define KEYSLOT_SWITCH_PACKAGE2KEY 0x8
#define KEYSLOT_SWITCH_TEMPKEY 0x9
#define KEYSLOT_SWITCH_SESSIONKEY 0xA