mirror of
https://github.com/CTCaer/hekate
synced 2024-12-22 11:21:23 +00:00
hos: Add Mariko PK11 decryption and unpacking
This commit is contained in:
parent
8880dfab24
commit
9b3e9724b7
8 changed files with 119 additions and 21 deletions
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue