Rewrite the memory map-related code...

...other style fixes, etc.
This commit is contained in:
TuxSH
2018-02-26 22:09:35 +01:00
parent bda9dcbe73
commit c7d83c6eb6
26 changed files with 603 additions and 442 deletions

View File

@@ -7,9 +7,6 @@
#include "cache.h"
#include "se.h"
/* Macro for the SE registers. */
#define SECURITY_ENGINE ((volatile security_engine_t *)(mmio_get_device_address(MMIO_DEVID_SE)))
void trigger_se_rsa_op(void *buf, size_t size);
void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size);
@@ -23,7 +20,7 @@ static unsigned int g_se_exp_sizes[KEYSLOT_RSA_MAX];
/* Initialize a SE linked list. */
void ll_init(se_ll_t *ll, void *buffer, size_t size) {
ll->num_entries = 0; /* 1 Entry. */
if (buffer != NULL) {
ll->addr_info.address = (uint32_t) get_physical_address(buffer);
ll->addr_info.size = (uint32_t) size;
@@ -39,7 +36,7 @@ void set_security_engine_callback(unsigned int (*callback)(void)) {
if (callback == NULL || g_se_callback != NULL) {
generic_panic();
}
g_se_callback = callback;
}
@@ -78,12 +75,12 @@ void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) {
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
/* Misc flags. */
if (flags & ~0x80) {
SECURITY_ENGINE->AES_KEYSLOT_FLAGS[keyslot] = ~flags;
}
/* Disable keyslot reads. */
if (flags & 0x80) {
SECURITY_ENGINE->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot);
@@ -95,13 +92,13 @@ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) {
if (keyslot >= KEYSLOT_RSA_MAX) {
generic_panic();
}
/* Misc flags. */
if (flags & ~0x80) {
/* TODO: Why are flags assigned this way? */
SECURITY_ENGINE->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);
@@ -112,7 +109,7 @@ void clear_aes_keyslot(unsigned int keyslot) {
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;
@@ -124,7 +121,7 @@ void clear_rsa_keyslot(unsigned int keyslot) {
if (keyslot >= KEYSLOT_RSA_MAX) {
generic_panic();
}
/* Zero out the whole keyslot. */
for (unsigned int i = 0; i < 0x40; i++) {
/* Select Keyslot Modulus[i] */
@@ -142,7 +139,7 @@ void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) {
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);
@@ -153,17 +150,17 @@ void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_
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 * i);
}
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 * i);
}
g_se_modulus_sizes[keyslot] = modulus_size;
g_se_exp_sizes[keyslot] = exp_size;
}
@@ -172,7 +169,7 @@ void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) {
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);
@@ -183,7 +180,7 @@ void clear_aes_keyslot_iv(unsigned int keyslot) {
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
for (size_t i = 0; i < (0x10 >> 2); i++) {
SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | 8;
SECURITY_ENGINE->AES_KEYTABLE_DATA = 0;
@@ -200,7 +197,7 @@ void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_sr
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;
@@ -214,11 +211,11 @@ void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr,
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
if (size == 0) {
return;
}
/* Setup Config register. */
if (encrypt) {
SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY);
@@ -249,7 +246,7 @@ void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr,
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;
/* Ensure writes go through. */
__asm__ __volatile__ ("dsb ish" : : : "memory");
}
@@ -266,7 +263,7 @@ void se_aes_cbc_encrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, ui
se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x44, true, callback);
}
void se_aes_cbc_decrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *iv, unsigned int (*callback)(void)) {
void se_aes_cbc_decrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *iv, unsigned int (*callback)(void)) {
set_aes_keyslot_iv(keyslot, iv, 0x10);
se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x66, false, callback);
}
@@ -274,16 +271,16 @@ void se_aes_cbc_decrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, ui
void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*callback)(void)) {
uint8_t stack_buf[KEYSIZE_RSA_MAX];
if (keyslot >= KEYSLOT_RSA_MAX || size > KEYSIZE_RSA_MAX) {
generic_panic();
}
/* Endian swap the input. */
for (size_t i = size; i > 0; i--) {
stack_buf[i] = *((uint8_t *)buf + size - i);
}
SECURITY_ENGINE->CONFIG_REG = (ALG_RSA | DST_RSAREG);
SECURITY_ENGINE->RSA_CONFIG = keyslot << 24;
@@ -291,7 +288,7 @@ void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*cal
SECURITY_ENGINE->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;
@@ -303,7 +300,7 @@ void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*cal
void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
uint8_t stack_buf[KEYSIZE_RSA_MAX];
if (keyslot >= KEYSLOT_RSA_MAX || src_size > KEYSIZE_RSA_MAX || dst_size > KEYSIZE_RSA_MAX) {
generic_panic();
}
@@ -312,13 +309,13 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co
for (size_t i = src_size; i > 0; i--) {
stack_buf[i] = *((uint8_t *)src + src_size - i);
}
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;
flush_dcache_range(stack_buf, stack_buf + KEYSIZE_RSA_MAX);
trigger_se_blocking_op(1, NULL, 0, stack_buf, src_size);
se_get_exp_mod_output(dst, dst_size);
@@ -329,10 +326,10 @@ void se_get_exp_mod_output(void *buf, size_t size) {
if (num_dwords < 1) {
return;
}
uint32_t *p_out = ((uint32_t *)buf) + num_dwords - 1;
uint32_t offset = 0;
/* Copy endian swapped output. */
while (num_dwords) {
*p_out = read32be(SECURITY_ENGINE->RSA_OUTPUT, offset);
@@ -347,13 +344,13 @@ void trigger_se_rsa_op(void *buf, size_t size) {
ll_init(&in_ll, (void *)buf, size);
/* Set the input LL. */
SECURITY_ENGINE->IN_LL_ADDR_REG = get_physical_address(&in_ll);
SECURITY_ENGINE->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;
/* Ensure writes go through. */
__asm__ __volatile__ ("dsb ish" : : : "memory");
}
@@ -361,19 +358,19 @@ void trigger_se_rsa_op(void *buf, size_t size) {
void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size) {
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. */
SECURITY_ENGINE->IN_LL_ADDR_REG = get_physical_address(&in_ll);
SECURITY_ENGINE->OUT_LL_ADDR_REG = get_physical_address(&out_ll);
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);
/* 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;
while (!(SECURITY_ENGINE->INT_STATUS_REG & 0x10)) { /* Wait a while */ }
se_check_for_error();
}
@@ -394,7 +391,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src,
/* Trigger AES operation. */
SECURITY_ENGINE->BLOCK_COUNT_REG = 0;
trigger_se_blocking_op(1, block, sizeof(block), block, sizeof(block));
/* Copy output data into dst. */
flush_dcache_range(block, block + sizeof(block));
memcpy(dst, block, dst_size);
@@ -404,22 +401,22 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo
if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) {
generic_panic();
}
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;
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;
trigger_se_blocking_op(1, dst, dst_size, src, aligned_size);
}
/* Handle final, unaligned block. */
if (aligned_size < dst_size && aligned_size < src_size) {
size_t last_block_size = dst_size - aligned_size;
@@ -434,7 +431,7 @@ void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size,
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;
@@ -455,7 +452,7 @@ void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size,
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_perform_aes_block_operation(dst, 0x10, src, 0x10);
@@ -466,7 +463,7 @@ void shift_left_xor_rb(uint8_t *key) {
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;
prev_high_bit = cur_byte >> 7;
}
if (prev_high_bit) {
key[0xF] ^= 0x87;
@@ -477,7 +474,7 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
/* Generate the derived key, to be XOR'd with final output block. */
uint8_t derived_key[0x10];
memset(derived_key, 0, sizeof(derived_key));
@@ -486,11 +483,11 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
if (data_size & 0xF) {
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);
clear_aes_keyslot_iv(keyslot);
unsigned int num_blocks = (data_size + 0xF) >> 4;
/* Handle aligned blocks. */
if (num_blocks > 1) {
@@ -498,26 +495,26 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
trigger_se_blocking_op(1, NULL, 0, data, data_size);
SECURITY_ENGINE->CRYPTO_REG |= 0x80;
}
/* Create final block. */
uint8_t last_block[0x10];
memset(last_block, 0, sizeof(last_block));
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. */
flush_dcache_range(last_block, last_block + sizeof(last_block));
trigger_se_blocking_op(1, 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);
@@ -544,10 +541,10 @@ void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
SECURITY_ENGINE->_0x21C = 0;
SECURITY_ENGINE->_0x220 = 0;
SECURITY_ENGINE->_0x224 = 0;
/* Trigger the operation. */
trigger_se_blocking_op(1, 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);
@@ -559,11 +556,11 @@ void se_initialize_rng(unsigned int keyslot) {
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
/* To initialize the RNG, we'll perform an RNG operation into an output buffer. */
/* 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);
@@ -577,13 +574,13 @@ void se_generate_random(unsigned int keyslot, void *dst, size_t size) {
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;
if (num_blocks >= 1) {
SECURITY_ENGINE->BLOCK_COUNT_REG = num_blocks - 1;
trigger_se_blocking_op(1, dst, aligned_size, NULL, 0);