From 5c24f58402faa04b490beab201c374ba44145d06 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sat, 17 Feb 2018 16:34:31 -0800 Subject: [PATCH] Example SMC implementation (load_aes_key) --- exosphere/smc_api.c | 49 +++++++++++++++++++++++++++++++++++++++++--- exosphere/smc_user.c | 31 ++++++++++++++++++++++++++++ exosphere/smc_user.h | 21 +++++++++++++++++++ 3 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 exosphere/smc_user.c create mode 100644 exosphere/smc_user.h diff --git a/exosphere/smc_api.c b/exosphere/smc_api.c index aeab4ed7e..0e0306319 100644 --- a/exosphere/smc_api.c +++ b/exosphere/smc_api.c @@ -2,6 +2,7 @@ #include "utils.h" #include "smc_api.h" +#include "smc_user.h" #include "se.h" #define SMC_USER_HANDLERS 0x13 @@ -93,10 +94,10 @@ smc_table_t g_smc_tables[2] = { }; int g_is_smc_in_progress = 0; -uint32_t (*g_smc_callback)(uint64_t, uint64_t) = NULL; +uint32_t (*g_smc_callback)(void *, uint64_t) = NULL; uint64_t g_smc_callback_key = 0; -uint64_t try_set_smc_callback(uint32_t (*callback)(uint64_t, uint64_t)) { +uint64_t try_set_smc_callback(uint32_t (*callback)(void *, uint64_t)) { uint64_t key; /* TODO: Atomics... */ if (g_smc_callback_key) { @@ -158,7 +159,7 @@ uint32_t smc_wrapper_sync(smc_args_t *args, uint32_t (*handler)(smc_args_t *)) { return result; } -uint32_t smc_wrapper_async(smc_args_t *args, uint32_t (*handler)(smc_args_t *), uint32_t (*callback)(uint64_t, uint64_t)) { +uint32_t smc_wrapper_async(smc_args_t *args, uint32_t (*handler)(smc_args_t *), uint32_t (*callback)(void *, uint64_t)) { uint32_t result; uint64_t key; /* TODO: Make g_is_smc_in_progress atomic. */ @@ -181,4 +182,46 @@ uint32_t smc_wrapper_async(smc_args_t *args, uint32_t (*handler)(smc_args_t *), } g_is_smc_in_progress = 0; return result; +} + +uint32_t smc_check_status(smc_args_t *args) { + if (g_smc_callback_key == 0) { + return 4; + } + + if (args->X[1] != g_smc_callback_key) { + return 5; + } + + args->X[1] = g_smc_callback(NULL, 0); + + g_smc_callback_key = 0; + return 0; +} + +uint32_t smc_get_result(smc_args_t *) { + uint32_t status; + unsigned char result_buf[0x400]; + if (g_smc_callback_key == 0) { + return 4; + } + + if (args->X[1] != g_smc_callback_key) { + return 5; + } + + /* Check result size */ + if (args->X[3] > 0x400) { + return 2; + } + + args->X[1] = g_smc_callback(result_buf, args->X[3]); + g_smc_callback_key = 0; + + /* TODO: Copy result from result_buf into output in args->X[2] */ + return 0; +} + +uint32_t smc_load_aes_key(smc_args_t *args) { + smc_wrapper_sync(args, user_load_aes_key); } \ No newline at end of file diff --git a/exosphere/smc_user.c b/exosphere/smc_user.c new file mode 100644 index 000000000..60559cd8c --- /dev/null +++ b/exosphere/smc_user.c @@ -0,0 +1,31 @@ +#include + +#include "utils.h" +#include "smc_api.h" +#include "smc_user.h" +#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]); + + uint32_t keyslot = (uint32_t)args->X[1]; + if (keyslot > 3) { + return 2; + } + + /* 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]; + + /* TODO: Unseal the kek. */ + set_aes_keyslot(9, sealed_kek, 0x10); + + /* Unwrap the key. */ + decrypt_data_into_keyslot(keyslot, 9, wrapped_key, 0x10); + return 0; +} \ No newline at end of file diff --git a/exosphere/smc_user.h b/exosphere/smc_user.h new file mode 100644 index 000000000..c1815f39e --- /dev/null +++ b/exosphere/smc_user.h @@ -0,0 +1,21 @@ +#ifndef EXOSPHERE_SMC_USER_H +#define EXOSPHERE_SMC_USER_H + +#include "smc_api.h" + +uint32_t user_exp_mod(smc_args_t *args); +uint32_t user_get_random_bytes(smc_args_t *args); +uint32_t user_generate_aes_kek(smc_args_t *args); +uint32_t user_load_aes_key(smc_args_t *args); +uint32_t user_crypt_aes(smc_args_t *args); +uint32_t user_generate_specific_aes_key(smc_args_t *args); +uint32_t user_compute_cmac(smc_args_t *args); +uint32_t user_load_rsa_private_key(smc_args_t *args); +uint32_t user_decrypt_rsa_private_key(smc_args_t *args); +uint32_t user_load_rsa_oaep_key(smc_args_t *args); +uint32_t user_rsa_oaep(smc_args_t *args); +uint32_t user_unwrap_rsa_wrapped_titlekey(smc_args_t *args); +uint32_t user_load_titlekey(smc_args_t *args); +uint32_t user_unwrap_aes_wrapped_titlekey(smc_args_t *args); + +#endif \ No newline at end of file