diff --git a/bootloader/hos/hos.c b/bootloader/hos/hos.c index df7a01f1..7a08e0d9 100644 --- a/bootloader/hos/hos.c +++ b/bootloader/hos/hos.c @@ -66,29 +66,7 @@ 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_kekseed[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[HOS_KB_VERSION_600 - HOS_KB_VERSION_100 + 1][SE_KEY_128_SIZE] = { +static const u8 eks_keyseeds[HOS_MKEY_VER_600 - HOS_MKEY_VER_100 + 1][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. { 0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B }, // 3.0.1. @@ -110,7 +88,7 @@ static const u8 master_kekseed_620[SE_KEY_128_SIZE] = { 0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A }; //!TODO: Update on tsec/mkey changes. -static const u8 master_kekseed_t210_tsec_v4[HOS_KB_VERSION_MAX - HOS_KB_VERSION_810 + 1][SE_KEY_128_SIZE] = { +static const u8 master_kekseed_t210_tsec_v4[HOS_MKEY_VER_MAX - HOS_MKEY_VER_810 + 1][SE_KEY_128_SIZE] = { { 0xDE, 0xDC, 0xE3, 0x39, 0x30, 0x88, 0x16, 0xF8, 0xAE, 0x97, 0xAD, 0xEC, 0x64, 0x2D, 0x41, 0x41 }, // 8.1.0. { 0x1A, 0xEC, 0x11, 0x82, 0x2B, 0x32, 0x38, 0x7A, 0x2B, 0xED, 0xBA, 0x01, 0x47, 0x7E, 0x3B, 0x67 }, // 9.0.0. { 0x30, 0x3F, 0x02, 0x7E, 0xD8, 0x38, 0xEC, 0xD7, 0x93, 0x25, 0x34, 0xB5, 0x30, 0xEB, 0xCA, 0x7A }, // 9.1.0. @@ -126,7 +104,7 @@ static const u8 master_kekseed_t210_tsec_v4[HOS_KB_VERSION_MAX - HOS_KB_VERSION_ }; //!TODO: Update on mkey changes. -static const u8 master_kekseed_t210b01[HOS_KB_VERSION_MAX - HOS_KB_VERSION_600 + 1][SE_KEY_128_SIZE] = { +static const u8 master_kekseed_t210b01[HOS_MKEY_VER_MAX - HOS_MKEY_VER_600 + 1][SE_KEY_128_SIZE] = { { 0x77, 0x60, 0x5A, 0xD2, 0xEE, 0x6E, 0xF8, 0x3C, 0x3F, 0x72, 0xE2, 0x59, 0x9D, 0xAC, 0x5E, 0x56 }, // 6.0.0. { 0x1E, 0x80, 0xB8, 0x17, 0x3E, 0xC0, 0x60, 0xAA, 0x11, 0xBE, 0x1A, 0x4A, 0xA6, 0x6F, 0xE4, 0xAE }, // 6.2.0. { 0x94, 0x08, 0x67, 0xBD, 0x0A, 0x00, 0x38, 0x84, 0x11, 0xD3, 0x1A, 0xDB, 0xDD, 0x8D, 0xF1, 0x8A }, // 7.0.0. @@ -303,13 +281,13 @@ out: } } -static void _hos_eks_clear(u32 kb) +static void _hos_eks_clear(u32 mkey) { // Check if Erista based unit. if (h_cfg.t210b01) return; - if (h_cfg.eks && kb >= HOS_KB_VERSION_700) + if (h_cfg.eks && mkey >= HOS_MKEY_VER_700) { // Check if current Master key is enabled. if (h_cfg.eks->enabled) @@ -338,16 +316,22 @@ out: } } -static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool is_exo) +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; + +static int _hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt, bool stock, bool is_exo) { static bool sbk_is_set = true; u32 retries = 0; bool use_tsec = false; tsec_keys_t tsec_keys; - kb_t *kb_data = (kb_t *)keyblob; - if (kb > HOS_KB_VERSION_MAX) + if (mkey > HOS_MKEY_VER_MAX) return 0; // Do Mariko keygen. @@ -357,7 +341,7 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock se_aes_unwrap_key(10, 14, console_keyseed_4xx); // Derive master key. - se_aes_unwrap_key(7, 12, master_kekseed_t210b01[kb - HOS_KB_VERSION_600]); + se_aes_unwrap_key(7, 12, master_kekseed_t210b01[mkey - HOS_MKEY_VER_600]); se_aes_unwrap_key(7, 7, master_keyseed_retail); // Derive latest pkg2 key. @@ -381,15 +365,15 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock _hos_eks_get(); // Use tsec keygen for old firmware or if EKS keys does not exist for newer. - if (kb <= HOS_KB_VERSION_620 || !h_cfg.eks || (h_cfg.eks->enabled != HOS_EKS_TSEC_VER)) + if (mkey <= HOS_MKEY_VER_620 || !h_cfg.eks || (h_cfg.eks->enabled != HOS_EKS_TSEC_VER)) use_tsec = true; - if (kb <= HOS_KB_VERSION_600) + if (mkey <= HOS_MKEY_VER_600) { tsec_ctxt->size = 0xF00; tsec_ctxt->type = TSEC_FW_TYPE_OLD; } - else if (kb == HOS_KB_VERSION_620) + else if (mkey == HOS_MKEY_VER_620) { tsec_ctxt->size = 0x2900; tsec_ctxt->type = TSEC_FW_TYPE_EMU; @@ -439,7 +423,7 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock } } - if (kb >= HOS_KB_VERSION_700) + if (mkey >= HOS_MKEY_VER_700) { // For 7.0.0 and up, save EKS slot if it doesn't exist. if (use_tsec) @@ -450,8 +434,8 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock // Use 8.1.0 for 7.0.0 otherwise the proper one. u32 mkey_idx = 0; - if (kb >= HOS_KB_VERSION_810) - mkey_idx = kb - HOS_KB_VERSION_810; + if (mkey >= HOS_MKEY_VER_810) + mkey_idx = mkey - HOS_MKEY_VER_810; if (!is_exo) { @@ -462,7 +446,8 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock } else { - se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, keyblob_keyseeds[0]); + // Decrypt eks and set keyslots. + se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0]); se_aes_unwrap_key(15, 14, tsec_keys.tmp); // Derive device keys. @@ -480,7 +465,7 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock se_aes_unwrap_key(8, 13, package2_keyseed); } } - else if (kb == HOS_KB_VERSION_620) + else if (mkey == HOS_MKEY_VER_620) { // Set TSEC key. se_aes_key_set(12, tsec_keys.tsec, SE_KEY_128_SIZE); @@ -497,8 +482,8 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock } else { - // Decrypt keyblob and set keyslots for Exosphere 2. - se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, keyblob_keyseeds[0]); + // Decrypt eks and set keyslots for Exosphere 2. + se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0]); se_aes_unwrap_key(15, 14, tsec_keys.tmp); // Derive device keys. @@ -524,54 +509,54 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock // Set TSEC key. se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE); - // Derive keyblob keys from TSEC+SBK. - se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, keyblob_keyseeds[0]); + // Derive eks keys from TSEC+SBK. + se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[0]); se_aes_unwrap_key(15, 14, tsec_keys.tsec); - se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, keyblob_keyseeds[kb]); + se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[mkey]); se_aes_unwrap_key(13, 14, tsec_keys.tsec); // Clear SBK. //se_aes_key_clear(14); /* - // Verify keyblob CMAC. + // Verify eks 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)) + se_aes_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)eks->ctr, sizeof(eks->ctr) + sizeof(eks->keys)); + if (!memcmp(eks->cmac, cmac, SE_KEY_128_SIZE)) return 0; */ se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, cmac_keyseed); se_aes_unwrap_key(11, 13, cmac_keyseed); - // Decrypt keyblob and set keyslots. - se_aes_crypt_ctr(13, &kb_data->keys, sizeof(kb_keys_t), &kb_data->keys, sizeof(kb_keys_t), 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_kekseed, SE_KEY_128_SIZE); - se_aes_key_set(13, kb_data->keys.master_kekseed, SE_KEY_128_SIZE); + // Decrypt eks and set keyslots. + se_aes_crypt_ctr(13, &eks->keys, sizeof(eks_keys_t), &eks->keys, sizeof(eks_keys_t), eks->ctr); + se_aes_key_set(11, eks->keys.package1_key, SE_KEY_128_SIZE); + se_aes_key_set(12, eks->keys.master_kekseed, SE_KEY_128_SIZE); + se_aes_key_set(13, eks->keys.master_kekseed, SE_KEY_128_SIZE); se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tsec, master_keyseed_retail); if (!is_exo) { - switch (kb) + switch (mkey) { - case HOS_KB_VERSION_100: - case HOS_KB_VERSION_300: - case HOS_KB_VERSION_301: + case HOS_MKEY_VER_100: + case HOS_MKEY_VER_300: + case HOS_MKEY_VER_301: se_aes_unwrap_key(13, 15, console_keyseed); se_aes_unwrap_key(12, 12, master_keyseed_retail); break; - case HOS_KB_VERSION_400: + case HOS_MKEY_VER_400: se_aes_unwrap_key(13, 15, console_keyseed_4xx); se_aes_unwrap_key(15, 15, console_keyseed); se_aes_unwrap_key(14, 12, master_keyseed_4xx); se_aes_unwrap_key(12, 12, master_keyseed_retail); sbk_is_set = false; break; - case HOS_KB_VERSION_500: - case HOS_KB_VERSION_600: + case HOS_MKEY_VER_500: + case HOS_MKEY_VER_600: se_aes_unwrap_key(10, 15, console_keyseed_4xx); se_aes_unwrap_key(15, 15, console_keyseed); se_aes_unwrap_key(14, 12, master_keyseed_4xx); @@ -644,13 +629,15 @@ try_load: return 0; } - gfx_printf("Identified pkg1 and mkey %d\n\n", ctxt->pkg1_id->kb); + gfx_printf("Identified pkg1 and mkey %d\n\n", ctxt->pkg1_id->mkey); - // Read the correct keyblob for older HOS versions. - if (ctxt->pkg1_id->kb <= HOS_KB_VERSION_600) + // Read the correct eks for older HOS versions. + if (ctxt->pkg1_id->mkey <= HOS_MKEY_VER_600) { - ctxt->keyblob = (u8 *)zalloc(EMMC_BLOCKSIZE); - emummc_storage_read(PKG1_HOS_KEYBLOBS_OFFSET / EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob); + const u32 eks_size = sizeof(pkg1_eks_t); + ctxt->eks = (pkg1_eks_t *)malloc(eks_size); + emummc_storage_read(PKG1_HOS_EKS_OFFSET + (ctxt->pkg1_id->mkey * eks_size) / EMMC_BLOCKSIZE, + eks_size / EMMC_BLOCKSIZE, ctxt->eks); } return 1; @@ -699,7 +686,7 @@ static void _free_launch_components(launch_ctxt_t *ctxt) { // Free the malloc'ed guaranteed addresses. free(ctxt->pkg3); - free(ctxt->keyblob); + free(ctxt->eks); free(ctxt->pkg1); free(ctxt->pkg2); free(ctxt->warmboot); @@ -750,7 +737,7 @@ static bool _get_fs_exfat_compatible(link_t *info, u32 *hos_revision) void hos_launch(ini_sec_t *cfg) { - u8 kb; + u8 mkey; u32 secmon_base; u32 warmboot_base; bool is_exo = false; @@ -792,7 +779,7 @@ void hos_launch(ini_sec_t *cfg) goto error; } - // Read package1 and the correct keyblob. + // Read package1 and the correct eks. if (!_read_emmc_pkg1(&ctxt)) { // Check if stock is enabled and device can boot in OFW. @@ -809,7 +796,7 @@ void hos_launch(ini_sec_t *cfg) goto error; } - kb = ctxt.pkg1_id->kb; + mkey = ctxt.pkg1_id->mkey; bool emummc_enabled = emu_cfg.enabled && !h_cfg.emummc_force_disable; @@ -874,7 +861,7 @@ void hos_launch(ini_sec_t *cfg) tsec_ctxt.pkg11_off = ctxt.pkg1_id->pkg11_off; // Generate keys. - if (!_hos_keygen(ctxt.keyblob, kb, &tsec_ctxt, ctxt.stock, is_exo)) + if (!_hos_keygen(ctxt.eks, mkey, &tsec_ctxt, ctxt.stock, is_exo)) goto error; gfx_puts("Generated keys\n"); @@ -882,7 +869,7 @@ void hos_launch(ini_sec_t *cfg) if (!ctxt.warmboot || !ctxt.secmon) { // Decrypt PK1 or PK11. - if (kb <= HOS_KB_VERSION_600 || h_cfg.t210b01) + if (mkey <= HOS_MKEY_VER_600 || h_cfg.t210b01) { if (!pkg1_decrypt(ctxt.pkg1_id, ctxt.pkg1)) { @@ -903,7 +890,7 @@ void hos_launch(ini_sec_t *cfg) } // Unpack PK11. - if (h_cfg.t210b01 || (kb <= HOS_KB_VERSION_620 && !emummc_enabled)) + if (h_cfg.t210b01 || (mkey <= HOS_MKEY_VER_620 && !emummc_enabled)) { // Skip T210B01 OEM header. u32 pk1_offset = 0; @@ -924,7 +911,7 @@ void hos_launch(ini_sec_t *cfg) } // Configure and manage Warmboot binary. - if (!pkg1_warmboot_config(&ctxt, warmboot_base, ctxt.pkg1_id->fuses, kb)) + if (!pkg1_warmboot_config(&ctxt, warmboot_base, ctxt.pkg1_id->fuses, mkey)) { // Can only happen on T210B01. _hos_crit_error("\nFailed to match warmboot with fuses!\nIf you continue, sleep wont work!"); @@ -942,7 +929,7 @@ void hos_launch(ini_sec_t *cfg) else if (!h_cfg.t210b01) { // Patch warmboot on T210 to allow downgrading. - if (kb >= HOS_KB_VERSION_700) + if (mkey >= HOS_MKEY_VER_700) { _hos_crit_error("No warmboot provided!"); goto error; @@ -970,13 +957,13 @@ void hos_launch(ini_sec_t *cfg) gfx_puts("Read pkg2\n"); // Decrypt package2 and parse KIP1 blobs in INI1 section. - pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2, kb, is_exo); + pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2, mkey, is_exo); if (!pkg2_hdr) { _hos_crit_error("Pkg2 decryption failed!\npkg1/pkg2 mismatch or old hekate!"); // Clear EKS slot, in case something went wrong with tsec keygen. - _hos_eks_clear(kb); + _hos_eks_clear(mkey); goto error; } @@ -1043,7 +1030,7 @@ void hos_launch(ini_sec_t *cfg) pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1); // Check if FS is compatible with exFAT and if 5.1.0. - if (!ctxt.stock && (sd_fs.fs_type == FS_EXFAT || kb == HOS_KB_VERSION_500 || ctxt.pkg1_id->fuses == 13)) + if (!ctxt.stock && (sd_fs.fs_type == FS_EXFAT || mkey == HOS_MKEY_VER_500 || ctxt.pkg1_id->fuses == 13)) { bool exfat_compat = _get_fs_exfat_compatible(&kip1_info, &ctxt.exo_ctx.hos_revision); @@ -1099,25 +1086,25 @@ void hos_launch(ini_sec_t *cfg) u32 pkg1_state_pkg2_ready = PKG1_STATE_PKG2_READY; // Finalize per firmware key access. Skip access control if Exosphere 2. - switch (kb | (is_exo << 7)) + switch (mkey | (is_exo << 7)) { - case HOS_KB_VERSION_100: - case HOS_KB_VERSION_300: - case HOS_KB_VERSION_301: + case HOS_MKEY_VER_100: + case HOS_MKEY_VER_300: + case HOS_MKEY_VER_301: se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG); se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG); pkg1_state_pkg2_ready = PKG1_STATE_PKG2_READY_OLD; break; - case HOS_KB_VERSION_400: - case HOS_KB_VERSION_500: - case HOS_KB_VERSION_600: + case HOS_MKEY_VER_400: + case HOS_MKEY_VER_500: + case HOS_MKEY_VER_600: se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG); se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG); break; } // Clear BCT area for retail units and copy it over if dev unit. - if (kb <= HOS_KB_VERSION_500 && !is_exo) + if (mkey <= HOS_MKEY_VER_500 && !is_exo) { memset((void *)SECMON_BCT_CFG_ADDR, 0, SZ_4K + SZ_8K); if (fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV) @@ -1131,11 +1118,11 @@ void hos_launch(ini_sec_t *cfg) } // Finalize MC carveout. - if (kb <= HOS_KB_VERSION_301 && !is_exo) + if (mkey <= HOS_MKEY_VER_301 && !is_exo) mc_config_carveout(); - // Lock SE before starting 'SecureMonitor' if < 6.2.0, otherwise lock bootrom and ipatches. - _se_lock(kb <= HOS_KB_VERSION_600 && !is_exo); + // Lock SE before starting secmon if < 6.2.0, otherwise lock bootrom and ipatches. + _se_lock(mkey <= HOS_MKEY_VER_600 && !is_exo); // Reset sysctr0 counters. Mandatory for 6.2.0 and up. for (u32 i = 0; i < SYSCTR0_COUNTERS; i++) @@ -1146,14 +1133,14 @@ void hos_launch(ini_sec_t *cfg) // Set secmon mailbox address and clear it. volatile secmon_mailbox_t *secmon_mailbox; - if (kb >= HOS_KB_VERSION_700 || is_exo) + if (mkey >= HOS_MKEY_VER_700 || is_exo) { memset((void *)SECMON7_MAILBOX_ADDR, 0, 0x200); secmon_mailbox = (secmon_mailbox_t *)(SECMON7_MAILBOX_ADDR + SECMON_STATE_OFFSET); } else { - if (kb <= HOS_KB_VERSION_301) + if (mkey <= HOS_MKEY_VER_301) memset((void *)SECMON_MAILBOX_ADDR, 0, 0x200); secmon_mailbox = (secmon_mailbox_t *)(SECMON_MAILBOX_ADDR + SECMON_STATE_OFFSET); } @@ -1162,7 +1149,7 @@ void hos_launch(ini_sec_t *cfg) secmon_mailbox->in = pkg1_state_pkg2_ready; secmon_mailbox->out = SECMON_STATE_NOT_READY; - // Disable display. This must be executed before secmon to provide support for all fw versions. + // Disable display. display_end(); clock_disable_host1x(); diff --git a/bootloader/hos/hos.h b/bootloader/hos/hos.h index a04f6509..e209c553 100644 --- a/bootloader/hos/hos.h +++ b/bootloader/hos/hos.h @@ -27,34 +27,34 @@ //!TODO: Update on mkey changes. enum { - HOS_KB_VERSION_100 = 0, - HOS_KB_VERSION_300 = 1, - HOS_KB_VERSION_301 = 2, - HOS_KB_VERSION_400 = 3, - HOS_KB_VERSION_500 = 4, - HOS_KB_VERSION_600 = 5, - HOS_KB_VERSION_620 = 6, - HOS_KB_VERSION_700 = 7, - HOS_KB_VERSION_810 = 8, - HOS_KB_VERSION_900 = 9, - HOS_KB_VERSION_910 = 10, - HOS_KB_VERSION_1210 = 11, - HOS_KB_VERSION_1300 = 12, - HOS_KB_VERSION_1400 = 13, - HOS_KB_VERSION_1500 = 14, - HOS_KB_VERSION_1600 = 15, - HOS_KB_VERSION_1700 = 16, - HOS_KB_VERSION_1800 = 17, - HOS_KB_VERSION_1900 = 18, - HOS_KB_VERSION_2000 = 19, - HOS_KB_VERSION_MAX = HOS_KB_VERSION_2000 + HOS_MKEY_VER_100 = 0, + HOS_MKEY_VER_300 = 1, + HOS_MKEY_VER_301 = 2, + HOS_MKEY_VER_400 = 3, + HOS_MKEY_VER_500 = 4, + HOS_MKEY_VER_600 = 5, + HOS_MKEY_VER_620 = 6, + HOS_MKEY_VER_700 = 7, + HOS_MKEY_VER_810 = 8, + HOS_MKEY_VER_900 = 9, + HOS_MKEY_VER_910 = 10, + HOS_MKEY_VER_1210 = 11, + HOS_MKEY_VER_1300 = 12, + HOS_MKEY_VER_1400 = 13, + HOS_MKEY_VER_1500 = 14, + HOS_MKEY_VER_1600 = 15, + HOS_MKEY_VER_1700 = 16, + HOS_MKEY_VER_1800 = 17, + HOS_MKEY_VER_1900 = 18, + HOS_MKEY_VER_2000 = 19, + HOS_MKEY_VER_MAX = HOS_MKEY_VER_2000 }; #define HOS_TSEC_VERSION 4 //! TODO: Update on TSEC Root Key changes. #define HOS_PKG11_MAGIC 0x31314B50 #define HOS_EKS_MAGIC 0x31534B45 // EKS1. -#define HOS_EKS_TSEC_VER (HOS_KB_VERSION_700 + HOS_TSEC_VERSION) +#define HOS_EKS_TSEC_VER (HOS_MKEY_VER_700 + HOS_TSEC_VERSION) // Use official Mariko secmon when in stock. Needs access to TZRAM. //#define HOS_MARIKO_STOCK_SECMON @@ -84,7 +84,7 @@ static_assert(sizeof(hos_eks_mbr_t) == 64, "HOS EKS size is wrong!"); typedef struct _launch_ctxt_t { - void *keyblob; + pkg1_eks_t *eks; void *pkg1; const pkg1_id_t *pkg1_id; diff --git a/bootloader/hos/pkg1.c b/bootloader/hos/pkg1.c index 618870b9..c801b2b8 100644 --- a/bootloader/hos/pkg1.c +++ b/bootloader/hos/pkg1.c @@ -141,7 +141,7 @@ static const u8 sec_map_100[3] = { PK11_SECTION_SM, PK11_SECTION_LD, PK11_SECTIO static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTION_SM }; static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB }; - // Timestamp KB FU TSEC PK11 SECMON Warmboot + // Timestamp MK FU TSEC PK11 SECMON Warmboot static const pkg1_id_t _pkg1_ids[] = { { "20161121", 0, 1, 0x1900, 0x3FE0, SM_100_ADR, 0x8000D000, _secmon_1_patchset }, // 1.0.0 (Patched relocator). { "20170210", 0, 2, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_2_patchset }, // 2.0.0 - 2.3.0. @@ -280,9 +280,9 @@ void pkg1_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01) else if (t210b01) { // For T210B01 we patch 6.X.X as is. Otherwise we decompress the program payload. - if (ctxt->pkg1_id->kb == HOS_KB_VERSION_600) + if (ctxt->pkg1_id->mkey == HOS_MKEY_VER_600) secmon_patchset = _secmon_6_mariko_patchset; - else if (ctxt->pkg1_id->kb == HOS_KB_VERSION_620) + else if (ctxt->pkg1_id->mkey == HOS_MKEY_VER_620) secmon_patchset = _secmon_620_mariko_patchset; else { @@ -291,9 +291,9 @@ void pkg1_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01) memset((void *)TZRAM_PROG_ADDR, 0, 0x38800); // Get size of compressed program payload and set patch offset. - u32 idx = ctxt->pkg1_id->kb - HOS_KB_VERSION_700; + u32 idx = ctxt->pkg1_id->mkey - HOS_MKEY_VER_700; u32 patch_offset = TZRAM_PROG_PK2_SIG_PATCH; - if (ctxt->pkg1_id->kb > HOS_KB_VERSION_910 || !memcmp(ctxt->pkg1_id->id, "20200303", 8)) //TODO: Add 11.0.0 support. + if (ctxt->pkg1_id->mkey >= HOS_MKEY_VER_1210 || !memcmp(ctxt->pkg1_id->id, "20200303", 8)) //TODO: Add 11.0.0 support. { idx++; patch_offset = TZRAM_PROG_PK2_SIG_PATCH_1000; @@ -323,7 +323,7 @@ void pkg1_warmboot_patch(void *hos_ctxt) const patch_t *warmboot_patchset; // Patch warmboot on T210 to allow downgrading. - switch (ctxt->pkg1_id->kb) + switch (ctxt->pkg1_id->mkey) { case 0: warmboot_patchset = _warmboot_1_patchset; @@ -352,7 +352,7 @@ static void _warmboot_filename(char *out, u32 fuses) strcat(out, ".bin"); } -int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base, u32 fuses_fw, u8 kb) +int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base, u32 fuses_fw, u8 mkey) { launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt; int res = 1; @@ -420,15 +420,16 @@ int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base, u32 fuses_fw, u8 kb) } else { - // Set warmboot address in PMC if required. - if (kb <= HOS_KB_VERSION_301) + // Set Warmboot address in PMC if required. + if (mkey <= HOS_MKEY_VER_301) PMC(APBDEV_PMC_SCRATCH1) = warmboot_base; - // Set Warmboot Physical Address ID for 3.0.0 - 3.0.2. - if (kb == HOS_KB_VERSION_300) - PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0xE3; // Warmboot 3.0.0 PA address id. - else if (kb == HOS_KB_VERSION_301) - PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA address id. + // Set Warmboot Physical Address ID for 3.0.0 - 3.0.2. For 4.0.0 and up, secmon does it. + // The check is already patched so it's actually irrelevant. + if (mkey == HOS_MKEY_VER_300) + PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0xE3; // Warmboot 3.0.0 PA ID. + else if (mkey == HOS_MKEY_VER_301) + PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA ID. } return res; diff --git a/bootloader/hos/pkg1.h b/bootloader/hos/pkg1.h index c0dab9a8..4852f732 100644 --- a/bootloader/hos/pkg1.h +++ b/bootloader/hos/pkg1.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2022-2024 CTCaer + * Copyright (c) 2022-2025 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, @@ -29,7 +29,7 @@ #define PKG1_BOOTLOADER_SIZE SZ_256K #define PKG1_BOOTLOADER_MAIN_OFFSET 0x100000 #define PKG1_BOOTLOADER_BACKUP_OFFSET 0x140000 -#define PKG1_HOS_KEYBLOBS_OFFSET 0x180000 +#define PKG1_HOS_EKS_OFFSET 0x180000 #define PKG1_ERISTA_ON_MARIKO_MAGIC 0xE59FD00C // For 4.0.0 Erista and up. #define PKG1_MARIKO_ON_ERISTA_MAGIC 0x40010040 // Mariko pkg1 entrypoint. @@ -59,6 +59,21 @@ typedef struct _bl_hdr_t210b01_t /* 0x160 */ u8 rsvd[0x10]; } bl_hdr_t210b01_t; +typedef struct _eks_keys_t +{ + u8 master_kekseed[SE_KEY_128_SIZE]; + u8 random_data[0x70]; + u8 package1_key[SE_KEY_128_SIZE]; +} eks_keys_t; + +typedef struct _pkg1_eks_t +{ + u8 cmac[SE_KEY_128_SIZE]; + u8 ctr[SE_AES_IV_SIZE]; + eks_keys_t keys; + u8 padding[0x150]; +} pkg1_eks_t; + typedef struct _pk1_hdr_t { /* 0x00 */ u32 si_sha256; // Secure Init. @@ -73,7 +88,7 @@ typedef struct _pk1_hdr_t typedef struct _pkg1_id_t { const char *id; - u16 kb; + u16 mkey; u16 fuses; u16 tsec_off; u16 pkg11_off; @@ -84,14 +99,14 @@ typedef struct _pkg1_id_t typedef struct _pk11_hdr_t { - u32 magic; - u32 wb_size; - u32 wb_off; - u32 pad; - u32 ldr_size; - u32 ldr_off; - u32 sm_size; - u32 sm_off; +/* 0x00 */ u32 magic; +/* 0x04 */ u32 wb_size; +/* 0x08 */ u32 wb_off; +/* 0x0C */ u32 pad; +/* 0x10 */ u32 ldr_size; +/* 0x14 */ u32 ldr_off; +/* 0x18 */ u32 sm_size; +/* 0x1C */ u32 sm_off; } pk11_hdr_t; const pkg1_id_t *pkg1_get_latest(); @@ -100,7 +115,7 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1); const u8 *pkg1_unpack(void *wm_dst, u32 *wb_sz, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1); void pkg1_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01); void pkg1_warmboot_patch(void *hos_ctxt); -int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base, u32 fuses_fw, u8 kb); +int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base, u32 fuses_fw, u8 mkey); void pkg1_warmboot_rsa_mod(u32 warmboot_base); #endif diff --git a/bootloader/hos/pkg2.c b/bootloader/hos/pkg2.c index e8b4aad3..b13b3b4e 100644 --- a/bootloader/hos/pkg2.c +++ b/bootloader/hos/pkg2.c @@ -38,16 +38,6 @@ u32 pkg2_newkern_ini1_start; u32 pkg2_newkern_ini1_end; u32 pkg2_newkern_ini1_rela; -enum kip_offset_section -{ - KIP_TEXT = 0, - KIP_RODATA = 1, - KIP_DATA = 2, - KIP_BSS = 3, - KIP_UNKSEC1 = 4, - KIP_UNKSEC2 = 5 -}; - #define KIP_PATCH_SECTION_SHIFT (29) #define KIP_PATCH_SECTION_MASK (7 << KIP_PATCH_SECTION_SHIFT) #define KIP_PATCH_OFFSET_MASK (~KIP_PATCH_SECTION_MASK) @@ -697,7 +687,7 @@ static const u8 mkey_vector_7xx[SE_KEY_128_SIZE] = { 0xEA, 0x60, 0xB3, 0xEA, 0xCE, 0x8F, 0x24, 0x46, 0x7D, 0x33, 0x9C, 0xD1, 0xBC, 0x24, 0x98, 0x29 }; u8 pkg2_keyslot; -pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb, bool is_exo) +pkg2_hdr_t *pkg2_decrypt(void *data, u8 mkey, bool is_exo) { u8 *pdata = (u8 *)data; @@ -713,7 +703,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb, bool is_exo) pkg2_keyslot = 8; // Decrypt 7.0.0 pkg2 via 8.1.0 mkey on Erista. - if (!h_cfg.t210b01 && kb == HOS_KB_VERSION_700) + if (!h_cfg.t210b01 && mkey == HOS_MKEY_VER_700) { u8 tmp_mkey[SE_KEY_128_SIZE]; @@ -802,7 +792,7 @@ void pkg2_build_encrypt(void *dst, void *hos_ctxt, link_t *kips_info, bool is_ex launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt; u32 meso_magic = *(u32 *)(ctxt->kernel + 4); u32 kernel_size = ctxt->kernel_size; - u8 kb = ctxt->pkg1_id->kb; + u8 mkey = ctxt->pkg1_id->mkey; u8 *pdst = (u8 *)dst; // Force new Package2 if Mesosphere. @@ -811,10 +801,10 @@ void pkg2_build_encrypt(void *dst, void *hos_ctxt, link_t *kips_info, bool is_ex ctxt->new_pkg2 = true; // Set key version. For Erista 7.0.0, use 8.1.0 because of a bug in Exo2? - u8 key_ver = kb ? kb + 1 : 0; + u8 key_ver = mkey ? mkey + 1 : 0; if (pkg2_keyslot == 9) { - key_ver = HOS_KB_VERSION_810 + 1; + key_ver = HOS_MKEY_VER_810 + 1; pkg2_keyslot = 8; } diff --git a/bootloader/hos/pkg2.h b/bootloader/hos/pkg2.h index 551e46e7..f8a775dd 100644 --- a/bootloader/hos/pkg2.h +++ b/bootloader/hos/pkg2.h @@ -90,6 +90,18 @@ typedef struct _pkg2_ini1_t u32 pad; } pkg2_ini1_t; +enum kip_offset_section +{ + KIP_TEXT = 0, + KIP_RODATA = 1, + KIP_DATA = 2, + KIP_BSS = 3, + KIP_UNKSEC1 = 4, + KIP_UNKSEC2 = 5 +}; + +#define KIP1_NUM_SECTIONS 6 + typedef struct _pkg2_kip1_sec_t { u32 offset; @@ -98,12 +110,10 @@ typedef struct _pkg2_kip1_sec_t u32 attrib; } pkg2_kip1_sec_t; -#define KIP1_NUM_SECTIONS 6 - typedef struct _pkg2_kip1_t { /* 0x000 */ u32 magic; -/* 0x004 */ u8 name[12]; +/* 0x004 */ char name[12]; /* 0x010 */ u64 tid; /* 0x018 */ u32 proc_cat; /* 0x01C */ u8 main_thrd_prio; @@ -160,7 +170,7 @@ void pkg2_get_ids(kip1_id_t **ids, u32 *entries); const char *pkg2_patch_kips(link_t *info, char *patch_names); const pkg2_kernel_id_t *pkg2_identify(const u8 *hash); -pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb, bool is_exo); +pkg2_hdr_t *pkg2_decrypt(void *data, u8 mkey, bool is_exo); void pkg2_build_encrypt(void *dst, void *hos_ctxt, link_t *kips_info, bool is_exo); #endif diff --git a/bootloader/hos/pkg3.c b/bootloader/hos/pkg3.c index 8ac885fc..7356906f 100644 --- a/bootloader/hos/pkg3.c +++ b/bootloader/hos/pkg3.c @@ -133,7 +133,7 @@ int parse_pkg3(launch_ctxt_t *ctxt, const char *path) bool experimental = false; // Skip if stock and Exosphere and warmboot are not needed. - bool pkg1_old = ctxt->pkg1_id->kb <= HOS_KB_VERSION_620; // Should check if t210b01? + bool pkg1_old = ctxt->pkg1_id->mkey <= HOS_MKEY_VER_620; // Should check if t210b01? bool emummc_disabled = !emu_cfg.enabled || h_cfg.emummc_force_disable; LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link) diff --git a/bootloader/hos/secmon_exo.c b/bootloader/hos/secmon_exo.c index 57938649..95f440fc 100644 --- a/bootloader/hos/secmon_exo.c +++ b/bootloader/hos/secmon_exo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2024 CTCaer + * Copyright (c) 2018-2025 CTCaer * Copyright (c) 2019 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it @@ -155,8 +155,8 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base) //! TODO: Replace current HOS version decoding (as it's bound to break in the future). // Old exosphere target versioning. - if (ctxt->pkg1_id->kb >= HOS_KB_VERSION_1210) // 12.1.0+ - exo_fw_no = ctxt->pkg1_id->kb + 4; + if (ctxt->pkg1_id->mkey >= HOS_MKEY_VER_1210) // 12.1.0+ + exo_fw_no = ctxt->pkg1_id->mkey + 4; else if (ctxt->pkg1_id->fuses <= 3 || ctxt->pkg1_id->fuses >= 10) // 1.0.0 - 3.0.0, 8.1.0 - 12.0.3. exo_fw_no = ctxt->pkg1_id->fuses; else @@ -169,7 +169,7 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base) exo_fw_no++; // Set 12.1.0 specific revision. - if (ctxt->pkg1_id->kb == HOS_KB_VERSION_1210) + if (ctxt->pkg1_id->mkey == HOS_MKEY_VER_1210) ctxt->exo_ctx.hos_revision = 1; // Feed old exosphere target versioning to new. diff --git a/nyx/nyx_gui/frontend/fe_emummc_tools.c b/nyx/nyx_gui/frontend/fe_emummc_tools.c index 77ea045e..d44e724c 100644 --- a/nyx/nyx_gui/frontend/fe_emummc_tools.c +++ b/nyx/nyx_gui/frontend/fe_emummc_tools.c @@ -33,7 +33,6 @@ #define OUT_FILENAME_SZ 128 #define NUM_SECTORS_PER_ITER 8192 // 4MB Cache. -extern hekate_config h_cfg; extern volatile boot_cfg_t *b_cfg; void load_emummc_cfg(emummc_cfg_t *emu_info) diff --git a/nyx/nyx_gui/frontend/gui_tools.c b/nyx/nyx_gui/frontend/gui_tools.c index e97f45a3..b6a9d761 100644 --- a/nyx/nyx_gui/frontend/gui_tools.c +++ b/nyx/nyx_gui/frontend/gui_tools.c @@ -1142,7 +1142,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn) char path[128]; - u8 kb = 0; + u8 mkey = 0; u8 *pkg1 = (u8 *)zalloc(SZ_256K); u8 *warmboot = (u8 *)zalloc(SZ_256K); u8 *secmon = (u8 *)zalloc(SZ_256K); @@ -1163,7 +1163,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn) // Read package1. static const u32 BOOTLOADER_SIZE = SZ_256K; static const u32 BOOTLOADER_MAIN_OFFSET = 0x100000; - static const u32 HOS_KEYBLOBS_OFFSET = 0x180000; + static const u32 HOS_EKS_OFFSET = 0x180000; char *build_date = malloc(32); u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header. @@ -1197,22 +1197,25 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn) goto out_free; } - kb = pkg1_id->kb; + mkey = pkg1_id->mkey; tsec_ctxt_t tsec_ctxt = {0}; tsec_ctxt.fw = (void *)(pkg1 + pkg1_id->tsec_off); tsec_ctxt.pkg1 = (void *)pkg1; tsec_ctxt.pkg11_off = pkg1_id->pkg11_off; - // Read keyblob. - u8 *keyblob = (u8 *)zalloc(EMMC_BLOCKSIZE); - sdmmc_storage_read(&emmc_storage, HOS_KEYBLOBS_OFFSET / EMMC_BLOCKSIZE + kb, 1, keyblob); + // Read the correct eks for older HOS versions. + const u32 eks_size = sizeof(pkg1_eks_t); + pkg1_eks_t *eks = (pkg1_eks_t *)malloc(eks_size); + emmc_set_partition(EMMC_BOOT0); + sdmmc_storage_read(&emmc_storage, HOS_EKS_OFFSET + (mkey * eks_size) / EMMC_BLOCKSIZE, + eks_size / EMMC_BLOCKSIZE, eks); - // Decrypt. - hos_keygen(keyblob, kb, &tsec_ctxt); - free(keyblob); + // Generate keys. + hos_keygen(eks, mkey, &tsec_ctxt); + free(eks); - if (h_cfg.t210b01 || kb <= HOS_KB_VERSION_600) + if (h_cfg.t210b01 || mkey <= HOS_MKEY_VER_600) { if (!pkg1_decrypt(pkg1_id, pkg1)) { @@ -1224,7 +1227,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn) } } - if (h_cfg.t210b01 || kb <= HOS_KB_VERSION_620) + if (h_cfg.t210b01 || mkey <= HOS_MKEY_VER_620) { pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1 + pk1_offset); pk11_hdr_t *hdr_pk11 = (pk11_hdr_t *)(pkg1 + pk1_offset + pkg1_id->pkg11_off + 0x20); @@ -1312,7 +1315,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn) res = sd_save_to_file(pkg2, pkg2_size, path); // Decrypt package2 and parse KIP1 blobs in INI1 section. - pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, kb); + pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, mkey); if (!pkg2_hdr) { strcat(txt_buf, "#FFDD00 Pkg2 decryption failed!#"); @@ -1327,7 +1330,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn) } // Clear EKS slot, in case something went wrong with tsec keygen. - hos_eks_clear(kb); + hos_eks_clear(mkey); goto out; } @@ -1428,7 +1431,7 @@ out_free: emmc_end(); sd_unmount(); - if (kb >= HOS_KB_VERSION_620) + if (mkey >= HOS_MKEY_VER_620) se_aes_key_clear(8); out_end: // Enable buttons. diff --git a/nyx/nyx_gui/hos/hos.c b/nyx/nyx_gui/hos/hos.c index f6fa5969..ac1d5820 100644 --- a/nyx/nyx_gui/hos/hos.c +++ b/nyx/nyx_gui/hos/hos.c @@ -28,29 +28,7 @@ u8 *cal0_buf = NULL; 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_kekseed[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[HOS_KB_VERSION_600 - HOS_KB_VERSION_100 + 1][SE_KEY_128_SIZE] = { +static const u8 eks_keyseeds[HOS_MKEY_VER_600 - HOS_MKEY_VER_100 + 1][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. { 0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B }, // 3.0.1. @@ -77,7 +55,7 @@ static const u8 master_kekseed_t210_max[SE_KEY_128_SIZE] = { 0xA1, 0x7D, 0x34, 0xDB, 0x2D, 0x9D, 0xDA, 0xE5, 0xF8, 0x15, 0x63, 0x4C, 0x8F, 0xE7, 0x6C, 0xD8 }; // 20.0.0. //!TODO: Update on mkey changes. -static const u8 master_kekseed_t210b01[HOS_KB_VERSION_MAX - HOS_KB_VERSION_600 + 1][SE_KEY_128_SIZE] = { +static const u8 master_kekseed_t210b01[HOS_MKEY_VER_MAX - HOS_MKEY_VER_600 + 1][SE_KEY_128_SIZE] = { { 0x77, 0x60, 0x5A, 0xD2, 0xEE, 0x6E, 0xF8, 0x3C, 0x3F, 0x72, 0xE2, 0x59, 0x9D, 0xAC, 0x5E, 0x56 }, // 6.0.0. { 0x1E, 0x80, 0xB8, 0x17, 0x3E, 0xC0, 0x60, 0xAA, 0x11, 0xBE, 0x1A, 0x4A, 0xA6, 0x6F, 0xE4, 0xAE }, // 6.2.0. { 0x94, 0x08, 0x67, 0xBD, 0x0A, 0x00, 0x38, 0x84, 0x11, 0xD3, 0x1A, 0xDB, 0xDD, 0x8D, 0xF1, 0x8A }, // 7.0.0. @@ -105,7 +83,7 @@ const u8 package2_keyseed[SE_KEY_128_SIZE] = { 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 }; //!TODO: Update on mkey changes. -static const u8 mkey_vectors[HOS_KB_VERSION_MAX + 1][SE_KEY_128_SIZE] = { +static const u8 mkey_vectors[HOS_MKEY_VER_MAX + 1][SE_KEY_128_SIZE] = { { 0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D }, // Zeroes encrypted with mkey 00. { 0x29, 0x4C, 0x04, 0xC8, 0xEB, 0x10, 0xED, 0x9D, 0x51, 0x64, 0x97, 0xFB, 0xF3, 0x4D, 0x50, 0xDD }, // Mkey 00 encrypted with mkey 01. { 0xDE, 0xCF, 0xEB, 0xEB, 0x10, 0xAE, 0x74, 0xD8, 0xAD, 0x7C, 0xF4, 0x9E, 0x62, 0xE0, 0xE8, 0x72 }, // Mkey 01 encrypted with mkey 02. @@ -129,7 +107,7 @@ static const u8 mkey_vectors[HOS_KB_VERSION_MAX + 1][SE_KEY_128_SIZE] = { }; //!TODO: Update on mkey changes. -static const u8 new_console_keyseed[HOS_KB_VERSION_MAX - HOS_KB_VERSION_400 + 1][SE_KEY_128_SIZE] = { +static const u8 new_console_keyseed[HOS_MKEY_VER_MAX - HOS_MKEY_VER_400 + 1][SE_KEY_128_SIZE] = { { 0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D }, // 4.x New Device Key Source. { 0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C }, // 5.x New Device Key Source. { 0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4 }, // 6.x New Device Key Source. @@ -150,7 +128,7 @@ static const u8 new_console_keyseed[HOS_KB_VERSION_MAX - HOS_KB_VERSION_400 + 1] }; //!TODO: Update on mkey changes. -static const u8 new_console_kekseed[HOS_KB_VERSION_MAX - HOS_KB_VERSION_400 + 1][SE_KEY_128_SIZE] = { +static const u8 new_console_kekseed[HOS_MKEY_VER_MAX - HOS_MKEY_VER_400 + 1][SE_KEY_128_SIZE] = { { 0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D }, // 4.x New Device Keygen Source. { 0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E }, // 5.x New Device Keygen Source. { 0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF }, // 6.x New Device Keygen Source. @@ -300,13 +278,13 @@ out: } } -void hos_eks_clear(u32 kb) +void hos_eks_clear(u32 mkey) { // Check if Erista based unit. if (h_cfg.t210b01) return; - if (h_cfg.eks && kb >= HOS_KB_VERSION_700) + if (h_cfg.eks && mkey >= HOS_MKEY_VER_700) { // Check if current Master key is enabled. if (h_cfg.eks->enabled) @@ -335,14 +313,20 @@ out: } } -int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt) +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; + +int hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt) { u32 retries = 0; bool use_tsec = false; tsec_keys_t tsec_keys; - kb_t *kb_data = (kb_t *)keyblob; - if (kb > HOS_KB_VERSION_MAX) + if (mkey > HOS_MKEY_VER_MAX) return 0; // Do Mariko keygen. @@ -352,7 +336,7 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt) se_aes_unwrap_key(10, 14, console_keyseed_4xx); // Derive master key. - se_aes_unwrap_key(7, 12, master_kekseed_t210b01[kb - HOS_KB_VERSION_600]); + se_aes_unwrap_key(7, 12, master_kekseed_t210b01[mkey - HOS_MKEY_VER_600]); se_aes_unwrap_key(7, 7, master_keyseed_retail); // Derive latest pkg2 key. @@ -367,15 +351,15 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt) _hos_eks_get(); // Use tsec keygen for old firmware or if EKS keys does not exist for newer. - if (kb <= HOS_KB_VERSION_620 || !h_cfg.eks || (h_cfg.eks->enabled != HOS_EKS_TSEC_VER)) + if (mkey <= HOS_MKEY_VER_620 || !h_cfg.eks || (h_cfg.eks->enabled != HOS_EKS_TSEC_VER)) use_tsec = true; - if (kb <= HOS_KB_VERSION_600) + if (mkey <= HOS_MKEY_VER_600) { tsec_ctxt->size = 0xF00; tsec_ctxt->type = TSEC_FW_TYPE_OLD; } - else if (kb == HOS_KB_VERSION_620) + else if (mkey == HOS_MKEY_VER_620) { tsec_ctxt->size = 0x2900; tsec_ctxt->type = TSEC_FW_TYPE_EMU; @@ -425,7 +409,7 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt) } } - if (kb >= HOS_KB_VERSION_700) + if (mkey >= HOS_MKEY_VER_700) { // For 7.0.0 and up, save EKS slot if it doesn't exist. if (use_tsec) @@ -434,8 +418,8 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt) free(tsec_ctxt->fw); } - // Decrypt keyblob and set keyslots. - se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, keyblob_keyseeds[0]); + // Decrypt eks and set keyslots. + se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0]); se_aes_unwrap_key(15, 14, tsec_keys.tmp); // Derive device keys. @@ -451,15 +435,15 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt) // Package2 key. se_aes_unwrap_key(8, 7, package2_keyseed); } - else if (kb == HOS_KB_VERSION_620) + else if (mkey == HOS_MKEY_VER_620) { // Set TSEC key. se_aes_key_set(12, tsec_keys.tsec, SE_KEY_128_SIZE); // Set TSEC root key. se_aes_key_set(13, tsec_keys.tsec_root, SE_KEY_128_SIZE); - // Decrypt keyblob and set keyslots. - se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, keyblob_keyseeds[0]); + // Decrypt eks and set keyslots. + se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0]); se_aes_unwrap_key(15, 14, tsec_keys.tmp); // Derive device keys. @@ -480,48 +464,48 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt) // Set TSEC key. se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE); - // Derive keyblob keys from TSEC+SBK. - se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, keyblob_keyseeds[0]); + // Derive eks keys from TSEC+SBK. + se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[0]); se_aes_unwrap_key(15, 14, tsec_keys.tsec); - se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, keyblob_keyseeds[kb]); + se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[mkey]); se_aes_unwrap_key(13, 14, tsec_keys.tsec); /* - // Verify keyblob CMAC. + // Verify eks 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)) + se_aes_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)eks->ctr, sizeof(eks->ctr) + sizeof(eks->keys)); + if (!memcmp(eks->cmac, cmac, SE_KEY_128_SIZE)) return 0; */ se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, cmac_keyseed); se_aes_unwrap_key(11, 13, cmac_keyseed); - // Decrypt keyblob and set keyslots. - se_aes_crypt_ctr(13, &kb_data->keys, sizeof(kb_keys_t), &kb_data->keys, sizeof(kb_keys_t), 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_kekseed, SE_KEY_128_SIZE); - se_aes_key_set(13, kb_data->keys.master_kekseed, SE_KEY_128_SIZE); + // Decrypt eks and set keyslots. + se_aes_crypt_ctr(13, &eks->keys, sizeof(eks_keys_t), &eks->keys, sizeof(eks_keys_t), eks->ctr); + se_aes_key_set(11, eks->keys.package1_key, SE_KEY_128_SIZE); + se_aes_key_set(12, eks->keys.master_kekseed, SE_KEY_128_SIZE); + se_aes_key_set(13, eks->keys.master_kekseed, SE_KEY_128_SIZE); se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tsec, master_keyseed_retail); - switch (kb) + switch (mkey) { - case HOS_KB_VERSION_100: - case HOS_KB_VERSION_300: - case HOS_KB_VERSION_301: + case HOS_MKEY_VER_100: + case HOS_MKEY_VER_300: + case HOS_MKEY_VER_301: se_aes_unwrap_key(13, 15, console_keyseed); se_aes_unwrap_key(12, 12, master_keyseed_retail); break; - case HOS_KB_VERSION_400: + case HOS_MKEY_VER_400: se_aes_unwrap_key(13, 15, console_keyseed_4xx); se_aes_unwrap_key(15, 15, console_keyseed); //se_aes_unwrap_key(14, 12, master_keyseed_4xx); // In this context it's useless. So don't kill SBK. se_aes_unwrap_key(12, 12, master_keyseed_retail); break; - case HOS_KB_VERSION_500: - case HOS_KB_VERSION_600: + case HOS_MKEY_VER_500: + case HOS_MKEY_VER_600: se_aes_unwrap_key(10, 15, console_keyseed_4xx); se_aes_unwrap_key(15, 15, console_keyseed); //se_aes_unwrap_key(14, 12, master_keyseed_4xx); // In this context it's useless. So don't kill SBK. @@ -559,7 +543,7 @@ static void _hos_validate_mkey() } while (mkey_idx - 1); se_aes_key_clear(2); - hos_eks_clear(HOS_KB_VERSION_MAX); + hos_eks_clear(HOS_MKEY_VER_MAX); } static void _hos_bis_print_key(u32 idx, u8 *key) @@ -578,14 +562,14 @@ static void _hos_bis_print_key(u32 idx, u8 *key) int hos_bis_keygen() { u32 keygen_rev = 0; - u32 console_key_slot = 15; // HOS_KB_VERSION_MAX. Only for Erista. + u32 console_key_slot = 15; // HOS_MKEY_VER_MAX. Only for Erista. tsec_ctxt_t tsec_ctxt = {0}; if (!bis_keys) bis_keys = malloc(SE_KEY_128_SIZE * 6); // Run initial keygen. - hos_keygen(NULL, HOS_KB_VERSION_MAX, &tsec_ctxt); + hos_keygen(NULL, HOS_MKEY_VER_MAX, &tsec_ctxt); // All Mariko use new device keygen. New keygen was introduced in 4.0.0. // We check unconditionally in order to support downgrades. @@ -599,7 +583,7 @@ int hos_bis_keygen() u32 mkey_idx = sizeof(mkey_vectors) / SE_KEY_128_SIZE; // Keygen revision uses bootloader version, which starts from 1. - keygen_rev -= (HOS_KB_VERSION_400 + 1); + keygen_rev -= (HOS_MKEY_VER_400 + 1); // Derive mkey 0. do @@ -649,7 +633,7 @@ int hos_bis_keygen() se_aes_crypt_block_ecb(2, DECRYPT, bis_keys + (4 * SE_KEY_128_SIZE), bis_keyseed[4]); se_aes_crypt_block_ecb(2, DECRYPT, bis_keys + (5 * SE_KEY_128_SIZE), bis_keyseed[5]); - // Validate key because HOS_KB_VERSION_MAX. + // Validate key because HOS_MKEY_VER_MAX. if (!h_cfg.t210b01) _hos_validate_mkey(); @@ -718,13 +702,13 @@ int hos_dump_cal0() cal0_buf = NULL; // Clear EKS keys. - hos_eks_clear(HOS_KB_VERSION_MAX); + hos_eks_clear(HOS_MKEY_VER_MAX); return 2; } u32 hash[8]; - se_calc_sha256_oneshot(hash, (u8 *)cal0 + 0x40, cal0->body_size); + se_calc_sha256_oneshot(hash, (u8 *)&cal0->cfg_id1, cal0->body_size); if (memcmp(hash, cal0->body_sha256, 0x20)) return 3; diff --git a/nyx/nyx_gui/hos/hos.h b/nyx/nyx_gui/hos/hos.h index bdc82b9c..747629d9 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-2024 CTCaer + * Copyright (c) 2018-2025 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, @@ -27,34 +27,34 @@ //!TODO: Update on mkey changes. enum { - HOS_KB_VERSION_100 = 0, - HOS_KB_VERSION_300 = 1, - HOS_KB_VERSION_301 = 2, - HOS_KB_VERSION_400 = 3, - HOS_KB_VERSION_500 = 4, - HOS_KB_VERSION_600 = 5, - HOS_KB_VERSION_620 = 6, - HOS_KB_VERSION_700 = 7, - HOS_KB_VERSION_810 = 8, - HOS_KB_VERSION_900 = 9, - HOS_KB_VERSION_910 = 10, - HOS_KB_VERSION_1210 = 11, - HOS_KB_VERSION_1300 = 12, - HOS_KB_VERSION_1400 = 13, - HOS_KB_VERSION_1500 = 14, - HOS_KB_VERSION_1600 = 15, - HOS_KB_VERSION_1700 = 16, - HOS_KB_VERSION_1800 = 17, - HOS_KB_VERSION_1900 = 18, - HOS_KB_VERSION_2000 = 19, - HOS_KB_VERSION_MAX = HOS_KB_VERSION_2000 + HOS_MKEY_VER_100 = 0, + HOS_MKEY_VER_300 = 1, + HOS_MKEY_VER_301 = 2, + HOS_MKEY_VER_400 = 3, + HOS_MKEY_VER_500 = 4, + HOS_MKEY_VER_600 = 5, + HOS_MKEY_VER_620 = 6, + HOS_MKEY_VER_700 = 7, + HOS_MKEY_VER_810 = 8, + HOS_MKEY_VER_900 = 9, + HOS_MKEY_VER_910 = 10, + HOS_MKEY_VER_1210 = 11, + HOS_MKEY_VER_1300 = 12, + HOS_MKEY_VER_1400 = 13, + HOS_MKEY_VER_1500 = 14, + HOS_MKEY_VER_1600 = 15, + HOS_MKEY_VER_1700 = 16, + HOS_MKEY_VER_1800 = 17, + HOS_MKEY_VER_1900 = 18, + HOS_MKEY_VER_2000 = 19, + HOS_MKEY_VER_MAX = HOS_MKEY_VER_2000 }; #define HOS_TSEC_VERSION 4 //! TODO: Update on TSEC Root Key changes. #define HOS_PKG11_MAGIC 0x31314B50 #define HOS_EKS_MAGIC 0x31534B45 // EKS1. -#define HOS_EKS_TSEC_VER (HOS_KB_VERSION_700 + HOS_TSEC_VERSION) +#define HOS_EKS_TSEC_VER (HOS_MKEY_VER_700 + HOS_TSEC_VERSION) typedef struct _hos_eks_mbr_t { @@ -71,8 +71,6 @@ static_assert(sizeof(hos_eks_mbr_t) == 64, "HOS EKS size is wrong!"); typedef struct _launch_ctxt_t { - void *keyblob; - void *pkg1; const pkg1_id_t *pkg1_id; @@ -85,18 +83,19 @@ typedef struct _launch_ctxt_t u32 pkg2_size; bool new_pkg2; - void *kernel; - u32 kernel_size; + void *kernel; + u32 kernel_size; + link_t kip1_list; - char* kip1_patches; + char *kip1_patches; ini_sec_t *cfg; } launch_ctxt_t; extern u8 *cal0_buf; -void hos_eks_clear(u32 kb); -int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt); +void hos_eks_clear(u32 mkey); +int hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt); int hos_bis_keygen(); void hos_bis_keys_clear(); int hos_dump_cal0(); diff --git a/nyx/nyx_gui/hos/pkg1.c b/nyx/nyx_gui/hos/pkg1.c index cecbf599..dec7c5ea 100644 --- a/nyx/nyx_gui/hos/pkg1.c +++ b/nyx/nyx_gui/hos/pkg1.c @@ -37,7 +37,7 @@ static const u8 sec_map_100[3] = { PK11_SECTION_SM, PK11_SECTION_LD, PK11_SECTIO static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTION_SM }; static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB }; - // Timestamp KB TSEC PK11 SECMON Warmboot + // Timestamp MK TSEC PK11 SECMON Warmboot static const pkg1_id_t _pkg1_ids[] = { { "20161121", 0, 0x1900, 0x3FE0, 0x40014020, 0x8000D000 }, // 1.0.0. { "20170210", 0, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000 }, // 2.0.0 - 2.3.0. @@ -121,9 +121,9 @@ const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t u32 sec_size[3] = { hdr->wb_size, hdr->ldr_size, hdr->sm_size }; // Get correct header mapping. - if (id->kb == HOS_KB_VERSION_100 && !memcmp(id->id, "20161121", 8)) + if (id->mkey == HOS_MKEY_VER_100 && !memcmp(id->id, "20161121", 8)) sec_map = sec_map_100; - else if (id->kb <= HOS_KB_VERSION_301) + else if (id->mkey <= HOS_MKEY_VER_301) sec_map = sec_map_2xx; else sec_map = sec_map_4xx; diff --git a/nyx/nyx_gui/hos/pkg1.h b/nyx/nyx_gui/hos/pkg1.h index 6d30b58e..f0b5cb52 100644 --- a/nyx/nyx_gui/hos/pkg1.h +++ b/nyx/nyx_gui/hos/pkg1.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2022-2023 CTCaer + * Copyright (c) 2022-2025 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, @@ -39,6 +39,21 @@ typedef struct _bl_hdr_t210b01_t /* 0x160 */ u8 rsvd[0x10]; } bl_hdr_t210b01_t; +typedef struct _eks_keys_t +{ + u8 master_kekseed[SE_KEY_128_SIZE]; + u8 random_data[0x70]; + u8 package1_key[SE_KEY_128_SIZE]; +} eks_keys_t; + +typedef struct _pkg1_eks_t +{ + u8 cmac[SE_KEY_128_SIZE]; + u8 ctr[SE_AES_IV_SIZE]; + eks_keys_t keys; + u8 padding[0x150]; +} pkg1_eks_t; + typedef struct _pk1_hdr_t { /* 0x00 */ u32 si_sha256; // Secure Init. @@ -53,8 +68,8 @@ typedef struct _pk1_hdr_t typedef struct _pkg1_id_t { const char *id; - u32 kb; - u32 tsec_off; + u16 mkey; + u16 tsec_off; u32 pkg11_off; u32 secmon_base; u32 warmboot_base; @@ -62,14 +77,14 @@ typedef struct _pkg1_id_t typedef struct _pk11_hdr_t { - u32 magic; - u32 wb_size; - u32 wb_off; - u32 pad; - u32 ldr_size; - u32 ldr_off; - u32 sm_size; - u32 sm_off; +/* 0x00 */ u32 magic; +/* 0x04 */ u32 wb_size; +/* 0x08 */ u32 wb_off; +/* 0x0C */ u32 pad; +/* 0x10 */ u32 ldr_size; +/* 0x14 */ u32 ldr_off; +/* 0x18 */ u32 sm_size; +/* 0x1C */ u32 sm_off; } pk11_hdr_t; const pkg1_id_t *pkg1_identify(u8 *pkg1, char *build_date); diff --git a/nyx/nyx_gui/hos/pkg2.c b/nyx/nyx_gui/hos/pkg2.c index 74fb7092..2066eef2 100644 --- a/nyx/nyx_gui/hos/pkg2.c +++ b/nyx/nyx_gui/hos/pkg2.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2024 CTCaer + * Copyright (c) 2018-2025 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, @@ -90,7 +90,7 @@ void pkg2_get_newkern_info(u8 *kern_data) } //!TODO: Update on mkey changes. -static const u8 mkey_vector_7xx[HOS_KB_VERSION_MAX - HOS_KB_VERSION_810 + 1][SE_KEY_128_SIZE] = +static const u8 mkey_vector_7xx[HOS_MKEY_VER_MAX - HOS_MKEY_VER_810 + 1][SE_KEY_128_SIZE] = { // Master key 7 encrypted with 8. (7.0.0 with 8.1.0) { 0xEA, 0x60, 0xB3, 0xEA, 0xCE, 0x8F, 0x24, 0x46, 0x7D, 0x33, 0x9C, 0xD1, 0xBC, 0x24, 0x98, 0x29 }, @@ -133,7 +133,7 @@ static bool _pkg2_key_unwrap_validate(pkg2_hdr_t *tmp_test, pkg2_hdr_t *hdr, u8 return (tmp_test->magic == PKG2_MAGIC); } -pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb) +pkg2_hdr_t *pkg2_decrypt(void *data, u8 mkey) { pkg2_hdr_t mkey_test; u8 *pdata = (u8 *)data; @@ -154,13 +154,13 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb) goto key_found; // Decrypt older pkg2 via new mkeys. - if ((kb >= HOS_KB_VERSION_700) && (kb < HOS_KB_VERSION_MAX)) + if ((mkey >= HOS_MKEY_VER_700) && (mkey < HOS_MKEY_VER_MAX)) { u8 tmp_mkey[SE_KEY_128_SIZE]; u8 decr_slot = 7; // THK mkey or T210B01 mkey. u8 mkey_seeds_cnt = sizeof(mkey_vector_7xx) / SE_KEY_128_SIZE; u8 mkey_seeds_idx = mkey_seeds_cnt; // Real index + 1. - u8 mkey_seeds_min_idx = mkey_seeds_cnt - (HOS_KB_VERSION_MAX - kb); + u8 mkey_seeds_min_idx = mkey_seeds_cnt - (HOS_MKEY_VER_MAX - mkey); while (mkey_seeds_cnt) { @@ -196,11 +196,11 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb) key_found: // Decrypt header. se_aes_crypt_ctr(pkg2_keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr); - //gfx_hexdump((u32)hdr, hdr, 0x100); if (hdr->magic != PKG2_MAGIC) return NULL; + // Decrypt sections. for (u32 i = 0; i < 4; i++) { DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]); @@ -208,7 +208,6 @@ DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]); continue; se_aes_crypt_ctr(pkg2_keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * SE_AES_IV_SIZE]); - //gfx_hexdump((u32)pdata, pdata, 0x100); pdata += hdr->sec_size[i]; } diff --git a/nyx/nyx_gui/hos/pkg2.h b/nyx/nyx_gui/hos/pkg2.h index df246399..6b153543 100644 --- a/nyx/nyx_gui/hos/pkg2.h +++ b/nyx/nyx_gui/hos/pkg2.h @@ -38,18 +38,18 @@ extern u32 pkg2_newkern_ini1_end; typedef struct _pkg2_hdr_t { - u8 ctr[0x10]; - u8 sec_ctr[0x40]; - u32 magic; - u32 base; - u32 pad0; - u8 pkg2_ver; - u8 bl_ver; - u16 pad1; - u32 sec_size[4]; - u32 sec_off[4]; - u8 sec_sha256[0x80]; - u8 data[]; +/* 0x000 */ u8 ctr[0x10]; +/* 0x010 */ u8 sec_ctr[0x40]; +/* 0x050 */ u32 magic; +/* 0x054 */ u32 base; +/* 0x058 */ u32 pad0; +/* 0x05C */ u8 pkg2_ver; +/* 0x05D */ u8 bl_ver; +/* 0x05E */ u16 pad1; +/* 0x060 */ u32 sec_size[4]; +/* 0x070 */ u32 sec_off[4]; +/* 0x080 */ u8 sec_sha256[0x80]; +/* 0x100 */ u8 data[]; } pkg2_hdr_t; typedef struct _pkg2_ini1_t @@ -60,6 +60,18 @@ typedef struct _pkg2_ini1_t u32 pad; } pkg2_ini1_t; +enum kip_offset_section +{ + KIP_TEXT = 0, + KIP_RODATA = 1, + KIP_DATA = 2, + KIP_BSS = 3, + KIP_UNKSEC1 = 4, + KIP_UNKSEC2 = 5 +}; + +#define KIP1_NUM_SECTIONS 6 + typedef struct _pkg2_kip1_sec_t { u32 offset; @@ -68,21 +80,19 @@ typedef struct _pkg2_kip1_sec_t u32 attrib; } pkg2_kip1_sec_t; -#define KIP1_NUM_SECTIONS 6 - typedef struct _pkg2_kip1_t { - u32 magic; - u8 name[12]; - u64 tid; - u32 proc_cat; - u8 main_thrd_prio; - u8 def_cpu_core; - u8 res; - u8 flags; - pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS]; - u32 caps[0x20]; - u8 data[]; +/* 0x000 */ u32 magic; +/* 0x004 */ char name[12]; +/* 0x010 */ u64 tid; +/* 0x018 */ u32 proc_cat; +/* 0x01C */ u8 main_thrd_prio; +/* 0x01D */ u8 def_cpu_core; +/* 0x01E */ u8 res; +/* 0x01F */ u8 flags; +/* 0x020 */ pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS]; +/* 0x080 */ u32 caps[0x20]; +/* 0x100 */ u8 data[]; } pkg2_kip1_t; typedef struct _pkg2_kip1_info_t @@ -95,6 +105,6 @@ typedef struct _pkg2_kip1_info_t void pkg2_get_newkern_info(u8 *kern_data); u32 pkg2_calc_kip1_size(pkg2_kip1_t *kip1); -pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb); +pkg2_hdr_t *pkg2_decrypt(void *data, u8 mkey); #endif