diff --git a/.gitignore b/.gitignore index c6127b38c..c2ede3414 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,5 @@ modules.order Module.symvers Mkfile.old dkms.conf + +.*/ diff --git a/exosphere/se.c b/exosphere/se.c index 034bb8570..d80bf9158 100644 --- a/exosphere/se.c +++ b/exosphere/se.c @@ -1,10 +1,9 @@ -#include - #include "utils.h" +#include "cache.h" #include "se.h" -void trigger_se_rsa_op(void *buf, unsigned int 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_rsa_op(void *buf, size_t 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. */ 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) { 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_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) { 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_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_DATA = read32be(exp, 4 * i); + g_security_engine->RSA_KEYTABLE_DATA = read32be(exponent, 4 * i); } 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) { 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_DATA = read32le(iv, 4 * i); } } -void set_se_ctr(const char *ctr) { +void set_se_ctr(const void *ctr) { if (g_security_engine == NULL) { 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) { 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->CRYPTO_REG = keyslot_src << 24; g_security_engine->BLOCK_COUNT_REG = 0; - g_se_callback->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; - - /* TODO: Cache flush the wrapped key. */ - + g_security_engine->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; + + 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); } -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)) { - unsigned char stack_buf[KEYSIZE_RSA_MAX]; +void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*callback)(void)) { + uint8_t stack_buf[KEYSIZE_RSA_MAX]; if (g_security_engine == NULL || keyslot >= KEYSLOT_RSA_MAX || size > KEYSIZE_RSA_MAX) { panic(); } /* Endian swap the input. */ - for (unsigned int i = size; i > 0; i--) { - stack_buf[i] = buf[size - i]; + for (size_t i = size; i > 0; 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->RSA_CONFIG = keyslot << 24; 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; - + set_security_engine_callback(callback); - + + flush_dcache_range(stack_buf, stack_buf + KEYSIZE_RSA_MAX); trigger_se_rsa_op(stack_buf, size); - + while (!(g_security_engine->INT_STATUS_REG & 2)) { /* Wait a while */ } -} \ No newline at end of file +} diff --git a/exosphere/se.h b/exosphere/se.h index 817178743..856f5b85b 100644 --- a/exosphere/se.h +++ b/exosphere/se.h @@ -1,6 +1,9 @@ #ifndef EXOSPHERE_SE_H #define EXOSPHERE_SE_H +#include +#include + /* Exosphere driver for the Tegra X1 security engine. */ #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_rsa_keyslot(unsigned int keyslot); -void set_aes_keyslot(unsigned int keyslot, const unsigned char *key, unsigned int 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 set_rsa_keyslot(unsigned int keyslot, const unsigned char *modulus, unsigned int modulus_size, const unsigned char *exp, unsigned int exp_size); -void set_aes_keyslot_iv(unsigned int keyslot, const unsigned char *iv, unsigned int iv_size); -void set_se_ctr(const char *ctr); +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 void *wrapped_key, size_t wrapped_key_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 void *iv, size_t iv_size); +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_exp_mod(unsigned int keyslot, unsigned char *buf, unsigned int size, 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, 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. */ /* In particular, smc_crypt_aes takes in raw DMA lists, and we need to support that. */ -#endif /* EXOSPHERE_SE_H */ \ No newline at end of file +#endif /* EXOSPHERE_SE_H */ diff --git a/exosphere/smc_user.c b/exosphere/smc_user.c index 60559cd8c..74ae455e3 100644 --- a/exosphere/smc_user.c +++ b/exosphere/smc_user.c @@ -6,10 +6,8 @@ #include "se.h" uint32_t user_load_aes_key(smc_args_t *args) { - unsigned char sealed_kek[0x10]; - unsigned char wrapped_key[0x10]; - uint64_t *p_sealed_kek = (uint64_t *)(&sealed_kek[0]); - uint64_t *p_wrapped_key = (uint64_t *)(&wrapped_key[0]); + uint64_t sealed_kek[2]; + uint64_t wrapped_key[2]; uint32_t keyslot = (uint32_t)args->X[1]; if (keyslot > 3) { @@ -17,10 +15,10 @@ uint32_t user_load_aes_key(smc_args_t *args) { } /* Copy keydata */ - p_sealed_kek[0] = args->X[2]; - p_sealed_kek[1] = args->X[3]; - p_wrapped_key[0] = args->X[4]; - p_wrapped_key[1] = args->X[5]; + sealed_kek[0] = args->X[2]; + sealed_kek[1] = args->X[3]; + wrapped_key[0] = args->X[4]; + wrapped_key[1] = args->X[5]; /* TODO: Unseal the kek. */ set_aes_keyslot(9, sealed_kek, 0x10); @@ -28,4 +26,4 @@ uint32_t user_load_aes_key(smc_args_t *args) { /* Unwrap the key. */ decrypt_data_into_keyslot(keyslot, 9, wrapped_key, 0x10); return 0; -} \ No newline at end of file +} diff --git a/exosphere/utils.h b/exosphere/utils.h index 9dc9664e5..13f3e4d62 100644 --- a/exosphere/utils.h +++ b/exosphere/utils.h @@ -2,16 +2,22 @@ #define EXOSPHERE_UTILS_H #include +#include void panic(void); -unsigned int read32le(const unsigned char *dword, unsigned int offset); -unsigned int read32be(const unsigned char *dword, unsigned int offset); +static inline uint32_t read32le(const void *dword, size_t offset) { + return *(uint32_t *)((uintptr_t)dword + offset); +} -static inline uint32_t get_core_id(void) { - uint32_t core_id; - asm volatile("mrs %0, MPIDR_EL1" : "=r"(core_id)); +static inline uint32_t read32be(const unsigned char *dword, size_t offset) { + return __builtin_bswap32(read32le(dword, offset)); +} + +static inline unsigned int get_core_id(void) { + unsigned int core_id; + __asm__ __volatile__ ("mrs %0, MPIDR_EL1" : "=r"(core_id)); return core_id; } -#endif \ No newline at end of file +#endif