Change argument types in se.c/h, implement read32le/be, etc.

This commit is contained in:
TuxSH 2018-02-19 00:02:37 +01:00
parent 9c588d4965
commit f629a629d1
5 changed files with 60 additions and 53 deletions

2
.gitignore vendored
View file

@ -50,3 +50,5 @@ modules.order
Module.symvers Module.symvers
Mkfile.old Mkfile.old
dkms.conf dkms.conf
.*/

View file

@ -1,10 +1,9 @@
#include <stdint.h>
#include "utils.h" #include "utils.h"
#include "cache.h"
#include "se.h" #include "se.h"
void trigger_se_rsa_op(void *buf, unsigned int size); void trigger_se_rsa_op(void *buf, size_t size);
void trigger_se_aes_op(unsigned int op, char *dst, unsigned int dst_size, const unsigned char *src, unsigned int src_size); void trigger_se_aes_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size);
/* Globals for driver. */ /* Globals for driver. */
volatile security_engine_t *g_security_engine; volatile security_engine_t *g_security_engine;
@ -97,30 +96,30 @@ void clear_rsa_keyslot(unsigned int keyslot) {
} }
} }
void set_aes_keyslot(unsigned int keyslot, const unsigned char *key, unsigned int key_size) { void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) {
if (g_security_engine == NULL || keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) { if (g_security_engine == NULL || keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) {
panic(); panic();
} }
for (unsigned int i = 0; i < (key_size >> 2); i++) { for (size_t i = 0; i < (key_size >> 2); i++) {
g_security_engine->AES_KEYTABLE_ADDR = (keyslot << 4) | i; g_security_engine->AES_KEYTABLE_ADDR = (keyslot << 4) | i;
g_security_engine->AES_KEYTABLE_DATA = read32le(key, 4 * i); g_security_engine->AES_KEYTABLE_DATA = read32le(key, 4 * i);
} }
} }
void set_rsa_keyslot(unsigned int keyslot, const unsigned char *modulus, unsigned int modulus_size, const unsigned char *exp, unsigned int exp_size) { void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) {
if (g_security_engine == NULL || keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) { if (g_security_engine == NULL || keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) {
panic(); panic();
} }
for (unsigned int i = 0; i < (modulus_size >> 2); i++) { for (size_t i = 0; i < (modulus_size >> 2); i++) {
g_security_engine->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i; g_security_engine->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i;
g_security_engine->RSA_KEYTABLE_DATA = read32be(modulus, 4 * i); g_security_engine->RSA_KEYTABLE_DATA = read32be(modulus, 4 * i);
} }
for (unsigned int i = 0; i < (exp_size >> 2); i++) { for (size_t i = 0; i < (exp_size >> 2); i++) {
g_security_engine->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; g_security_engine->RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
g_security_engine->RSA_KEYTABLE_DATA = read32be(exp, 4 * i); g_security_engine->RSA_KEYTABLE_DATA = read32be(exponent, 4 * i);
} }
g_se_modulus_sizes[keyslot] = modulus_size; g_se_modulus_sizes[keyslot] = modulus_size;
@ -128,18 +127,18 @@ void set_rsa_keyslot(unsigned int keyslot, const unsigned char *modulus, unsigne
} }
void set_aes_keyslot_iv(unsigned int keyslot, const unsigned char *iv, unsigned int iv_size) { void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) {
if (g_security_engine == NULL || keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) { if (g_security_engine == NULL || keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) {
panic(); panic();
} }
for (unsigned int i = 0; i < (iv_size >> 2); i++) { for (size_t i = 0; i < (iv_size >> 2); i++) {
g_security_engine->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; g_security_engine->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
g_security_engine->AES_KEYTABLE_DATA = read32le(iv, 4 * i); g_security_engine->AES_KEYTABLE_DATA = read32le(iv, 4 * i);
} }
} }
void set_se_ctr(const char *ctr) { void set_se_ctr(const void *ctr) {
if (g_security_engine == NULL) { if (g_security_engine == NULL) {
panic(); panic();
} }
@ -149,7 +148,7 @@ void set_se_ctr(const char *ctr) {
} }
} }
void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const unsigned char *wrapped_key, unsigned int wrapped_key_size) { void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) {
if (g_security_engine == NULL || keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSIZE_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) { if (g_security_engine == NULL || keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSIZE_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) {
panic(); panic();
} }
@ -157,38 +156,37 @@ void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_sr
g_security_engine->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB); g_security_engine->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB);
g_security_engine->CRYPTO_REG = keyslot_src << 24; g_security_engine->CRYPTO_REG = keyslot_src << 24;
g_security_engine->BLOCK_COUNT_REG = 0; g_security_engine->BLOCK_COUNT_REG = 0;
g_se_callback->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; g_security_engine->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8;
/* TODO: Cache flush the wrapped key. */ flush_dcache_range(wrapped_key, (const uint8_t *)wrapped_key + wrapped_key_size);
trigger_se_aes_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size); trigger_se_aes_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size);
} }
void se_crypt_aes(unsigned int keyslot, unsigned char *dst, unsigned int dst_size, const unsigned char *src, unsigned int src_size, unsigned int config, unsigned int mode, unsigned int (*callback)(void)); void se_crypt_aes(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config, unsigned int mode, unsigned int (*callback)(void));
void se_exp_mod(unsigned int keyslot, unsigned char *buf, unsigned int size, unsigned int (*callback)(void)) { void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*callback)(void)) {
unsigned char stack_buf[KEYSIZE_RSA_MAX]; uint8_t stack_buf[KEYSIZE_RSA_MAX];
if (g_security_engine == NULL || keyslot >= KEYSLOT_RSA_MAX || size > KEYSIZE_RSA_MAX) { if (g_security_engine == NULL || keyslot >= KEYSLOT_RSA_MAX || size > KEYSIZE_RSA_MAX) {
panic(); panic();
} }
/* Endian swap the input. */ /* Endian swap the input. */
for (unsigned int i = size; i > 0; i--) { for (size_t i = size; i > 0; i--) {
stack_buf[i] = buf[size - i]; stack_buf[i] = *((uint8_t *)buf + size - i);
} }
/* TODO: Flush cache for stack copy. */
g_security_engine->CONFIG_REG = (ALG_RSA | DST_RSAREG); g_security_engine->CONFIG_REG = (ALG_RSA | DST_RSAREG);
g_security_engine->RSA_CONFIG = keyslot << 24; g_security_engine->RSA_CONFIG = keyslot << 24;
g_security_engine->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; g_security_engine->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1;
g_security_engine->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; g_security_engine->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2;
set_security_engine_callback(callback); set_security_engine_callback(callback);
flush_dcache_range(stack_buf, stack_buf + KEYSIZE_RSA_MAX);
trigger_se_rsa_op(stack_buf, size); trigger_se_rsa_op(stack_buf, size);
while (!(g_security_engine->INT_STATUS_REG & 2)) { /* Wait a while */ } while (!(g_security_engine->INT_STATUS_REG & 2)) { /* Wait a while */ }
} }

View file

@ -1,6 +1,9 @@
#ifndef EXOSPHERE_SE_H #ifndef EXOSPHERE_SE_H
#define EXOSPHERE_SE_H #define EXOSPHERE_SE_H
#include <stdint.h>
#include <stddef.h>
/* Exosphere driver for the Tegra X1 security engine. */ /* Exosphere driver for the Tegra X1 security engine. */
#define KEYSLOT_AES_MAX 0x10 #define KEYSLOT_AES_MAX 0x10
@ -100,18 +103,18 @@ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags);
void clear_aes_keyslot(unsigned int keyslot); void clear_aes_keyslot(unsigned int keyslot);
void clear_rsa_keyslot(unsigned int keyslot); void clear_rsa_keyslot(unsigned int keyslot);
void set_aes_keyslot(unsigned int keyslot, const unsigned char *key, unsigned int key_size); void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size);
void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const unsigned char *wrapped_key, unsigned int wrapped_key_size); void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size);
void set_rsa_keyslot(unsigned int keyslot, const unsigned char *modulus, unsigned int modulus_size, const unsigned char *exp, unsigned int exp_size); void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size);
void set_aes_keyslot_iv(unsigned int keyslot, const unsigned char *iv, unsigned int iv_size); void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size);
void set_se_ctr(const char *ctr); void set_se_ctr(const void *ctr);
void se_crypt_aes(unsigned int keyslot, unsigned char *dst, unsigned int dst_size, const unsigned char *src, unsigned int src_size, unsigned int config, unsigned int mode, unsigned int (*callback)(void)); void se_crypt_aes(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config, unsigned int mode, unsigned int (*callback)(void));
void se_exp_mod(unsigned int keyslot, unsigned char *buf, unsigned int size, unsigned int (*callback)(void)); void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*callback)(void));
void se_generate_random(unsigned int keyslot, unsigned char *dst, unsigned int size); void se_generate_random(unsigned int keyslot, void *dst, size_t size);
/* TODO: SE context save API, consider extending AES API for secure world vs non-secure world operations. */ /* TODO: SE context save API, consider extending AES API for secure world vs non-secure world operations. */
/* In particular, smc_crypt_aes takes in raw DMA lists, and we need to support that. */ /* In particular, smc_crypt_aes takes in raw DMA lists, and we need to support that. */
#endif /* EXOSPHERE_SE_H */ #endif /* EXOSPHERE_SE_H */

View file

@ -6,10 +6,8 @@
#include "se.h" #include "se.h"
uint32_t user_load_aes_key(smc_args_t *args) { uint32_t user_load_aes_key(smc_args_t *args) {
unsigned char sealed_kek[0x10]; uint64_t sealed_kek[2];
unsigned char wrapped_key[0x10]; uint64_t wrapped_key[2];
uint64_t *p_sealed_kek = (uint64_t *)(&sealed_kek[0]);
uint64_t *p_wrapped_key = (uint64_t *)(&wrapped_key[0]);
uint32_t keyslot = (uint32_t)args->X[1]; uint32_t keyslot = (uint32_t)args->X[1];
if (keyslot > 3) { if (keyslot > 3) {
@ -17,10 +15,10 @@ uint32_t user_load_aes_key(smc_args_t *args) {
} }
/* Copy keydata */ /* Copy keydata */
p_sealed_kek[0] = args->X[2]; sealed_kek[0] = args->X[2];
p_sealed_kek[1] = args->X[3]; sealed_kek[1] = args->X[3];
p_wrapped_key[0] = args->X[4]; wrapped_key[0] = args->X[4];
p_wrapped_key[1] = args->X[5]; wrapped_key[1] = args->X[5];
/* TODO: Unseal the kek. */ /* TODO: Unseal the kek. */
set_aes_keyslot(9, sealed_kek, 0x10); set_aes_keyslot(9, sealed_kek, 0x10);
@ -28,4 +26,4 @@ uint32_t user_load_aes_key(smc_args_t *args) {
/* Unwrap the key. */ /* Unwrap the key. */
decrypt_data_into_keyslot(keyslot, 9, wrapped_key, 0x10); decrypt_data_into_keyslot(keyslot, 9, wrapped_key, 0x10);
return 0; return 0;
} }

View file

@ -2,16 +2,22 @@
#define EXOSPHERE_UTILS_H #define EXOSPHERE_UTILS_H
#include <stdint.h> #include <stdint.h>
#include <stddef.h>
void panic(void); void panic(void);
unsigned int read32le(const unsigned char *dword, unsigned int offset); static inline uint32_t read32le(const void *dword, size_t offset) {
unsigned int read32be(const unsigned char *dword, unsigned int offset); return *(uint32_t *)((uintptr_t)dword + offset);
}
static inline uint32_t get_core_id(void) { static inline uint32_t read32be(const unsigned char *dword, size_t offset) {
uint32_t core_id; return __builtin_bswap32(read32le(dword, offset));
asm volatile("mrs %0, MPIDR_EL1" : "=r"(core_id)); }
static inline unsigned int get_core_id(void) {
unsigned int core_id;
__asm__ __volatile__ ("mrs %0, MPIDR_EL1" : "=r"(core_id));
return core_id; return core_id;
} }
#endif #endif