hos: Add Mariko PK11 decryption and unpacking

This commit is contained in:
CTCaer 2020-07-04 21:32:36 +03:00
parent 8880dfab24
commit 9b3e9724b7
8 changed files with 119 additions and 21 deletions

View file

@ -129,7 +129,7 @@ void dump_packages12()
if (kb <= KB_FIRMWARE_VERSION_620) 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); pk11_hdr_t *hdr_pk11 = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20);

View file

@ -591,6 +591,7 @@ static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
static const u32 BOOTLOADER_BACKUP_OFFSET = 0x140000; static const u32 BOOTLOADER_BACKUP_OFFSET = 0x140000;
static const u32 HOS_KEYBLOBS_OFFSET = 0x180000; 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; u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET;
ctxt->pkg1 = (void *)malloc(BOOTLOADER_SIZE); ctxt->pkg1 = (void *)malloc(BOOTLOADER_SIZE);
@ -599,7 +600,7 @@ try_load:
emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0); 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); 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) if (!ctxt->pkg1_id)
{ {
_hos_crit_error("Unknown pkg1 version."); _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. // Decrypt and unpack package1 if we require parts of it.
if (!ctxt.warmboot || !ctxt.secmon) if (!ctxt.warmboot || !ctxt.secmon)
{ {
if (kb <= KB_FIRMWARE_VERSION_600) // Decrypt PK1 or PK11.
pkg1_decrypt(ctxt.pkg1_id, ctxt.pkg1); if (kb <= KB_FIRMWARE_VERSION_600 || h_cfg.t210b01)
if (kb <= KB_FIRMWARE_VERSION_620 && !emummc_enabled)
{ {
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"); gfx_puts("Decrypted & unpacked pkg1\n");
} }
else else

View file

@ -21,11 +21,14 @@
#include "hos.h" #include "hos.h"
#include "pkg1.h" #include "pkg1.h"
#include "../config.h"
#include <gfx_utils.h> #include <gfx_utils.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <sec/se.h> #include <sec/se.h>
#include <utils/aarch64_util.h> #include <utils/aarch64_util.h>
extern hekate_config h_cfg;
// Secmon package2 signature/hash checks patches for Erista. // Secmon package2 signature/hash checks patches for Erista.
#define SM_100_ADR 0x4002B020 // Original: 0x40014020. #define SM_100_ADR 0x4002B020 // Original: 0x40014020.
PATCHSET_DEF(_secmon_1_patchset, 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); gfx_printf("Found pkg1 ('%s').\n\n", build_date);
for (u32 i = 0; _pkg1_ids[i].id; i++) 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 &_pkg1_ids[i];
return NULL; return NULL;
} }
void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1) int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
{ {
// Decrypt package1. // Decrypt package1.
pk11_hdr_t *hdr;
u8 *pkg11 = pkg1 + id->pkg11_off; u8 *pkg11 = pkg1 + id->pkg11_off;
u32 pkg11_size = *(u32 *)pkg11; 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);
} }
const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1) // Return if header is valid.
return (hdr->magic == PKG1_MAGIC);
}
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 u8 *sec_map;
const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20); 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++) for (u32 i = 0; i < 3; i++)
{ {
if (sec_map[i] == PK11_SECTION_WB && wm_dst) if (sec_map[i] == PK11_SECTION_WB && wm_dst)
{
memcpy(wm_dst, pdata, sec_size[sec_map[i]]); 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) else if (sec_map[i] == PK11_SECTION_LD && ldr_dst)
memcpy(ldr_dst, pdata, sec_size[sec_map[i]]); memcpy(ldr_dst, pdata, sec_size[sec_map[i]]);
else if (sec_map[i] == PK11_SECTION_SM && sm_dst) else if (sec_map[i] == PK11_SECTION_SM && sm_dst)

View file

@ -19,6 +19,8 @@
#include <utils/types.h> #include <utils/types.h>
#define PKG1_MAGIC 0x31314B50
#define PK11_SECTION_WB 0 #define PK11_SECTION_WB 0
#define PK11_SECTION_LD 1 #define PK11_SECTION_LD 1
#define PK11_SECTION_SM 2 #define PK11_SECTION_SM 2
@ -35,6 +37,19 @@ typedef struct _patch_t
{ 0xFFFFFFFF, 0xFFFFFFFF } \ { 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 typedef struct _pkg1_id_t
{ {
const char *id; const char *id;
@ -61,7 +76,7 @@ typedef struct _pk11_hdr_t
const pkg1_id_t *pkg1_get_latest(); const pkg1_id_t *pkg1_get_latest();
const pkg1_id_t *pkg1_identify(u8 *pkg1); const pkg1_id_t *pkg1_identify(u8 *pkg1);
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); const u8 *pkg1_unpack(void *wm_dst, u32 *wb_sz, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1);
#endif #endif

View file

@ -158,7 +158,7 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new)
switch (kb) switch (kb)
{ {
case KB_FIRMWARE_VERSION_100_200: case KB_FIRMWARE_VERSION_100_200:
if (!strcmp(ctxt->pkg1_id->id, "20161121183008")) if (!memcmp(ctxt->pkg1_id->id, "20161121183008", 8))
exoFwNo = 1; exoFwNo = 1;
else else
exoFwNo = 2; exoFwNo = 2;
@ -168,9 +168,9 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new)
break; break;
default: default:
exoFwNo = kb + 1; 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. 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. exoFwNo++; // ATM_TARGET_FW_1000.
break; break;
} }

View file

@ -297,6 +297,7 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
u8 kb = 0; u8 kb = 0;
u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET; 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); u8 *pkg1 = (u8 *)malloc(BOOTLOADER_SIZE);
sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400); 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); 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); sdmmc_storage_read(&emmc_storage, bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, pkg1);
char *build_date = malloc(32); 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); s_printf(txt_buf + strlen(txt_buf), "#00DDFF Found pkg1 ('%s')#\n", build_date);
free(build_date); free(build_date);

View file

@ -21,11 +21,14 @@
#include "hos.h" #include "hos.h"
#include "pkg1.h" #include "pkg1.h"
#include "../config.h"
#include <gfx_utils.h> #include <gfx_utils.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <sec/se.h> #include <sec/se.h>
#include <utils/aarch64_util.h> #include <utils/aarch64_util.h>
extern hekate_config h_cfg;
/* /*
* package1.1 header: <wb, ldr, sm> * package1.1 header: <wb, ldr, sm>
* package1.1 layout: * 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++) 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 &_pkg1_ids[i];
return NULL; return NULL;
} }
void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1) int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
{ {
// Decrypt package1. // Decrypt package1.
pk11_hdr_t *hdr;
u8 *pkg11 = pkg1 + id->pkg11_off; u8 *pkg11 = pkg1 + id->pkg11_off;
u32 pkg11_size = *(u32 *)pkg11; 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) const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1)

View file

@ -19,10 +19,25 @@
#include <utils/types.h> #include <utils/types.h>
#define PKG1_MAGIC 0x31314B50
#define PK11_SECTION_WB 0 #define PK11_SECTION_WB 0
#define PK11_SECTION_LD 1 #define PK11_SECTION_LD 1
#define PK11_SECTION_SM 2 #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 typedef struct _pkg1_id_t
{ {
const char *id; const char *id;
@ -46,7 +61,7 @@ typedef struct _pk11_hdr_t
} pk11_hdr_t; } pk11_hdr_t;
const pkg1_id_t *pkg1_identify(u8 *pkg1, char *build_date); 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); const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1);
#endif #endif