mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
Implement titlekey SMCs (with skeleton tkey API)
This commit is contained in:
parent
59281c5a97
commit
61f8886879
4 changed files with 141 additions and 6 deletions
|
@ -138,10 +138,10 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo
|
||||||
void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||||
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||||
|
|
||||||
|
/* Hash API */
|
||||||
|
void se_calculate_sha256(void *dst, const void *src, size_t src_size);
|
||||||
|
|
||||||
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));
|
/* RSA API */
|
||||||
|
|
||||||
|
|
||||||
void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*callback)(void));
|
void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*callback)(void));
|
||||||
void se_get_exp_mod_output(void *buf, size_t size);
|
void se_get_exp_mod_output(void *buf, size_t size);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "smc_user.h"
|
#include "smc_user.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
#include "userpage.h"
|
#include "userpage.h"
|
||||||
|
#include "titlekey.h"
|
||||||
|
|
||||||
#define SMC_USER_HANDLERS 0x13
|
#define SMC_USER_HANDLERS 0x13
|
||||||
#define SMC_PRIV_HANDLERS 0x9
|
#define SMC_PRIV_HANDLERS 0x9
|
||||||
|
@ -305,7 +306,49 @@ uint32_t smc_rsa_oaep(smc_args_t *args) {
|
||||||
return smc_wrapper_async(args, user_rsa_oaep, smc_exp_mod_get_result);
|
return smc_wrapper_async(args, user_rsa_oaep, smc_exp_mod_get_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t smc_unwrap_rsa_wrapped_titlekey_get_result(void *buf, uint64_t size) {
|
||||||
|
uint64_t *p_sealed_key = (uint64_t *)buf;
|
||||||
|
uint8_t rsa_wrapped_titlekey[0x100];
|
||||||
|
uint8_t aes_wrapped_titlekey[0x10];
|
||||||
|
uint8_t titlekey[0x10];
|
||||||
|
uint64_t sealed_titlekey[2];
|
||||||
|
if (get_exp_mod_done() != 1) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size != 0x10) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
se_get_exp_mod_output(wrapped_titlekey, 0x100);
|
||||||
|
if (tkey_rsa_unwrap(aes_wrapped_titlekey, 0x10, rsa_wrapped_titlekey, 0x100) != 0x10) {
|
||||||
|
/* Failed to extract RSA wrapped key. */
|
||||||
|
g_is_smc_in_progress = 0;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
tkey_aes_unwrap(titlekey, 0x10, aes_wrapped_titlekey, 0x10);
|
||||||
|
tkey_seal(sealed_titlekey, 0x10, titlekey, 0x10);
|
||||||
|
|
||||||
|
p_sealed_key[0] = sealed_titlekey[0];
|
||||||
|
p_sealed_key[1] = sealed_titlekey[1];
|
||||||
|
|
||||||
|
/* smc_unwrap_aes_wrapped_titlekey is done now. */
|
||||||
|
g_is_smc_in_progress = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t smc_unwrap_rsa_wrapped_titlekey(smc_args_t *args) {
|
||||||
|
return smc_wrapper_async(args, user_unwrap_rsa_wrapped_titlekey, smc_unwrap_rsa_wrapped_titlekey_get_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t smc_load_titlekey(smc_args_t *args) {
|
||||||
|
return smc_wrapper_sync(args, user_load_titlekey);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t smc_unwrap_aes_wrapped_titlekey(smc_args_t *args) {
|
||||||
|
return smc_wrapper_sync(args, user_unwrap_aes_wrapped_titlekey);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t smc_cpu_on(smc_args_t *args) {
|
uint32_t smc_cpu_on(smc_args_t *args) {
|
||||||
return cpu_on((uint32_t)args->X[1], args->X[2], args->X[3]);
|
return cpu_on((uint32_t)args->X[1], args->X[2], args->X[3]);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "smc_user.h"
|
#include "smc_user.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
#include "userpage.h"
|
#include "userpage.h"
|
||||||
|
#include "titlekey.h"
|
||||||
|
|
||||||
/* Globals. */
|
/* Globals. */
|
||||||
int g_crypt_aes_done = 0;
|
int g_crypt_aes_done = 0;
|
||||||
|
@ -188,8 +189,6 @@ uint32_t user_rsa_oaep(smc_args_t *args) {
|
||||||
|
|
||||||
upage_ref_t page_ref;
|
upage_ref_t page_ref;
|
||||||
|
|
||||||
size_t exponent_size = (size_t)args->X[4];
|
|
||||||
|
|
||||||
void *user_input = (void *)args->X[1];
|
void *user_input = (void *)args->X[1];
|
||||||
void *user_modulus = (void *)args->X[2];
|
void *user_modulus = (void *)args->X[2];
|
||||||
|
|
||||||
|
@ -211,3 +210,81 @@ uint32_t user_rsa_oaep(smc_args_t *args) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t user_unwrap_rsa_wrapped_titlekey(smc_args_t *args) {
|
||||||
|
uint8_t modulus[0x100];
|
||||||
|
uint8_t wrapped_key[0x100];
|
||||||
|
|
||||||
|
upage_ref_t page_ref;
|
||||||
|
|
||||||
|
void *user_wrapped_key = (void *)args->X[1];
|
||||||
|
void *user_modulus = (void *)args->X[2];
|
||||||
|
unsigned int master_key_rev = (unsigned int)args->X[7];
|
||||||
|
|
||||||
|
/* TODO: Validate Master Key Revision. */
|
||||||
|
|
||||||
|
/* Copy user data into secure memory. */
|
||||||
|
if (upage_init(&page_ref, user_wrapped_key) == 0) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (user_copy_to_secure(&page_ref, wrapped_key, user_wrapped_key, 0x100) == 0) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (user_copy_to_secure(&page_ref, modulus, user_modulus, 0x100) == 0) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_exp_mod_done(0);
|
||||||
|
|
||||||
|
/* Expected salt occupies args->X[3] to args->X[6]. */
|
||||||
|
tkey_set_expected_salt(&args->X[3]);
|
||||||
|
|
||||||
|
tkey_set_master_key_rev(master_key_rev);
|
||||||
|
|
||||||
|
/* Hardcode RSA keyslot 0. */
|
||||||
|
set_rsa_keyslot(0, modulus, 0x100, g_rsa_private_exponent, 0x100);
|
||||||
|
se_exp_mod(0, wrapped_key, 0x100, exp_mod_done_handler);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t user_load_titlekey(smc_args_t *args) {
|
||||||
|
uint64_t sealed_titlekey[2];
|
||||||
|
|
||||||
|
uint32_t keyslot = (uint32_t)args->X[1];
|
||||||
|
if (keyslot > 3) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy keydata */
|
||||||
|
sealed_titlekey[0] = args->X[2];
|
||||||
|
sealed_titlekey[1] = args->X[3];
|
||||||
|
|
||||||
|
/* Unseal the key. */
|
||||||
|
tkey_unseal(keyslot, sealed_titlekey, 0x10);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t user_unwrap_aes_wrapped_titlekey(smc_args_t *args) {
|
||||||
|
uint64_t aes_wrapped_titlekey[2];
|
||||||
|
uint8_t titlekey[0x10];
|
||||||
|
uint64_t sealed_titlekey[2];
|
||||||
|
|
||||||
|
aes_wrapped_titlekey[0] = args->X[1];
|
||||||
|
aes_wrapped_titlekey[1] = args->X[2];
|
||||||
|
unsigned int master_key_rev = (unsigned int)args->X[3];
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: Validate Master Key Revision. */
|
||||||
|
tkey_set_master_key_rev(master_key_rev);
|
||||||
|
|
||||||
|
|
||||||
|
tkey_aes_unwrap(titlekey, 0x10, aes_wrapped_titlekey, 0x10);
|
||||||
|
tkey_seal(sealed_titlekey, 0x10, titlekey, 0x10);
|
||||||
|
|
||||||
|
args->X[1] = sealed_titlekey[0];
|
||||||
|
args->X[2] = sealed_titlekey[1];
|
||||||
|
|
||||||
|
}
|
15
exosphere/titlekey.h
Normal file
15
exosphere/titlekey.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef EXOSPHERE_TITLEKEY_H
|
||||||
|
#define EXOSPHERE_TITLEKEY_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void tkey_set_expected_salt(uint64_t *salt);
|
||||||
|
void tkey_set_master_key_rev(unsigned int master_key_rev);
|
||||||
|
|
||||||
|
size_t tkey_rsa_unwrap(void *dst, size_t dst_size, void *src, size_t src_size);
|
||||||
|
|
||||||
|
void tkey_aes_unwrap(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||||
|
void tkey_seal(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||||
|
void tkey_unseal(unsigned int keyslot, const void *src, size_t src_size);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue