diff --git a/bootloader/frontend/fe_tools.c b/bootloader/frontend/fe_tools.c index 1ab05b2..a17623d 100644 --- a/bootloader/frontend/fe_tools.c +++ b/bootloader/frontend/fe_tools.c @@ -129,7 +129,7 @@ void dump_packages12() if (kb <= KB_FIRMWARE_VERSION_620) { - const u8 *sec_map = pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1); + const u8 *sec_map = pkg1_unpack(warmboot, NULL, secmon, loader, pkg1_id, pkg1); pk11_hdr_t *hdr_pk11 = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20); diff --git a/bootloader/hos/hos.c b/bootloader/hos/hos.c index 9664780..042be2f 100644 --- a/bootloader/hos/hos.c +++ b/bootloader/hos/hos.c @@ -591,6 +591,7 @@ static int _read_emmc_pkg1(launch_ctxt_t *ctxt) static const u32 BOOTLOADER_BACKUP_OFFSET = 0x140000; static const u32 HOS_KEYBLOBS_OFFSET = 0x180000; + u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header. u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET; ctxt->pkg1 = (void *)malloc(BOOTLOADER_SIZE); @@ -599,7 +600,7 @@ try_load: emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0); emummc_storage_read(&emmc_storage, bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, ctxt->pkg1); - ctxt->pkg1_id = pkg1_identify(ctxt->pkg1); + ctxt->pkg1_id = pkg1_identify(ctxt->pkg1 + pk1_offset); if (!ctxt->pkg1_id) { _hos_crit_error("Unknown pkg1 version."); @@ -832,12 +833,30 @@ int hos_launch(ini_sec_t *cfg) // Decrypt and unpack package1 if we require parts of it. if (!ctxt.warmboot || !ctxt.secmon) { - if (kb <= KB_FIRMWARE_VERSION_600) - pkg1_decrypt(ctxt.pkg1_id, ctxt.pkg1); - - if (kb <= KB_FIRMWARE_VERSION_620 && !emummc_enabled) + // Decrypt PK1 or PK11. + if (kb <= KB_FIRMWARE_VERSION_600 || h_cfg.t210b01) { - pkg1_unpack((void *)ctxt.pkg1_id->warmboot_base, (void *)ctxt.pkg1_id->secmon_base, NULL, ctxt.pkg1_id, ctxt.pkg1); + if (!pkg1_decrypt(ctxt.pkg1_id, ctxt.pkg1)) + { + _hos_crit_error("Pkg1 decryption failed!"); + if (h_cfg.t210b01) + EPRINTF("Is BEK missing?"); + goto error; + } + } + + // Unpack PK11. + if (h_cfg.t210b01 || (kb <= KB_FIRMWARE_VERSION_620 && !emummc_enabled)) + { + // Skip T210B01 OEM header. + u32 pk1_offset = 0; + if (h_cfg.t210b01) + pk1_offset = sizeof(bl_hdr_t210b01_t); + + pkg1_unpack((void *)warmboot_base, &ctxt.warmboot_size, + !exo_new ? (void *)ctxt.pkg1_id->secmon_base : NULL, NULL, + ctxt.pkg1_id, ctxt.pkg1 + pk1_offset); + gfx_puts("Decrypted & unpacked pkg1\n"); } else diff --git a/bootloader/hos/pkg1.c b/bootloader/hos/pkg1.c index 701a4f5..1b4a673 100644 --- a/bootloader/hos/pkg1.c +++ b/bootloader/hos/pkg1.c @@ -21,11 +21,14 @@ #include "hos.h" #include "pkg1.h" +#include "../config.h" #include #include #include #include +extern hekate_config h_cfg; + // Secmon package2 signature/hash checks patches for Erista. #define SM_100_ADR 0x4002B020 // Original: 0x40014020. PATCHSET_DEF(_secmon_1_patchset, @@ -145,20 +148,39 @@ const pkg1_id_t *pkg1_identify(u8 *pkg1) gfx_printf("Found pkg1 ('%s').\n\n", build_date); for (u32 i = 0; _pkg1_ids[i].id; i++) - if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 12)) + if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 8)) return &_pkg1_ids[i]; return NULL; } -void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1) +int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1) { // Decrypt package1. + pk11_hdr_t *hdr; u8 *pkg11 = pkg1 + id->pkg11_off; u32 pkg11_size = *(u32 *)pkg11; - se_aes_crypt_ctr(11, pkg11 + 0x20, pkg11_size, pkg11 + 0x20, pkg11_size, pkg11 + 0x10); + + if (!h_cfg.t210b01) + { + hdr = (pk11_hdr_t *)(pkg11 + 0x20); + se_aes_crypt_ctr(11, hdr, pkg11_size, hdr, pkg11_size, pkg11 + 0x10); + } + else + { + bl_hdr_t210b01_t *oem_hdr = (bl_hdr_t210b01_t *)pkg1; + pkg1 += sizeof(bl_hdr_t210b01_t); + hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20); + + // Use BEK for T210B01. + se_aes_iv_clear(13); + se_aes_crypt_cbc(13, 0, pkg1 + 0x20, oem_hdr->size - 0x20, pkg1 + 0x20, oem_hdr->size - 0x20); + } + + // Return if header is valid. + return (hdr->magic == PKG1_MAGIC); } -const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, 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) { const u8 *sec_map; const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20); @@ -179,7 +201,11 @@ const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t for (u32 i = 0; i < 3; i++) { if (sec_map[i] == PK11_SECTION_WB && wm_dst) + { memcpy(wm_dst, pdata, sec_size[sec_map[i]]); + if (wb_sz) + *wb_sz = sec_size[sec_map[i]]; + } else if (sec_map[i] == PK11_SECTION_LD && ldr_dst) memcpy(ldr_dst, pdata, sec_size[sec_map[i]]); else if (sec_map[i] == PK11_SECTION_SM && sm_dst) diff --git a/bootloader/hos/pkg1.h b/bootloader/hos/pkg1.h index bcaa1bd..ef17300 100644 --- a/bootloader/hos/pkg1.h +++ b/bootloader/hos/pkg1.h @@ -19,6 +19,8 @@ #include +#define PKG1_MAGIC 0x31314B50 + #define PK11_SECTION_WB 0 #define PK11_SECTION_LD 1 #define PK11_SECTION_SM 2 @@ -35,6 +37,19 @@ typedef struct _patch_t { 0xFFFFFFFF, 0xFFFFFFFF } \ } +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; + typedef struct _pkg1_id_t { const char *id; @@ -61,7 +76,7 @@ typedef struct _pk11_hdr_t const pkg1_id_t *pkg1_get_latest(); const pkg1_id_t *pkg1_identify(u8 *pkg1); -void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1); -const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1); +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); #endif diff --git a/bootloader/hos/secmon_exo.c b/bootloader/hos/secmon_exo.c index 7cc51a9..e96a5e9 100644 --- a/bootloader/hos/secmon_exo.c +++ b/bootloader/hos/secmon_exo.c @@ -158,7 +158,7 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new) switch (kb) { case KB_FIRMWARE_VERSION_100_200: - if (!strcmp(ctxt->pkg1_id->id, "20161121183008")) + if (!memcmp(ctxt->pkg1_id->id, "20161121183008", 8)) exoFwNo = 1; else exoFwNo = 2; @@ -168,9 +168,9 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new) break; default: exoFwNo = kb + 1; - if (!strcmp(ctxt->pkg1_id->id, "20190314172056") || (kb >= KB_FIRMWARE_VERSION_810)) + if (!memcmp(ctxt->pkg1_id->id, "20190314172056", 8) || (kb >= KB_FIRMWARE_VERSION_810)) exoFwNo++; // ATM_TARGET_FW_800/810/900/910. - if (!strcmp(ctxt->pkg1_id->id, "20200303104606")) + if (!memcmp(ctxt->pkg1_id->id, "20200303104606", 8)) exoFwNo++; // ATM_TARGET_FW_1000. break; } diff --git a/nyx/nyx_gui/frontend/gui_info.c b/nyx/nyx_gui/frontend/gui_info.c index 1bf47fc..8978c86 100644 --- a/nyx/nyx_gui/frontend/gui_info.c +++ b/nyx/nyx_gui/frontend/gui_info.c @@ -297,6 +297,7 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn) u8 kb = 0; u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET; + u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header. u8 *pkg1 = (u8 *)malloc(BOOTLOADER_SIZE); sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400); sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0); @@ -305,7 +306,7 @@ try_load: sdmmc_storage_read(&emmc_storage, bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, pkg1); char *build_date = malloc(32); - const pkg1_id_t *pkg1_id = pkg1_identify(pkg1, build_date); + const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset, build_date); s_printf(txt_buf + strlen(txt_buf), "#00DDFF Found pkg1 ('%s')#\n", build_date); free(build_date); diff --git a/nyx/nyx_gui/hos/pkg1.c b/nyx/nyx_gui/hos/pkg1.c index df6f420..d115791 100644 --- a/nyx/nyx_gui/hos/pkg1.c +++ b/nyx/nyx_gui/hos/pkg1.c @@ -21,11 +21,14 @@ #include "hos.h" #include "pkg1.h" +#include "../config.h" #include #include #include #include +extern hekate_config h_cfg; + /* * package1.1 header: * package1.1 layout: @@ -66,17 +69,36 @@ const pkg1_id_t *pkg1_identify(u8 *pkg1, char *build_date) } for (u32 i = 0; _pkg1_ids[i].id; i++) - if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 12)) + if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 8)) return &_pkg1_ids[i]; return NULL; } -void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1) +int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1) { // Decrypt package1. + pk11_hdr_t *hdr; u8 *pkg11 = pkg1 + id->pkg11_off; u32 pkg11_size = *(u32 *)pkg11; - se_aes_crypt_ctr(11, pkg11 + 0x20, pkg11_size, pkg11 + 0x20, pkg11_size, pkg11 + 0x10); + + if (!h_cfg.t210b01) + { + hdr = (pk11_hdr_t *)(pkg11 + 0x20); + se_aes_crypt_ctr(11, hdr, pkg11_size, hdr, pkg11_size, pkg11 + 0x10); + } + else + { + bl_hdr_t210b01_t *oem_hdr = (bl_hdr_t210b01_t *)pkg1; + pkg1 += sizeof(bl_hdr_t210b01_t); + hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20); + + // Use BEK for T210B01. + se_aes_iv_clear(13); + se_aes_crypt_cbc(13, 0, pkg1 + 0x20, oem_hdr->size, pkg1 + 0x20, oem_hdr->size); + } + + // Return if header is valid. + return (hdr->magic == PKG1_MAGIC); } const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1) diff --git a/nyx/nyx_gui/hos/pkg1.h b/nyx/nyx_gui/hos/pkg1.h index 74f101b..ca6295d 100644 --- a/nyx/nyx_gui/hos/pkg1.h +++ b/nyx/nyx_gui/hos/pkg1.h @@ -19,10 +19,25 @@ #include +#define PKG1_MAGIC 0x31314B50 + #define PK11_SECTION_WB 0 #define PK11_SECTION_LD 1 #define PK11_SECTION_SM 2 +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; + typedef struct _pkg1_id_t { const char *id; @@ -46,7 +61,7 @@ typedef struct _pk11_hdr_t } pk11_hdr_t; const pkg1_id_t *pkg1_identify(u8 *pkg1, char *build_date); -void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1); +int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1); const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1); #endif