1
0
Fork 0
mirror of https://github.com/suchmememanyskill/TegraExplorer.git synced 2024-09-16 20:13:24 +01:00
TegraExplorer/source/keys/keys.c
2023-07-28 14:00:59 +02:00

295 lines
10 KiB
C

#include "keys.h"
#include <libs/fatfs/ff.h>
#include <storage/nx_sd.h>
#include <storage/sdmmc.h>
#include <utils/btn.h>
#include <utils/list.h>
#include <utils/sprintf.h>
#include <utils/util.h>
#include <libs/fatfs/ff.h>
#include <mem/heap.h>
#include <mem/mc.h>
#include <mem/minerva.h>
#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 <display/di.h>
#include <gfx_utils.h>
#include "../config.h"
#include "../storage/emummc.h"
#include "../gfx/gfx.h"
#include "../tegraexplorer/tconf.h"
#include "../storage/mountmanager.h"
#include "../storage/nx_emmc.h"
#include "key_sources.inl"
#include <string.h>
extern hekate_config h_cfg;
#define DPRINTF(x)
#define TSEC_KEY_DATA_OFFSET 0x300
#define PKG1_MAX_SIZE 0x40000
#define PKG1_OFFSET 0x100000
#define KEYBLOB_OFFSET 0x180000
typedef struct _bl_hdr_t210b01_t
{
u8 aes_mac[0x10];
u8 rsa_sig[0x100];
u8 salt[0x20];
u8 sha256[0x20];
u32 version;
u32 size;
u32 load_addr;
u32 entrypoint;
u8 rsvd[0x10];
} bl_hdr_t210b01_t;
static int _key_exists(const void *data) { return memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) != 0; };
static ALWAYS_INLINE u8 *_find_tsec_fw(const u8 *pkg1) {
const u32 tsec_fw_align = 0x100;
const u32 tsec_fw_first_instruction = 0xCF42004D;
for (const u32 *pos = (const u32 *)pkg1; (u8 *)pos < pkg1 + PKG1_MAX_SIZE; pos += tsec_fw_align / sizeof(u32))
if (*pos == tsec_fw_first_instruction)
return (u8 *)pos;
return NULL;
}
static ALWAYS_INLINE u32 _get_tsec_fw_size(tsec_key_data_t *key_data) {
return key_data->blob0_size + sizeof(tsec_key_data_t) + key_data->blob1_size + key_data->blob2_size + key_data->blob3_size + key_data->blob4_size;
}
static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed) {
if (!_key_exists(key_source) || !_key_exists(master_key) || !_key_exists(kek_seed))
return;
se_aes_key_set(ks, master_key, AES_128_KEY_SIZE);
se_aes_unwrap_key(ks, ks, kek_seed);
se_aes_unwrap_key(ks, ks, key_source);
if (key_seed && _key_exists(key_seed))
se_aes_unwrap_key(ks, ks, key_seed);
}
static void _get_device_key(u32 ks, void *out_device_key, u32 revision, const void *device_key, const void *new_device_key, const void *master_key) {
if (revision == KB_FIRMWARE_VERSION_100_200 && !h_cfg.t210b01) {
memcpy(out_device_key, device_key, AES_128_KEY_SIZE);
return;
}
if (revision >= KB_FIRMWARE_VERSION_400) {
revision -= KB_FIRMWARE_VERSION_400;
} else {
revision = 0;
}
u32 temp_key[AES_128_KEY_SIZE / 4] = {0};
se_aes_key_set(ks, new_device_key, AES_128_KEY_SIZE);
se_aes_crypt_ecb(ks, 0, temp_key, AES_128_KEY_SIZE, device_master_key_source_sources[revision], AES_128_KEY_SIZE);
se_aes_key_set(ks, master_key, AES_128_KEY_SIZE);
se_aes_unwrap_key(ks, ks, device_master_kek_sources[revision]);
se_aes_crypt_ecb(ks, 0, out_device_key, AES_128_KEY_SIZE, temp_key, AES_128_KEY_SIZE);
}
static void _derive_misc_keys(key_derivation_ctx_t *keys) {
if (_key_exists(keys->master_key)) {
_generate_kek(8, header_kek_source, keys->master_key, aes_kek_generation_source, aes_key_generation_source);
se_aes_crypt_block_ecb(8, 0, keys->header_key + 0x00, header_key_source + 0x00);
se_aes_crypt_block_ecb(8, 0, keys->header_key + 0x10, header_key_source + 0x10);
}
if (_key_exists(keys->device_key) || (_key_exists(keys->master_key) && _key_exists(keys->device_key_4x))) {
_get_device_key(8, keys->temp_key, 0, keys->device_key, keys->device_key_4x, keys->master_key);
_generate_kek(8, save_mac_kek_source, keys->temp_key, aes_kek_generation_source, NULL);
se_aes_crypt_block_ecb(8, 0, keys->save_mac_key, save_mac_key_source);
}
}
static void _derive_bis_keys(key_derivation_ctx_t *keys) {
/* key = unwrap(source, wrapped_key):
key_set(ks, wrapped_key), block_ecb(ks, 0, key, source) -> final key in key
*/
u32 key_generation = fuse_read_odm_keygen_rev();
if (key_generation)
key_generation--;
if (!(_key_exists(keys->device_key) || (key_generation && _key_exists(keys->master_key) && _key_exists(keys->device_key_4x)))) {
return;
}
_get_device_key(8, keys->temp_key, key_generation, keys->device_key, keys->device_key_4x, keys->master_key);
se_aes_key_set(8, keys->temp_key, AES_128_KEY_SIZE);
se_aes_unwrap_key(8, 8, retail_specific_aes_key_source); // kek = unwrap(rsaks, devkey)
se_aes_crypt_block_ecb(8, 0, keys->bis_key[0] + 0x00, bis_key_source[0] + 0x00); // bkey = unwrap(bkeys, kek)
se_aes_crypt_block_ecb(8, 0, keys->bis_key[0] + 0x10, bis_key_source[0] + 0x10);
// kek = generate_kek(bkeks, devkey, aeskek, aeskey)
_generate_kek(8, bis_kek_source, keys->temp_key, aes_kek_generation_source, aes_key_generation_source);
se_aes_crypt_block_ecb(8, 0, keys->bis_key[1] + 0x00, bis_key_source[1] + 0x00); // bkey = unwrap(bkeys, kek)
se_aes_crypt_block_ecb(8, 0, keys->bis_key[1] + 0x10, bis_key_source[1] + 0x10);
se_aes_crypt_block_ecb(8, 0, keys->bis_key[2] + 0x00, bis_key_source[2] + 0x00);
se_aes_crypt_block_ecb(8, 0, keys->bis_key[2] + 0x10, bis_key_source[2] + 0x10);
}
static int _derive_master_keys_from_keyblobs(key_derivation_ctx_t *keys) {
u8 *keyblob_block = (u8 *)calloc(KB_FIRMWARE_VERSION_600 + 1, NX_EMMC_BLOCKSIZE);
encrypted_keyblob_t *current_keyblob = (encrypted_keyblob_t *)keyblob_block;
u32 keyblob_mac[AES_128_KEY_SIZE / 4] = {0};
keys->sbk[0] = FUSE(FUSE_PRIVATE_KEY0);
keys->sbk[1] = FUSE(FUSE_PRIVATE_KEY1);
keys->sbk[2] = FUSE(FUSE_PRIVATE_KEY2);
keys->sbk[3] = FUSE(FUSE_PRIVATE_KEY3);
if (keys->sbk[0] == 0xFFFFFFFF) {
u8 *aes_keys = (u8 *)calloc(0x1000, 1);
se_get_aes_keys(aes_keys + 0x800, aes_keys, AES_128_KEY_SIZE);
memcpy(keys->sbk, aes_keys + 14 * AES_128_KEY_SIZE, AES_128_KEY_SIZE);
free(aes_keys);
}
se_aes_key_set(8, keys->tsec_keys, sizeof(keys->tsec_keys) / 2);
se_aes_key_set(9, keys->sbk, 0x10);
if (!emummc_storage_read(&emmc_storage, KEYBLOB_OFFSET / NX_EMMC_BLOCKSIZE, KB_FIRMWARE_VERSION_600 + 1, keyblob_block)) {
DPRINTF("Unable to read keyblobs.");
}
se_aes_crypt_block_ecb(8, 0, keys->keyblob_key, keyblob_key_source); // temp = unwrap(kbks, tsec)
se_aes_crypt_block_ecb(9, 0, keys->keyblob_key, keys->keyblob_key); // kbk = unwrap(temp, sbk)
se_aes_key_set(7, keys->keyblob_key, sizeof(keys->keyblob_key));
se_aes_crypt_block_ecb(7, 0, keys->keyblob_mac_key, keyblob_mac_key_source); // kbm = unwrap(kbms, kbk)
se_aes_crypt_block_ecb(7, 0, keys->device_key, per_console_key_source); // devkey = unwrap(pcks, kbk0)
se_aes_crypt_block_ecb(7, 0, keys->device_key_4x, device_master_key_source_kek_source);
se_aes_key_set(10, keys->keyblob_mac_key, sizeof(keys->keyblob_mac_key));
se_aes_cmac(10, keyblob_mac, sizeof(keyblob_mac), current_keyblob->iv, sizeof(current_keyblob->iv) + sizeof(keyblob_t));
if (memcmp(current_keyblob, keyblob_mac, sizeof(keyblob_mac)) != 0) {
//EPRINTFARGS("Keyblob %x corrupt.", 0);
free(keyblob_block);
return true;
}
se_aes_key_set(6, keys->keyblob_key, sizeof(keys->keyblob_key));
se_aes_crypt_ctr(6, &keys->keyblob, sizeof(keyblob_t), &current_keyblob->key_data, sizeof(keyblob_t), current_keyblob->iv);
memcpy(keys->package1_key, keys->keyblob.package1_key, sizeof(keys->package1_key));
memcpy(keys->master_kek, keys->keyblob.master_kek, sizeof(keys->master_kek));
se_aes_key_set(7, keys->master_kek, sizeof(keys->master_kek));
se_aes_crypt_block_ecb(7, 0, keys->master_key, master_key_source);
free(keyblob_block);
return false;
}
static bool _derive_tsec_keys(tsec_ctxt_t *tsec_ctxt, key_derivation_ctx_t *keys) {
tsec_ctxt->fw = _find_tsec_fw(tsec_ctxt->pkg1);
if (!tsec_ctxt->fw) {
DPRINTF("Unable to locate TSEC firmware.");
return false;
}
tsec_ctxt->size = _get_tsec_fw_size((tsec_key_data_t *)(tsec_ctxt->fw + TSEC_KEY_DATA_OFFSET));
if (tsec_ctxt->size > PKG1_MAX_SIZE) {
DPRINTF("Unexpected TSEC firmware size.");
return false;
}
int res = 0;
u32 retries = 0;
mc_disable_ahb_redirect();
while (tsec_query(keys->tsec_keys, tsec_ctxt) < 0) {
memset(keys->tsec_keys, 0, sizeof(keys->tsec_keys));
retries++;
if (retries > 15) {
res = -1;
break;
}
}
mc_enable_ahb_redirect(false);
if (res < 0) {
//EPRINTFARGS("ERROR %x dumping TSEC.\n", res);
return false;
}
return true;
}
static ALWAYS_INLINE u8 *_read_pkg1() {
/*
if (emummc_storage_init_mmc(&emmc_storage, &emmc_sdmmc)) {
DPRINTF("Unable to init MMC.");
return NULL;
}
*/
if (connectMMC(MMC_CONN_EMMC))
return NULL;
// Read package1.
u8 *pkg1 = (u8 *)malloc(PKG1_MAX_SIZE);
if (!emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0)) {
DPRINTF("Unable to set partition.");
return NULL;
}
if (!emummc_storage_read(&emmc_storage, PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1)) {
DPRINTF("Unable to read pkg1.");
return NULL;
}
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header.
char *pkg1txt = calloc(16, 1);
memcpy(pkg1txt, pkg1 + pk1_offset + 0x10, 14);
TConf.pkg1ID = pkg1txt;
return pkg1;
}
key_derivation_ctx_t __attribute__((aligned(4))) dumpedKeys = {0};
int DumpKeys(){
if (h_cfg.t210b01) // i'm not even attempting to dump on mariko
return 2;
u8 *pkg1 = _read_pkg1();
if (!pkg1) {
return 1;
}
bool res = true;
tsec_ctxt_t tsec_ctxt;
tsec_ctxt.pkg1 = pkg1;
res =_derive_tsec_keys(&tsec_ctxt, &dumpedKeys);
free(pkg1);
if (res == false) {
return 1;
}
if (_derive_master_keys_from_keyblobs(&dumpedKeys))
return 1;
_derive_bis_keys(&dumpedKeys);
_derive_misc_keys(&dumpedKeys);
return 0;
}
void PrintKey(u8 *key, u32 len){
for (int i = 0; i < len; i++){
gfx_printf("%02x", key[i]);
}
}