From 40afcfd6865c0e16d6bbeb0ca026c2eece71e8fc Mon Sep 17 00:00:00 2001 From: CTCaer Date: Thu, 12 Sep 2019 23:39:47 +0300 Subject: [PATCH] hos: Support pkg2 encrypted with newer mkeys --- bootloader/frontend/fe_tools.c | 2 +- bootloader/hos/hos.c | 4 ++-- bootloader/hos/pkg2.c | 38 +++++++++++++++++++++++++++++--- bootloader/hos/pkg2.h | 2 +- nyx/nyx_gui/frontend/gui_tools.c | 2 +- nyx/nyx_gui/hos/hos.c | 2 +- nyx/nyx_gui/hos/pkg2.c | 37 ++++++++++++++++++++++++++++--- nyx/nyx_gui/hos/pkg2.h | 2 +- 8 files changed, 76 insertions(+), 13 deletions(-) diff --git a/bootloader/frontend/fe_tools.c b/bootloader/frontend/fe_tools.c index 1971163..75ae6e5 100644 --- a/bootloader/frontend/fe_tools.c +++ b/bootloader/frontend/fe_tools.c @@ -190,7 +190,7 @@ void dump_packages12() nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, pkg2_size_aligned / NX_EMMC_BLOCKSIZE, pkg2); // Decrypt package2 and parse KIP1 blobs in INI1 section. - pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2); + pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, kb); if (!pkg2_hdr) { gfx_printf("Pkg2 decryption failed!\n"); diff --git a/bootloader/hos/hos.c b/bootloader/hos/hos.c index 93fa94b..5fd8687 100644 --- a/bootloader/hos/hos.c +++ b/bootloader/hos/hos.c @@ -89,7 +89,7 @@ static const u8 master_keyseed_retail[0x10] = static const u8 console_keyseed[0x10] = { 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 }; -static const u8 package2_keyseed[] = +const u8 package2_keyseed[] = { 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 }; static const u8 master_keyseed_4xx_5xx_610[0x10] = @@ -544,7 +544,7 @@ DPRINTF("Generated keys\n"); gfx_printf("Read pkg2\n"); // Decrypt package2 and parse KIP1 blobs in INI1 section. - pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2); + pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2, ctxt.pkg1_id->kb); if (!pkg2_hdr) { _hos_crit_error("Pkg2 decryption failed!"); diff --git a/bootloader/hos/pkg2.c b/bootloader/hos/pkg2.c index 6c4601c..b5abe48 100644 --- a/bootloader/hos/pkg2.c +++ b/bootloader/hos/pkg2.c @@ -18,6 +18,7 @@ #include +#include "hos.h" #include "pkg2.h" #include "pkg2_ini_kippatch.h" @@ -32,6 +33,8 @@ #include "../gfx/gfx.h" extern hekate_config h_cfg; +extern const u8 package2_keyseed[]; + extern void *sd_file_read(const char *path, u32 *fsize); #ifdef KIP1_PATCH_DEBUG @@ -1039,9 +1042,16 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames) return NULL; } -pkg2_hdr_t *pkg2_decrypt(void *data) +static const uint8_t mkey_keyseed_8xx[][0x10] = { + {0x4D, 0xD9, 0x98, 0x42, 0x45, 0x0D, 0xB1, 0x3C, 0x52, 0x0C, 0x9A, 0x44, 0xBB, 0xAD, 0xAF, 0x80} // Master key 8 encrypted with 9. +}; + +pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb) +{ + pkg2_hdr_t mkey_test; u8 *pdata = (u8 *)data; + u8 keyslot = 8; // Skip signature. pdata += 0x100; @@ -1051,8 +1061,27 @@ pkg2_hdr_t *pkg2_decrypt(void *data) // Skip header. pdata += sizeof(pkg2_hdr_t); + //! Check if we need to decrypt with newer mkeys. Valid for 8.1.0 and up. + if ((kb >= KB_FIRMWARE_VERSION_810) && (kb < KB_FIRMWARE_VERSION_MAX)) + { + u8 tmp_mkey[0x10]; + // Decrypt older encrypted mkey. + se_aes_crypt_ecb(12, 0, tmp_mkey, 0x10, mkey_keyseed_8xx[KB_FIRMWARE_VERSION_MAX - kb - 1], 0x10); + // Set and unwrap pkg2 key. + se_aes_key_set(9, tmp_mkey, 0x10); + se_aes_unwrap_key(9, 9, package2_keyseed); + + // Decrypt header and test if it's valid. + se_aes_crypt_ctr(9, &mkey_test, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr); + + if (mkey_test.magic == PKG2_MAGIC) + keyslot = 9; + else + se_aes_key_clear(9); + } + // Decrypt header. - se_aes_crypt_ctr(8, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr); + se_aes_crypt_ctr(keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr); //gfx_hexdump((u32)hdr, hdr, 0x100); if (hdr->magic != PKG2_MAGIC) @@ -1064,12 +1093,15 @@ DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]); if (!hdr->sec_size[i]) continue; - se_aes_crypt_ctr(8, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]); + se_aes_crypt_ctr(keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]); //gfx_hexdump((u32)pdata, pdata, 0x100); pdata += hdr->sec_size[i]; } + if (keyslot != 8) + se_aes_key_clear(9); + return hdr; } diff --git a/bootloader/hos/pkg2.h b/bootloader/hos/pkg2.h index e7757af..c637a76 100644 --- a/bootloader/hos/pkg2.h +++ b/bootloader/hos/pkg2.h @@ -151,7 +151,7 @@ void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1); const char* pkg2_patch_kips(link_t *info, char* patchNames); const pkg2_kernel_id_t *pkg2_identify(u8 *hash); -pkg2_hdr_t *pkg2_decrypt(void *data); +pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb); void pkg2_build_encrypt(void *dst, void *kernel, u32 kernel_size, link_t *kips_info, bool new_pkg2); #endif diff --git a/nyx/nyx_gui/frontend/gui_tools.c b/nyx/nyx_gui/frontend/gui_tools.c index 68ea2b6..4ec2f8f 100644 --- a/nyx/nyx_gui/frontend/gui_tools.c +++ b/nyx/nyx_gui/frontend/gui_tools.c @@ -506,7 +506,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn) #endif // Decrypt package2 and parse KIP1 blobs in INI1 section. - pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2); + pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, kb); if (!pkg2_hdr) { s_printf(txt_buf + strlen(txt_buf), "#FFDD00 Pkg2 decryption failed!#"); diff --git a/nyx/nyx_gui/hos/hos.c b/nyx/nyx_gui/hos/hos.c index f01de85..43d7725 100644 --- a/nyx/nyx_gui/hos/hos.c +++ b/nyx/nyx_gui/hos/hos.c @@ -79,7 +79,7 @@ static const u8 master_keyseed_retail[0x10] = static const u8 console_keyseed[0x10] = { 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 }; -static const u8 package2_keyseed[] = +const u8 package2_keyseed[] = { 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 }; static const u8 master_keyseed_4xx_5xx_610[0x10] = diff --git a/nyx/nyx_gui/hos/pkg2.c b/nyx/nyx_gui/hos/pkg2.c index 5c0a8fe..f9c15f2 100644 --- a/nyx/nyx_gui/hos/pkg2.c +++ b/nyx/nyx_gui/hos/pkg2.c @@ -28,6 +28,8 @@ #include "../gfx/gfx.h" +extern const u8 package2_keyseed[]; + /*#include "util.h" #define DPRINTF(...) gfx_printf(__VA_ARGS__) #define DEBUG_PRINTING*/ @@ -79,9 +81,16 @@ DPRINTF(" kip1 %d:%s @ %08X (%08X)\n", i, kip1->name, (u32)kip1, ki->size); } } -pkg2_hdr_t *pkg2_decrypt(void *data) +static const uint8_t mkey_keyseed_8xx[][0x10] = { + {0x4D, 0xD9, 0x98, 0x42, 0x45, 0x0D, 0xB1, 0x3C, 0x52, 0x0C, 0x9A, 0x44, 0xBB, 0xAD, 0xAF, 0x80} // Master key 8 encrypted with 9. +}; + +pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb) +{ + pkg2_hdr_t mkey_test; u8 *pdata = (u8 *)data; + u8 keyslot = 8; // Skip signature. pdata += 0x100; @@ -91,8 +100,27 @@ pkg2_hdr_t *pkg2_decrypt(void *data) // Skip header. pdata += sizeof(pkg2_hdr_t); + //! Check if we need to decrypt with newer mkeys. Valid for 8.1.0 and up. + if ((kb >= KB_FIRMWARE_VERSION_810) && (kb < KB_FIRMWARE_VERSION_MAX)) + { + u8 tmp_mkey[0x10]; + // Decrypt older encrypted mkey. + se_aes_crypt_ecb(12, 0, tmp_mkey, 0x10, mkey_keyseed_8xx[KB_FIRMWARE_VERSION_MAX - kb - 1], 0x10); + // Set and unwrap pkg2 key. + se_aes_key_set(9, tmp_mkey, 0x10); + se_aes_unwrap_key(9, 9, package2_keyseed); + + // Decrypt header and test if it's valid. + se_aes_crypt_ctr(9, &mkey_test, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr); + + if (mkey_test.magic == PKG2_MAGIC) + keyslot = 9; + else + se_aes_key_clear(9); + } + // Decrypt header. - se_aes_crypt_ctr(8, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr); + se_aes_crypt_ctr(keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr); //gfx_hexdump((u32)hdr, hdr, 0x100); if (hdr->magic != PKG2_MAGIC) @@ -104,11 +132,14 @@ DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]); if (!hdr->sec_size[i]) continue; - se_aes_crypt_ctr(8, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]); + se_aes_crypt_ctr(keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]); //gfx_hexdump((u32)pdata, pdata, 0x100); pdata += hdr->sec_size[i]; } + if (keyslot != 8) + se_aes_key_clear(9); + return hdr; } diff --git a/nyx/nyx_gui/hos/pkg2.h b/nyx/nyx_gui/hos/pkg2.h index 2ac3554..60e6f87 100644 --- a/nyx/nyx_gui/hos/pkg2.h +++ b/nyx/nyx_gui/hos/pkg2.h @@ -93,6 +93,6 @@ void pkg2_get_newkern_info(u8 *kern_data); u32 pkg2_calc_kip1_size(pkg2_kip1_t *kip1); void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2); -pkg2_hdr_t *pkg2_decrypt(void *data); +pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb); #endif