keys: Split crypto functions by sysmodule
This commit is contained in:
parent
c7d90ec8ca
commit
dd41e3fee8
14 changed files with 621 additions and 326 deletions
|
@ -17,9 +17,11 @@
|
|||
#include "keys.h"
|
||||
|
||||
#include "cal0_read.h"
|
||||
#include "es_crypto.h"
|
||||
#include "fs_crypto.h"
|
||||
#include "gmac.h"
|
||||
|
||||
#include "../../keygen/tsec_keygen.h"
|
||||
#include "nfc_crypto.h"
|
||||
#include "ssl_crypto.h"
|
||||
|
||||
#include "../config.h"
|
||||
#include <display/di.h>
|
||||
|
@ -35,9 +37,7 @@
|
|||
#include <mem/sdram.h>
|
||||
#include <sec/se.h>
|
||||
#include <sec/se_t210.h>
|
||||
#include <sec/tsec.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <mem/smmu.h>
|
||||
#include <soc/t210.h>
|
||||
#include "../storage/emummc.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
|
@ -59,49 +59,49 @@ static u32 _key_count = 0, _titlekey_count = 0;
|
|||
static u32 start_time, end_time;
|
||||
u32 color_idx = 0;
|
||||
|
||||
// key functions
|
||||
static int _key_exists(const void *data) { return memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) != 0; };
|
||||
static void _save_key(const char *name, const void *data, u32 len, char *outbuf);
|
||||
static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf);
|
||||
static void _save_key(const char *name, const void *data, u32 len, char *outbuf) {
|
||||
if (!key_exists(data))
|
||||
return;
|
||||
u32 pos = strlen(outbuf);
|
||||
pos += s_printf(&outbuf[pos], "%s = ", name);
|
||||
for (u32 i = 0; i < len; i++)
|
||||
pos += s_printf(&outbuf[pos], "%02x", *(u8*)(data + i));
|
||||
s_printf(&outbuf[pos], "\n");
|
||||
_key_count++;
|
||||
}
|
||||
|
||||
static void _derive_master_key_mariko(key_storage_t *keys, bool is_dev) {
|
||||
static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf) {
|
||||
char *temp_name = calloc(1, 0x40);
|
||||
for (u32 i = 0; i < num_keys; i++) {
|
||||
s_printf(temp_name, "%s_%02x", name, i + start_key);
|
||||
_save_key(temp_name, data + i * len, len, outbuf);
|
||||
}
|
||||
free(temp_name);
|
||||
}
|
||||
|
||||
static void _derive_master_keys_mariko(key_storage_t *keys, bool is_dev) {
|
||||
minerva_periodic_training();
|
||||
// Relies on the SBK being properly set in slot 14
|
||||
se_aes_crypt_block_ecb(KS_SECURE_BOOT, DECRYPT, keys->device_key_4x, device_master_key_source_kek_source);
|
||||
// Derive all master keys based on Mariko KEK
|
||||
for (u32 i = KB_FIRMWARE_VERSION_600; i < ARRAY_SIZE(mariko_master_kek_sources) + KB_FIRMWARE_VERSION_600; i++) {
|
||||
// Relies on the Mariko KEK being properly set in slot 12
|
||||
se_aes_crypt_block_ecb(KS_MARIKO_KEK, DECRYPT, keys->master_kek[i], is_dev ? &mariko_master_kek_sources_dev[i - KB_FIRMWARE_VERSION_600] : &mariko_master_kek_sources[i - KB_FIRMWARE_VERSION_600]);
|
||||
u32 kek_source_index = i - KB_FIRMWARE_VERSION_600;
|
||||
const void *kek_source = is_dev ? &mariko_master_kek_sources_dev[kek_source_index] : &mariko_master_kek_sources[kek_source_index];
|
||||
se_aes_crypt_block_ecb(KS_MARIKO_KEK, DECRYPT, keys->master_kek[i], kek_source);
|
||||
load_aes_key(KS_AES_ECB, keys->master_key[i], keys->master_kek[i], master_key_source);
|
||||
}
|
||||
}
|
||||
|
||||
static int _run_ams_keygen(key_storage_t *keys) {
|
||||
tsec_ctxt_t tsec_ctxt;
|
||||
tsec_ctxt.fw = tsec_keygen;
|
||||
tsec_ctxt.size = sizeof(tsec_keygen);
|
||||
tsec_ctxt.type = TSEC_FW_TYPE_NEW;
|
||||
|
||||
u32 retries = 0;
|
||||
while (tsec_query(keys->temp_key, &tsec_ctxt) < 0) {
|
||||
retries++;
|
||||
if (retries > 15) {
|
||||
EPRINTF("Failed to run keygen.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _derive_master_keys_from_latest_key(key_storage_t *keys, bool is_dev) {
|
||||
minerva_periodic_training();
|
||||
if (!h_cfg.t210b01) {
|
||||
u32 tsec_root_key_slot = is_dev ? 11 : 13;
|
||||
u32 tsec_root_key_slot = is_dev ? KS_TSEC_ROOT_DEV : KS_TSEC_ROOT;
|
||||
// Derive all master keys based on current root key
|
||||
for (u32 i = KB_FIRMWARE_VERSION_810 - KB_FIRMWARE_VERSION_620; i < ARRAY_SIZE(master_kek_sources); i++) {
|
||||
se_aes_crypt_block_ecb(tsec_root_key_slot, DECRYPT, keys->master_kek[i + KB_FIRMWARE_VERSION_620], master_kek_sources[i]);
|
||||
load_aes_key(KS_AES_ECB, keys->master_key[i + KB_FIRMWARE_VERSION_620], keys->master_kek[i + KB_FIRMWARE_VERSION_620], master_key_source);
|
||||
u32 key_index = i + KB_FIRMWARE_VERSION_620;
|
||||
se_aes_crypt_block_ecb(tsec_root_key_slot, DECRYPT, keys->master_kek[key_index], master_kek_sources[i]);
|
||||
load_aes_key(KS_AES_ECB, keys->master_key[key_index], keys->master_kek[key_index], master_key_source);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ static void _derive_master_keys_from_latest_key(key_storage_t *keys, bool is_dev
|
|||
}
|
||||
load_aes_key(KS_AES_ECB, keys->temp_key, keys->master_key[0], is_dev ? master_key_vectors_dev[0] : master_key_vectors[0]);
|
||||
|
||||
if (_key_exists(keys->temp_key)) {
|
||||
if (key_exists(keys->temp_key)) {
|
||||
EPRINTFARGS("Unable to derive master keys for %s.", is_dev ? "dev" : "prod");
|
||||
memset(keys->master_key, 0, sizeof(keys->master_key));
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ static void _derive_keyblob_keys(key_storage_t *keys) {
|
|||
|
||||
memcpy(keys->package1_key[i], keys->keyblob[i].package1_key, sizeof(keys->package1_key[i]));
|
||||
memcpy(keys->master_kek[i], keys->keyblob[i].master_kek, sizeof(keys->master_kek[i]));
|
||||
if (!_key_exists(keys->master_key[i])) {
|
||||
if (!key_exists(keys->master_key[i])) {
|
||||
load_aes_key(KS_AES_ECB, keys->master_key[i], keys->master_kek[i], master_key_source);
|
||||
}
|
||||
}
|
||||
|
@ -186,67 +186,26 @@ static void _derive_keyblob_keys(key_storage_t *keys) {
|
|||
static void _derive_bis_keys(key_storage_t *keys) {
|
||||
minerva_periodic_training();
|
||||
u32 generation = fuse_read_odm_keygen_rev();
|
||||
|
||||
if (!(_key_exists(keys->device_key) || (generation && _key_exists(keys->master_key[0]) && _key_exists(keys->device_key_4x)))) {
|
||||
return;
|
||||
}
|
||||
generate_specific_aes_key(KS_AES_ECB, keys, &keys->bis_key[0], bis_key_sources[0], generation);
|
||||
u32 access_key[SE_KEY_128_SIZE / 4] = {0};
|
||||
const u32 option = IS_DEVICE_UNIQUE;
|
||||
generate_aes_kek(KS_AES_ECB, keys, access_key, bis_kek_source, generation, option);
|
||||
generate_aes_key(KS_AES_ECB, keys, keys->bis_key[1], sizeof(keys->bis_key[1]), access_key, bis_key_sources[1]);
|
||||
generate_aes_key(KS_AES_ECB, keys, keys->bis_key[2], sizeof(keys->bis_key[2]), access_key, bis_key_sources[2]);
|
||||
memcpy(keys->bis_key[3], keys->bis_key[2], sizeof(keys->bis_key[3]));
|
||||
}
|
||||
|
||||
static void _derive_non_unique_keys(key_storage_t *keys, bool is_dev) {
|
||||
minerva_periodic_training();
|
||||
if (_key_exists(keys->master_key[0])) {
|
||||
const u32 generation = 0;
|
||||
const u32 option = GET_IS_DEVICE_UNIQUE(NOT_DEVICE_UNIQUE);
|
||||
generate_aes_kek(KS_AES_ECB, keys, keys->temp_key, header_kek_source, generation, option);
|
||||
generate_aes_key(KS_AES_ECB, keys, keys->header_key, sizeof(keys->header_key), keys->temp_key, header_key_source);
|
||||
}
|
||||
}
|
||||
|
||||
static void _derive_rsa_kek(u32 ks, key_storage_t *keys, void *out_rsa_kek, const void *kekek_source, const void *kek_source, u32 generation, u32 option) {
|
||||
void *access_key = keys->temp_key;
|
||||
generate_aes_kek(ks, keys, access_key, kekek_source, generation, option);
|
||||
get_device_unique_data_key(ks, out_rsa_kek, access_key, kek_source);
|
||||
fs_derive_bis_keys(keys, keys->bis_key, generation);
|
||||
}
|
||||
|
||||
static void _derive_misc_keys(key_storage_t *keys, bool is_dev) {
|
||||
minerva_periodic_training();
|
||||
if (_key_exists(keys->device_key) || (_key_exists(keys->master_key[0]) && _key_exists(keys->device_key_4x))) {
|
||||
void *access_key = keys->temp_key;
|
||||
const u32 generation = 0;
|
||||
const u32 option = IS_DEVICE_UNIQUE;
|
||||
generate_aes_kek(KS_AES_ECB, keys, access_key, save_mac_kek_source, generation, option);
|
||||
load_aes_key(KS_AES_ECB, keys->save_mac_key, access_key, save_mac_key_source);
|
||||
}
|
||||
|
||||
if (_key_exists(keys->master_key[0])) {
|
||||
const void *eticket_kek_source = is_dev ? eticket_rsa_kek_source_dev : eticket_rsa_kek_source;
|
||||
const u32 generation = 0;
|
||||
u32 option = SET_SEAL_KEY_INDEX(SEAL_KEY_IMPORT_ES_DEVICE_KEY) | NOT_DEVICE_UNIQUE;
|
||||
_derive_rsa_kek(KS_AES_ECB, keys, keys->eticket_rsa_kek, eticket_rsa_kekek_source, eticket_kek_source, generation, option);
|
||||
|
||||
const void *ssl_kek_source = is_dev ? ssl_rsa_kek_source_dev : ssl_rsa_kek_source;
|
||||
option = SET_SEAL_KEY_INDEX(SEAL_KEY_DECRYPT_DEVICE_UNIQUE_DATA) | NOT_DEVICE_UNIQUE;
|
||||
_derive_rsa_kek(KS_AES_ECB, keys, keys->ssl_rsa_kek, ssl_rsa_kekek_source, ssl_kek_source, generation, option);
|
||||
}
|
||||
fs_derive_save_mac_key(keys, keys->save_mac_key);
|
||||
es_derive_rsa_kek_original(keys, keys->eticket_rsa_kek, is_dev);
|
||||
ssl_derive_rsa_kek_original(keys, keys->ssl_rsa_kek, is_dev);
|
||||
}
|
||||
|
||||
static void _derive_per_generation_keys(key_storage_t *keys) {
|
||||
static void _derive_non_unique_keys(key_storage_t *keys) {
|
||||
minerva_periodic_training();
|
||||
fs_derive_header_key(keys, keys->header_key);
|
||||
|
||||
for (u32 generation = 0; generation < ARRAY_SIZE(keys->master_key); generation++) {
|
||||
minerva_periodic_training();
|
||||
if (!_key_exists(keys->master_key[generation]))
|
||||
if (!key_exists(keys->master_key[generation]))
|
||||
continue;
|
||||
for (u32 source_type = 0; source_type < ARRAY_SIZE(key_area_key_sources); source_type++) {
|
||||
void *access_key = keys->temp_key;
|
||||
const u32 option = GET_IS_DEVICE_UNIQUE(NOT_DEVICE_UNIQUE);
|
||||
generate_aes_kek(KS_AES_ECB, keys, access_key, key_area_key_sources[source_type], generation + 1, option);
|
||||
load_aes_key(KS_AES_ECB, keys->key_area_key[source_type][generation], access_key, aes_key_generation_source);
|
||||
fs_derive_key_area_key(keys, keys->key_area_key[source_type][generation], source_type, generation);
|
||||
}
|
||||
load_aes_key(KS_AES_ECB, keys->package2_key[generation], keys->master_key[generation], package2_key_source);
|
||||
load_aes_key(KS_AES_ECB, keys->titlekek[generation], keys->master_key[generation], titlekek_source);
|
||||
|
@ -292,7 +251,7 @@ static void _decode_tickets(u32 buf_size, titlekey_buffer_t *titlekey_buffer, u3
|
|||
}
|
||||
}
|
||||
|
||||
static bool _get_titlekeys_from_save(u32 buf_size, const u8 *save_mac_key, titlekey_buffer_t *titlekey_buffer, rsa_keypair_t *rsa_keypair) {
|
||||
static bool _get_titlekeys_from_save(u32 buf_size, const u8 *save_mac_key, titlekey_buffer_t *titlekey_buffer, eticket_rsa_keypair_t *rsa_keypair) {
|
||||
FIL fp;
|
||||
u64 br = buf_size;
|
||||
u64 offset = 0;
|
||||
|
@ -471,14 +430,12 @@ static bool _decrypt_ssl_rsa_key(key_storage_t *keys, titlekey_buffer_t *titleke
|
|||
return true;
|
||||
}
|
||||
|
||||
const u32 option = SET_SEAL_KEY_INDEX(SEAL_KEY_DECRYPT_DEVICE_UNIQUE_DATA) | NOT_DEVICE_UNIQUE;
|
||||
ssl_derive_rsa_kek_legacy(keys, keys->ssl_rsa_kek_legacy);
|
||||
ctr_key = keys->ssl_rsa_kek_legacy;
|
||||
_derive_rsa_kek(KS_AES_ECB, keys, ctr_key, ssl_rsa_kekek_source, ssl_rsa_kek_source_legacy, generation, option);
|
||||
enforce_unique = false;
|
||||
} else if (generation) {
|
||||
const u32 option = SET_SEAL_KEY_INDEX(SEAL_KEY_IMPORT_SSL_KEY) | IS_DEVICE_UNIQUE;
|
||||
ssl_derive_rsa_kek_device_unique(keys, keys->ssl_rsa_kek_personalized, generation);
|
||||
ctr_key = keys->ssl_rsa_kek_personalized;
|
||||
_derive_rsa_kek(KS_AES_ECB, keys, ctr_key, ssl_client_cert_kek_source, ssl_client_cert_key_source, generation, option);
|
||||
} else {
|
||||
ctr_key = keys->ssl_rsa_kek;
|
||||
}
|
||||
|
@ -520,9 +477,9 @@ static bool _decrypt_eticket_rsa_key(key_storage_t *keys, titlekey_buffer_t *tit
|
|||
|
||||
// Handle legacy case
|
||||
if (key_size == ETICKET_RSA_KEYPAIR_SIZE) {
|
||||
const u32 option = SET_SEAL_KEY_INDEX(SEAL_KEY_IMPORT_ES_DEVICE_KEY) | NOT_DEVICE_UNIQUE;
|
||||
ctr_key = keys->temp_key;
|
||||
_derive_rsa_kek(KS_AES_ECB, keys, ctr_key, eticket_rsa_kekek_source, eticket_rsa_kek_source_legacy, generation, option);
|
||||
u32 temp_key[SE_KEY_128_SIZE / 4] = {0};
|
||||
es_derive_rsa_kek_legacy(keys, temp_key);
|
||||
ctr_key = temp_key;
|
||||
|
||||
se_aes_key_set(KS_AES_CTR, ctr_key, SE_KEY_128_SIZE);
|
||||
se_aes_crypt_ctr(KS_AES_CTR, &keys->eticket_rsa_keypair, sizeof(keys->eticket_rsa_keypair), encrypted_key, sizeof(keys->eticket_rsa_keypair), iv);
|
||||
|
@ -535,10 +492,8 @@ static bool _decrypt_eticket_rsa_key(key_storage_t *keys, titlekey_buffer_t *tit
|
|||
}
|
||||
|
||||
if (generation) {
|
||||
const u32 option = SET_SEAL_KEY_INDEX(SEAL_KEY_IMPORT_ES_DEVICE_KEY) | IS_DEVICE_UNIQUE;
|
||||
es_derive_rsa_kek_device_unique(keys, keys->eticket_rsa_kek_personalized, generation, is_dev);
|
||||
ctr_key = keys->eticket_rsa_kek_personalized;
|
||||
const void *kek_source = is_dev ? eticket_rsa_kek_source_dev : eticket_rsa_kek_source;
|
||||
_derive_rsa_kek(KS_AES_ECB, keys, ctr_key, eticket_rsa_kekek_source, kek_source, generation, option);
|
||||
} else {
|
||||
ctr_key = keys->eticket_rsa_kek;
|
||||
}
|
||||
|
@ -556,16 +511,12 @@ static bool _decrypt_eticket_rsa_key(key_storage_t *keys, titlekey_buffer_t *tit
|
|||
}
|
||||
|
||||
static bool _derive_titlekeys(key_storage_t *keys, titlekey_buffer_t *titlekey_buffer, bool is_dev) {
|
||||
if (!_key_exists(keys->eticket_rsa_kek)) {
|
||||
if (!key_exists(keys->eticket_rsa_kek)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gfx_printf("%kTitlekeys... \n", colors[(color_idx++) % 6]);
|
||||
|
||||
if (!_decrypt_eticket_rsa_key(keys, titlekey_buffer, is_dev)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const u32 buf_size = SAVE_BLOCK_SIZE_DEFAULT;
|
||||
_get_titlekeys_from_save(buf_size, keys->save_mac_key, titlekey_buffer, NULL);
|
||||
_get_titlekeys_from_save(buf_size, keys->save_mac_key, titlekey_buffer, &keys->eticket_rsa_keypair);
|
||||
|
@ -591,6 +542,17 @@ static bool _derive_emmc_keys(key_storage_t *keys, titlekey_buffer_t *titlekey_b
|
|||
EPRINTF("Unable to set partition.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool res = _decrypt_ssl_rsa_key(keys, titlekey_buffer);
|
||||
if (!res) {
|
||||
EPRINTF("Unable to derive SSL key.");
|
||||
}
|
||||
|
||||
res =_decrypt_eticket_rsa_key(keys, titlekey_buffer, is_dev);
|
||||
if (!res) {
|
||||
EPRINTF("Unable to derive ETicket key.");
|
||||
}
|
||||
|
||||
// Parse eMMC GPT
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &emmc_storage);
|
||||
|
@ -616,11 +578,6 @@ static bool _derive_emmc_keys(key_storage_t *keys, titlekey_buffer_t *titlekey_b
|
|||
EPRINTF("Unable to get SD seed.");
|
||||
}
|
||||
|
||||
bool res = _decrypt_ssl_rsa_key(keys, titlekey_buffer);
|
||||
if (!res) {
|
||||
EPRINTF("Unable to derive SSL key.");
|
||||
}
|
||||
|
||||
res = _derive_titlekeys(keys, titlekey_buffer, is_dev);
|
||||
if (!res) {
|
||||
EPRINTF("Unable to derive titlekeys.");
|
||||
|
@ -660,7 +617,7 @@ int save_mariko_partial_keys(u32 start, u32 count, bool append) {
|
|||
// Check if key is as expected
|
||||
if (ks < ARRAY_SIZE(mariko_key_vectors)) {
|
||||
se_aes_crypt_block_ecb(ks, DECRYPT, &data[0], mariko_key_vectors[ks]);
|
||||
if (_key_exists(data)) {
|
||||
if (key_exists(data)) {
|
||||
EPRINTFARGS("Failed to validate keyslot %d.", ks);
|
||||
continue;
|
||||
}
|
||||
|
@ -858,19 +815,19 @@ static void _derive_master_keys(key_storage_t *prod_keys, key_storage_t *dev_key
|
|||
key_storage_t *keys = is_dev ? dev_keys : prod_keys;
|
||||
|
||||
if (h_cfg.t210b01) {
|
||||
_derive_master_key_mariko(keys, is_dev);
|
||||
_derive_master_keys_mariko(keys, is_dev);
|
||||
_derive_master_keys_from_latest_key(keys, is_dev);
|
||||
} else {
|
||||
int res = _run_ams_keygen(keys);
|
||||
if (res) {
|
||||
if (run_ams_keygen(keys)) {
|
||||
EPRINTF("Failed to run keygen.");
|
||||
return;
|
||||
}
|
||||
|
||||
u8 *aes_keys = (u8 *)calloc(SZ_4K, 1);
|
||||
se_get_aes_keys(aes_keys + SZ_2K, aes_keys, SE_KEY_128_SIZE);
|
||||
memcpy(&dev_keys->tsec_root_key, aes_keys + KS_TSEC_ROOT_DEV * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(keys->tsec_key, aes_keys + KS_TSEC * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(&prod_keys->tsec_root_key, aes_keys + KS_TSEC_ROOT * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(keys->tsec_key, aes_keys + KS_TSEC * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(&prod_keys->tsec_root_key, aes_keys + KS_TSEC_ROOT * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
free(aes_keys);
|
||||
|
||||
_derive_master_keys_from_latest_key(prod_keys, false);
|
||||
|
@ -916,17 +873,15 @@ static void _derive_keys() {
|
|||
TPRINTFARGS("%kBIS keys... ", colors[(color_idx++) % 6]);
|
||||
|
||||
_derive_misc_keys(keys, is_dev);
|
||||
_derive_non_unique_keys(&prod_keys, is_dev);
|
||||
_derive_non_unique_keys(&dev_keys, is_dev);
|
||||
_derive_per_generation_keys(&prod_keys);
|
||||
_derive_per_generation_keys(&dev_keys);
|
||||
_derive_non_unique_keys(&prod_keys);
|
||||
_derive_non_unique_keys(&dev_keys);
|
||||
|
||||
titlekey_buffer_t *titlekey_buffer = (titlekey_buffer_t *)TITLEKEY_BUF_ADR;
|
||||
|
||||
// Requires BIS key for SYSTEM partition
|
||||
if (!emmc_storage.initialized) {
|
||||
EPRINTF("eMMC not initialized.\nSkipping SD seed and titlekeys.");
|
||||
} else if (_key_exists(keys->bis_key[2])) {
|
||||
} else if (key_exists(keys->bis_key[2])) {
|
||||
_derive_emmc_keys(keys, titlekey_buffer, is_dev);
|
||||
} else {
|
||||
EPRINTF("Missing needed BIS keys.\nSkipping SD seed and titlekeys.");
|
||||
|
@ -946,37 +901,6 @@ static void _derive_keys() {
|
|||
}
|
||||
}
|
||||
|
||||
static void _decrypt_amiibo_keys(key_storage_t *keys, const u8 *encrypted_keys, nfc_save_key_t nfc_save_keys[2]) {
|
||||
u32 kek[SE_KEY_128_SIZE / 4] = {0};
|
||||
decrypt_aes_key(KS_AES_ECB, keys, kek, nfc_key_source, 0, 0);
|
||||
|
||||
nfc_keyblob_t __attribute__((aligned(4))) nfc_keyblob;
|
||||
static const u8 nfc_iv[SE_KEY_128_SIZE] = {
|
||||
0xB9, 0x1D, 0xC1, 0xCF, 0x33, 0x5F, 0xA6, 0x13, 0x2A, 0xEF, 0x90, 0x99, 0xAA, 0xCA, 0x93, 0xC8};
|
||||
se_aes_key_set(KS_AES_CTR, kek, SE_KEY_128_SIZE);
|
||||
se_aes_crypt_ctr(KS_AES_CTR, &nfc_keyblob, sizeof(nfc_keyblob), encrypted_keys, sizeof(nfc_keyblob), &nfc_iv);
|
||||
|
||||
minerva_periodic_training();
|
||||
|
||||
u32 xor_pad[0x20 / 4] = {0};
|
||||
se_aes_key_set(KS_AES_CTR, nfc_keyblob.ctr_key, SE_KEY_128_SIZE);
|
||||
se_aes_crypt_ctr(KS_AES_CTR, xor_pad, sizeof(xor_pad), xor_pad, sizeof(xor_pad), nfc_keyblob.ctr_iv);
|
||||
|
||||
minerva_periodic_training();
|
||||
|
||||
memcpy(nfc_save_keys[0].hmac_key, nfc_keyblob.hmac_key, sizeof(nfc_keyblob.hmac_key));
|
||||
memcpy(nfc_save_keys[0].phrase, nfc_keyblob.phrase, sizeof(nfc_keyblob.phrase));
|
||||
nfc_save_keys[0].seed_size = sizeof(nfc_keyblob.seed);
|
||||
memcpy(nfc_save_keys[0].seed, nfc_keyblob.seed, sizeof(nfc_keyblob.seed));
|
||||
memcpy(nfc_save_keys[0].xor_pad, xor_pad, sizeof(xor_pad));
|
||||
|
||||
memcpy(nfc_save_keys[1].hmac_key, nfc_keyblob.hmac_key_for_verif, sizeof(nfc_keyblob.hmac_key_for_verif));
|
||||
memcpy(nfc_save_keys[1].phrase, nfc_keyblob.phrase_for_verif, sizeof(nfc_keyblob.phrase_for_verif));
|
||||
nfc_save_keys[1].seed_size = sizeof(nfc_keyblob.seed_for_verif);
|
||||
memcpy(nfc_save_keys[1].seed, nfc_keyblob.seed_for_verif, sizeof(nfc_keyblob.seed_for_verif));
|
||||
memcpy(nfc_save_keys[1].xor_pad, xor_pad, sizeof(xor_pad));
|
||||
}
|
||||
|
||||
void derive_amiibo_keys() {
|
||||
minerva_change_freq(FREQ_1600);
|
||||
|
||||
|
@ -984,7 +908,6 @@ void derive_amiibo_keys() {
|
|||
|
||||
key_storage_t __attribute__((aligned(4))) prod_keys = {0}, dev_keys = {0};
|
||||
key_storage_t *keys = is_dev ? &dev_keys : &prod_keys;
|
||||
const u8 *encrypted_keys = is_dev ? encrypted_nfc_keys_dev : encrypted_nfc_keys;
|
||||
|
||||
_derive_master_keys(&prod_keys, &dev_keys, is_dev);
|
||||
|
||||
|
@ -998,7 +921,7 @@ void derive_amiibo_keys() {
|
|||
|
||||
minerva_periodic_training();
|
||||
|
||||
if (!_key_exists(keys->master_key[0])) {
|
||||
if (!key_exists(keys->master_key[0])) {
|
||||
EPRINTF("Unable to derive master keys for NFC.");
|
||||
minerva_change_freq(FREQ_800);
|
||||
btn_wait();
|
||||
|
@ -1007,7 +930,7 @@ void derive_amiibo_keys() {
|
|||
|
||||
nfc_save_key_t __attribute__((aligned(4))) nfc_save_keys[2] = {0};
|
||||
|
||||
_decrypt_amiibo_keys(keys, encrypted_keys, nfc_save_keys);
|
||||
nfc_decrypt_amiibo_keys(keys, nfc_save_keys, is_dev);
|
||||
|
||||
minerva_periodic_training();
|
||||
|
||||
|
@ -1073,23 +996,3 @@ void dump_keys() {
|
|||
}
|
||||
gfx_clear_grey(0x1B);
|
||||
}
|
||||
|
||||
static void _save_key(const char *name, const void *data, u32 len, char *outbuf) {
|
||||
if (!_key_exists(data))
|
||||
return;
|
||||
u32 pos = strlen(outbuf);
|
||||
pos += s_printf(&outbuf[pos], "%s = ", name);
|
||||
for (u32 i = 0; i < len; i++)
|
||||
pos += s_printf(&outbuf[pos], "%02x", *(u8*)(data + i));
|
||||
s_printf(&outbuf[pos], "\n");
|
||||
_key_count++;
|
||||
}
|
||||
|
||||
static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf) {
|
||||
char *temp_name = calloc(1, 0x40);
|
||||
for (u32 i = 0; i < num_keys; i++) {
|
||||
s_printf(temp_name, "%s_%02x", name, i + start_key);
|
||||
_save_key(temp_name, data + i * len, len, outbuf);
|
||||
}
|
||||
free(temp_name);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue