From 2428736bfa74f0281a493474344ab3aac48a9ea8 Mon Sep 17 00:00:00 2001 From: CTCaer Date: Sat, 6 Feb 2021 03:00:48 +0200 Subject: [PATCH] hos: Use structs for eks keyblobs and tsec keys --- bdk/sec/tsec.c | 2 +- bdk/sec/tsec.h | 2 +- bootloader/hos/hos.c | 76 +++++++++++++++++++++++++++++-------------- bootloader/hos/hos.h | 17 +++++----- nyx/nyx_gui/hos/hos.c | 76 +++++++++++++++++++++++++++++-------------- nyx/nyx_gui/hos/hos.h | 19 ++++++----- 6 files changed, 123 insertions(+), 69 deletions(-) diff --git a/bdk/sec/tsec.c b/bdk/sec/tsec.c index 9236dc5..124cfa3 100644 --- a/bdk/sec/tsec.c +++ b/bdk/sec/tsec.c @@ -62,7 +62,7 @@ static int _tsec_dma_pa_to_internal_100(int not_imem, int i_offset, int pa_offse return _tsec_dma_wait_idle(); } -int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) +int tsec_query(void *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) { int res = 0; u8 *fwbuf = NULL; diff --git a/bdk/sec/tsec.h b/bdk/sec/tsec.h index 6206034..c722d42 100644 --- a/bdk/sec/tsec.h +++ b/bdk/sec/tsec.h @@ -29,6 +29,6 @@ typedef struct _tsec_ctxt_t u32 secmon_base; } tsec_ctxt_t; -int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt); +int tsec_query(void *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt); #endif diff --git a/bootloader/hos/hos.c b/bootloader/hos/hos.c index 44b4c5a..9d99449 100644 --- a/bootloader/hos/hos.c +++ b/bootloader/hos/hos.c @@ -75,6 +75,28 @@ typedef struct _secmon_mailbox_t u32 out; } secmon_mailbox_t; +typedef struct _tsec_keys_t +{ + u8 tsec[SE_KEY_128_SIZE]; + u8 tsec_root[SE_KEY_128_SIZE]; + u8 tmp[SE_KEY_128_SIZE]; +} tsec_keys_t; + +typedef struct _kb_keys_t +{ + u8 master_keyseed[SE_KEY_128_SIZE]; + u8 random_data[0x70]; + u8 package1_key[SE_KEY_128_SIZE]; +} kb_keys_t; + +typedef struct _kb_t +{ + u8 cmac[SE_KEY_128_SIZE]; + u8 ctr[SE_AES_IV_SIZE]; + kb_keys_t keys; + u8 padding[0x150]; +} kb_t; + static const u8 keyblob_keyseeds[][SE_KEY_128_SIZE] = { { 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 }, // 1.0.0. { 0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC }, // 3.0.0. @@ -356,10 +378,11 @@ int hos_keygen_t210b01(u32 kb) return 1; } -int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt) +int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt) { - u8 tmp[0x30]; u32 retries = 0; + tsec_keys_t tsec_keys; + kb_t *kb_data = (kb_t *)keyblob; if (kb > KB_FIRMWARE_VERSION_MAX) return 0; @@ -387,9 +410,9 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c // Get TSEC key. if (kb <= KB_FIRMWARE_VERSION_620) { - while (tsec_query(tmp, kb, tsec_ctxt) < 0) + while (tsec_query(&tsec_keys, kb, tsec_ctxt) < 0) { - memset(tmp, 0x00, 0x20); + memset(&tsec_keys, 0x00, 0x20); retries++; // We rely on racing conditions, make sure we cover even the unluckiest cases. @@ -441,14 +464,14 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c else if (kb == KB_FIRMWARE_VERSION_620) { // Set TSEC key. - se_aes_key_set(12, tmp, SE_KEY_128_SIZE); + se_aes_key_set(12, tsec_keys.tsec, SE_KEY_128_SIZE); // Set TSEC root key. - se_aes_key_set(13, tmp + SE_KEY_128_SIZE, SE_KEY_128_SIZE); + se_aes_key_set(13, tsec_keys.tsec_root, SE_KEY_128_SIZE); if (!(emu_cfg.enabled && !h_cfg.emummc_force_disable) && hos_ctxt->stock) { // Package2 key. - se_aes_key_set(8, tmp + SE_KEY_128_SIZE, SE_KEY_128_SIZE); + se_aes_key_set(8, tsec_keys.tsec_root, SE_KEY_128_SIZE); se_aes_unwrap_key(8, 8, master_keyseed_620); se_aes_unwrap_key(8, 8, master_keyseed_retail); se_aes_unwrap_key(8, 8, package2_keyseed); @@ -456,8 +479,8 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c else { // Decrypt keyblob and set keyslots - se_aes_crypt_block_ecb(12, 0, tmp + 0x20, keyblob_keyseeds[0]); - se_aes_unwrap_key(15, 14, tmp + 0x20); + se_aes_crypt_block_ecb(12, 0, tsec_keys.tmp, keyblob_keyseeds[0]); + se_aes_unwrap_key(15, 14, tsec_keys.tmp); se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx); se_aes_unwrap_key(15, 15, console_keyseed); @@ -486,33 +509,36 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG); // Set TSEC key. - se_aes_key_set(13, tmp, SE_KEY_128_SIZE); + se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE); // Derive keyblob keys from TSEC+SBK. - se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]); - se_aes_unwrap_key(15, 14, tmp); - se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[kb]); - se_aes_unwrap_key(13, 14, tmp); + se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[0]); + se_aes_unwrap_key(15, 14, tsec_keys.tsec); + se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[kb]); + se_aes_unwrap_key(13, 14, tsec_keys.tsec); // Clear SBK. se_aes_key_clear(14); - //TODO: verify keyblob CMAC. - //se_aes_unwrap_key(11, 13, cmac_keyseed); - //se_aes_cmac(tmp, 0x10, 11, keyblob + 0x10, 0xA0); - //if (!memcmp(keyblob, tmp, 0x10)) - // return 0; +/* + // Verify keyblob CMAC. + u8 cmac[SE_KEY_128_SIZE]; + se_aes_unwrap_key(11, 13, cmac_keyseed); + se_aes_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)kb_data->ctr, sizeof(kb_data->ctr) + sizeof(kb_data->keys)); + if (!memcmp(kb_data->cmac, cmac, SE_KEY_128_SIZE)) + return 0; +*/ - se_aes_crypt_block_ecb(13, 0, tmp, cmac_keyseed); + se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, cmac_keyseed); se_aes_unwrap_key(11, 13, cmac_keyseed); // Decrypt keyblob and set keyslots. - se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10); - se_aes_key_set(11, keyblob + 0x20 + 0x80, SE_KEY_128_SIZE); // Package1 key. - se_aes_key_set(12, keyblob + 0x20, SE_KEY_128_SIZE); - se_aes_key_set(13, keyblob + 0x20, SE_KEY_128_SIZE); + se_aes_crypt_ctr(13, &kb_data->keys, sizeof(kb_data->keys), &kb_data->keys, sizeof(kb_data->keys), kb_data->ctr); + se_aes_key_set(11, kb_data->keys.package1_key, SE_KEY_128_SIZE); + se_aes_key_set(12, kb_data->keys.master_keyseed, SE_KEY_128_SIZE); + se_aes_key_set(13, kb_data->keys.master_keyseed, SE_KEY_128_SIZE); - se_aes_crypt_block_ecb(12, 0, tmp, master_keyseed_retail); + se_aes_crypt_block_ecb(12, 0, tsec_keys.tsec, master_keyseed_retail); if (!h_cfg.aes_slots_new) { diff --git a/bootloader/hos/hos.h b/bootloader/hos/hos.h index b5900c6..f0f07cd 100644 --- a/bootloader/hos/hos.h +++ b/bootloader/hos/hos.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer + * Copyright (c) 2018-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -20,6 +20,7 @@ #include "pkg1.h" #include "pkg2.h" +#include #include #include #include @@ -56,14 +57,14 @@ typedef struct _exo_ctxt_t typedef struct _hos_eks_keys_t { - u8 mkk[0x10]; - u8 fdk[0x10]; + u8 mkk[SE_KEY_128_SIZE]; + u8 fdk[SE_KEY_128_SIZE]; } hos_eks_keys_t; typedef struct _hos_eks_bis_keys_t { - u8 crypt[0x10]; - u8 tweak[0x10]; + u8 crypt[SE_KEY_128_SIZE]; + u8 tweak[SE_KEY_128_SIZE]; } hos_eks_bis_keys_t; typedef struct _hos_eks_mbr_t @@ -73,8 +74,8 @@ typedef struct _hos_eks_mbr_t u8 enabled_bis; u8 rsvd[2]; u32 lot0; - u8 dkg[0x10]; - u8 dkk[0x10]; + u8 dkg[SE_KEY_128_SIZE]; + u8 dkk[SE_KEY_128_SIZE]; hos_eks_keys_t keys[5]; hos_eks_bis_keys_t bis_keys[3]; } hos_eks_mbr_t; @@ -129,6 +130,6 @@ void hos_eks_get(); void hos_eks_save(u32 kb); void hos_eks_clear(u32 kb); int hos_launch(ini_sec_t *cfg); -int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt); +int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt); #endif diff --git a/nyx/nyx_gui/hos/hos.c b/nyx/nyx_gui/hos/hos.c index dc9eb14..f3f1c13 100644 --- a/nyx/nyx_gui/hos/hos.c +++ b/nyx/nyx_gui/hos/hos.c @@ -45,6 +45,28 @@ extern hekate_config h_cfg; static u8 *bis_keys = NULL; +typedef struct _tsec_keys_t +{ + u8 tsec[SE_KEY_128_SIZE]; + u8 tsec_root[SE_KEY_128_SIZE]; + u8 tmp[SE_KEY_128_SIZE]; +} tsec_keys_t; + +typedef struct _kb_keys_t +{ + u8 master_keyseed[SE_KEY_128_SIZE]; + u8 random_data[0x70]; + u8 package1_key[SE_KEY_128_SIZE]; +} kb_keys_t; + +typedef struct _kb_t +{ + u8 cmac[SE_KEY_128_SIZE]; + u8 ctr[SE_AES_IV_SIZE]; + kb_keys_t keys; + u8 padding[0x150]; +} kb_t; + static const u8 keyblob_keyseeds[][SE_KEY_128_SIZE] = { { 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 }, // 1.0.0. { 0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC }, // 3.0.0. @@ -417,10 +439,11 @@ int hos_keygen_t210b01(u32 kb) return 1; } -int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt) +int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt) { - u8 tmp[0x30]; u32 retries = 0; + tsec_keys_t tsec_keys; + kb_t *kb_data = (kb_t *)keyblob; if (kb > KB_FIRMWARE_VERSION_MAX) return 0; @@ -448,9 +471,9 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt) // Get TSEC key. if (kb <= KB_FIRMWARE_VERSION_620) { - while (tsec_query(tmp, kb, tsec_ctxt) < 0) + while (tsec_query(&tsec_keys, kb, tsec_ctxt) < 0) { - memset(tmp, 0x00, 0x20); + memset(&tsec_keys, 0x00, 0x20); retries++; // We rely on racing conditions, make sure we cover even the unluckiest cases. @@ -489,13 +512,13 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt) else if (kb == KB_FIRMWARE_VERSION_620) { // Set TSEC key. - se_aes_key_set(12, tmp, SE_KEY_128_SIZE); + se_aes_key_set(12, tsec_keys.tsec, SE_KEY_128_SIZE); // Set TSEC root key. - se_aes_key_set(13, tmp + SE_KEY_128_SIZE, SE_KEY_128_SIZE); + se_aes_key_set(13, tsec_keys.tsec_root, SE_KEY_128_SIZE); // Decrypt keyblob and set keyslots - se_aes_crypt_block_ecb(12, 0, tmp + 0x20, keyblob_keyseeds[0]); - se_aes_unwrap_key(15, 14, tmp + 0x20); + se_aes_crypt_block_ecb(12, 0, tsec_keys.tmp, keyblob_keyseeds[0]); + se_aes_unwrap_key(15, 14, tsec_keys.tmp); se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx); se_aes_unwrap_key(15, 15, console_keyseed); @@ -507,33 +530,36 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt) else { // Set TSEC key. - se_aes_key_set(13, tmp, SE_KEY_128_SIZE); + se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE); // Derive keyblob keys from TSEC+SBK. - se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]); - se_aes_unwrap_key(15, 14, tmp); - se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[kb]); - se_aes_unwrap_key(13, 14, tmp); + se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[0]); + se_aes_unwrap_key(15, 14, tsec_keys.tsec); + se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[kb]); + se_aes_unwrap_key(13, 14, tsec_keys.tsec); // Clear SBK. se_aes_key_clear(14); - //TODO: verify keyblob CMAC. - //se_aes_unwrap_key(11, 13, cmac_keyseed); - //se_aes_cmac(tmp, 0x10, 11, keyblob + 0x10, 0xA0); - //if (!memcmp(keyblob, tmp, 0x10)) - // return 0; +/* + // Verify keyblob CMAC. + u8 cmac[SE_KEY_128_SIZE]; + se_aes_unwrap_key(11, 13, cmac_keyseed); + se_aes_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)kb_data->ctr, sizeof(kb_data->ctr) + sizeof(kb_data->keys)); + if (!memcmp(kb_data->cmac, cmac, SE_KEY_128_SIZE)) + return 0; +*/ - se_aes_crypt_block_ecb(13, 0, tmp, cmac_keyseed); + se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, cmac_keyseed); se_aes_unwrap_key(11, 13, cmac_keyseed); // Decrypt keyblob and set keyslots. - se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10); - se_aes_key_set(11, keyblob + 0x20 + 0x80, SE_KEY_128_SIZE); // Package1 key. - se_aes_key_set(12, keyblob + 0x20, SE_KEY_128_SIZE); - se_aes_key_set(13, keyblob + 0x20, SE_KEY_128_SIZE); + se_aes_crypt_ctr(13, &kb_data->keys, sizeof(kb_data->keys), &kb_data->keys, sizeof(kb_data->keys), kb_data->ctr); + se_aes_key_set(11, kb_data->keys.package1_key, SE_KEY_128_SIZE); + se_aes_key_set(12, kb_data->keys.master_keyseed, SE_KEY_128_SIZE); + se_aes_key_set(13, kb_data->keys.master_keyseed, SE_KEY_128_SIZE); - se_aes_crypt_block_ecb(12, 0, tmp, master_keyseed_retail); + se_aes_crypt_block_ecb(12, 0, tsec_keys.tsec, master_keyseed_retail); switch (kb) { @@ -606,7 +632,7 @@ static void _hos_bis_print_key(u32 idx, u8 *key) gfx_puts("\n"); } -int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt) +int hos_bis_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt) { u32 keygen_rev = 0; u32 console_key_slot = kb >= KB_FIRMWARE_VERSION_400 ? 15 : 13; diff --git a/nyx/nyx_gui/hos/hos.h b/nyx/nyx_gui/hos/hos.h index fa93466..6ebb9e1 100644 --- a/nyx/nyx_gui/hos/hos.h +++ b/nyx/nyx_gui/hos/hos.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer + * Copyright (c) 2018-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -20,6 +20,7 @@ #include "pkg1.h" #include "pkg2.h" +#include #include #include #include @@ -44,14 +45,14 @@ typedef struct _hos_eks_keys_t { - u8 mkk[0x10]; - u8 fdk[0x10]; + u8 mkk[SE_KEY_128_SIZE]; + u8 fdk[SE_KEY_128_SIZE]; } hos_eks_keys_t; typedef struct _hos_eks_bis_keys_t { - u8 crypt[0x10]; - u8 tweak[0x10]; + u8 crypt[SE_KEY_128_SIZE]; + u8 tweak[SE_KEY_128_SIZE]; } hos_eks_bis_keys_t; typedef struct _hos_eks_mbr_t @@ -61,8 +62,8 @@ typedef struct _hos_eks_mbr_t u8 enabled_bis; u8 rsvd[2]; u32 lot0; - u8 dkg[0x10]; - u8 dkk[0x10]; + u8 dkg[SE_KEY_128_SIZE]; + u8 dkk[SE_KEY_128_SIZE]; hos_eks_keys_t keys[5]; hos_eks_bis_keys_t bis_keys[3]; } hos_eks_mbr_t; @@ -98,8 +99,8 @@ void hos_eks_save(u32 kb); void hos_eks_clear(u32 kb); void hos_eks_bis_save(); void hos_eks_bis_clear(); -int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt); -int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt); +int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt); +int hos_bis_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt); void hos_bis_keys_clear(); #endif