mirror of
https://github.com/CTCaer/hekate
synced 2024-12-22 11:21:23 +00:00
Feature/4x (#10)
* Dump sm, added JanV work * add Ac_K patches, fix boot, keygen is wrong, need more work * cleanup keygen, correct key for 4xx * remove unused code, cleanup code
This commit is contained in:
parent
764231b418
commit
4d7f016e3a
8 changed files with 236 additions and 176 deletions
249
ipl/hos.c
249
ipl/hos.c
|
@ -32,11 +32,20 @@
|
|||
#include "pkg2.h"
|
||||
#include "ff.h"
|
||||
|
||||
/*#include "gfx.h"
|
||||
#include "gfx.h"
|
||||
extern gfx_ctxt_t gfx_ctxt;
|
||||
extern gfx_con_t gfx_con;
|
||||
#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)*/
|
||||
#define DPRINTF(...)
|
||||
#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)
|
||||
//#define DPRINTF(...)
|
||||
|
||||
enum KB_FIRMWARE_VERSION {
|
||||
KB_FIRMWARE_VERSION_100_200 = 0,
|
||||
KB_FIRMWARE_VERSION_300 = 1,
|
||||
KB_FIRMWARE_VERSION_301 = 2,
|
||||
KB_FIRMWARE_VERSION_400 = 3,
|
||||
KB_FIRMWARE_VERSION_500 = 4,
|
||||
KB_FIRMWARE_VERSION_MAX
|
||||
};
|
||||
|
||||
#define NUM_KEYBLOB_KEYS 5
|
||||
static const u8 keyblob_keyseeds[NUM_KEYBLOB_KEYS][0x10] = {
|
||||
|
@ -50,19 +59,19 @@ static const u8 keyblob_keyseeds[NUM_KEYBLOB_KEYS][0x10] = {
|
|||
static const u8 cmac_keyseed[0x10] =
|
||||
{ 0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5 };
|
||||
|
||||
static const u8 mkey_keyseed_retail[0x10] =
|
||||
static const u8 master_keyseed_retail[0x10] =
|
||||
{ 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C };
|
||||
|
||||
static const u8 ckey_keyseed[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 key8_keyseed[] =
|
||||
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
|
||||
|
||||
static const u8 new_masterkey_seed[0x10] =
|
||||
static const u8 master_keyseed_4xx[0x10] =
|
||||
{ 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 };
|
||||
|
||||
static const u8 new_per_console_key[0x10] =
|
||||
static const u8 console_keyseed_4xx[0x10] =
|
||||
{ 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
|
||||
|
||||
|
||||
|
@ -94,18 +103,27 @@ static void _se_lock()
|
|||
}
|
||||
|
||||
// <-- key derivation algorithm
|
||||
static int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
|
||||
int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
|
||||
{
|
||||
u8 *tmp = (u8 *)malloc(0x10);
|
||||
u8 tmp[0x10];
|
||||
|
||||
se_key_acc_ctrl(12, 0x15);
|
||||
se_key_acc_ctrl(13, 0x15);
|
||||
se_key_acc_ctrl(0x0D, 0x15);
|
||||
se_key_acc_ctrl(0x0E, 0x15);
|
||||
|
||||
//Get TSEC key.
|
||||
if (tsec_query(tmp, 1, tsec_fw) < 0)
|
||||
return 0;
|
||||
|
||||
se_aes_key_set(13, tmp, 0x10);
|
||||
se_aes_key_set(0x0D, tmp, 0x10);
|
||||
|
||||
//Derive keyblob keys from TSEC+SBK.
|
||||
se_aes_crypt_block_ecb(0x0D, 0x00, tmp, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(0x0F, 0x0E, tmp);
|
||||
se_aes_crypt_block_ecb(0xD, 0x00, tmp, keyblob_keyseeds[kb]);
|
||||
se_aes_unwrap_key(0x0D, 0x0E, tmp);
|
||||
|
||||
// Clear SBK
|
||||
se_aes_key_clear(0x0E);
|
||||
|
||||
//TODO: verify keyblob CMAC.
|
||||
//se_aes_unwrap_key(11, 13, cmac_keyseed);
|
||||
|
@ -113,131 +131,43 @@ static int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
|
|||
//if (!memcmp(keyblob, tmp, 0x10))
|
||||
// return 0;
|
||||
|
||||
switch(kb) {
|
||||
// 1.0.0~2.0.0 FW
|
||||
case 0: {
|
||||
se_aes_crypt_block_ecb(0x0D, 0, tmp, cmac_keyseed);
|
||||
se_aes_unwrap_key(0x0B, 0x0D, cmac_keyseed);
|
||||
|
||||
//Derive keyblob key from TSEC+SBK.
|
||||
memcpy(tmp, keyblob_keyseeds[kb], 0x10);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, tmp);
|
||||
se_aes_unwrap_key(13, 14, tmp);
|
||||
se_aes_key_clear(14);
|
||||
//Decrypt keyblob and set keyslots.
|
||||
se_aes_crypt_ctr(0x0D, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
|
||||
se_aes_key_set(0x0B, keyblob + 0x20 + 0x80, 0x10); // package1 key
|
||||
se_aes_key_set(0x0C, keyblob + 0x20, 0x10);
|
||||
se_aes_key_set(0x0D, keyblob + 0x20, 0x10);
|
||||
|
||||
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
|
||||
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10);
|
||||
se_aes_key_set(12, keyblob + 0x20, 0x10);
|
||||
se_aes_crypt_block_ecb(0x0C, 0, tmp, master_keyseed_retail);
|
||||
|
||||
//TODO: for some reason SE likes to hang if we don't execute an operation here.
|
||||
memcpy(tmp, mkey_keyseed_retail, 0x10);
|
||||
se_aes_crypt_block_ecb(12, 0, tmp, tmp);
|
||||
|
||||
//Generate retail master key.
|
||||
memcpy(tmp, mkey_keyseed_retail, 0x10);
|
||||
se_aes_unwrap_key(12, 12, tmp);
|
||||
|
||||
//Generate console specific key.
|
||||
memcpy(tmp, ckey_keyseed, 0x10);
|
||||
se_aes_unwrap_key(13, 13, tmp);
|
||||
|
||||
memcpy(tmp, key8_keyseed, 0x10);
|
||||
se_key_acc_ctrl(8, 0x15);
|
||||
se_aes_unwrap_key(8, 12, tmp);
|
||||
|
||||
se_key_acc_ctrl(12, 0xFF);
|
||||
se_key_acc_ctrl(13, 0xFF);
|
||||
}
|
||||
break;
|
||||
// 3.0.0~3.0.1 FW
|
||||
case 1:
|
||||
case 2: {
|
||||
|
||||
// keyslot 10
|
||||
memcpy(tmp, keyblob_keyseeds[0], 0x10);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, tmp);
|
||||
se_aes_unwrap_key(10, 14, tmp);
|
||||
|
||||
// keyslot 13
|
||||
memcpy(tmp, keyblob_keyseeds[kb], 0x10);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, tmp);
|
||||
se_aes_unwrap_key(13, 14, tmp);
|
||||
|
||||
se_aes_key_clear(14);
|
||||
se_aes_key_clear(15);
|
||||
|
||||
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
|
||||
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10);
|
||||
se_aes_key_set(12, keyblob + 0x20, 0x10);
|
||||
|
||||
//TODO: for some reason SE likes to hang if we don't execute an operation here.
|
||||
memcpy(tmp, mkey_keyseed_retail, 0x10);
|
||||
se_aes_crypt_block_ecb(12, 0, tmp, tmp);
|
||||
|
||||
//Generate retail master key.
|
||||
memcpy(tmp, mkey_keyseed_retail, 0x10);
|
||||
se_aes_unwrap_key(12, 12, tmp);
|
||||
|
||||
//Generate console specific key.
|
||||
memcpy(tmp, ckey_keyseed, 0x10);
|
||||
se_aes_unwrap_key(13, 10, tmp);
|
||||
se_aes_key_clear(10);
|
||||
|
||||
memcpy(tmp, key8_keyseed, 0x10);
|
||||
se_key_acc_ctrl(8, 0x15);
|
||||
se_aes_unwrap_key(8, 12, tmp);
|
||||
|
||||
se_key_acc_ctrl(12, 0xFF);
|
||||
se_key_acc_ctrl(13, 0xFF);
|
||||
}
|
||||
switch (kb) {
|
||||
case KB_FIRMWARE_VERSION_100_200:
|
||||
case KB_FIRMWARE_VERSION_300:
|
||||
se_aes_unwrap_key(0x0D, 0x0F, console_keyseed);
|
||||
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
|
||||
break;
|
||||
|
||||
// 4.0.0~5.0.1 FW
|
||||
case 3:
|
||||
case 4: {
|
||||
se_key_acc_ctrl(14, 0x15);
|
||||
se_key_acc_ctrl(15, 0x15);
|
||||
case KB_FIRMWARE_VERSION_400:
|
||||
se_aes_unwrap_key(0x0D, 0x0F, console_keyseed_4xx);
|
||||
se_aes_unwrap_key(0x0F, 0x0F, console_keyseed);
|
||||
se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx);
|
||||
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
|
||||
break;
|
||||
|
||||
// keyslot 15
|
||||
memcpy(tmp, keyblob_keyseeds[0], 0x10);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, tmp);
|
||||
se_aes_unwrap_key(15, 14, tmp);
|
||||
|
||||
// keyslot 13
|
||||
memcpy(tmp, keyblob_keyseeds[kb], 0x10);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, tmp);
|
||||
se_aes_unwrap_key(13, 14, tmp);
|
||||
|
||||
se_aes_key_clear(14);
|
||||
|
||||
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
|
||||
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10);
|
||||
se_aes_key_set(12, keyblob + 0x20, 0x10);
|
||||
|
||||
//TODO: for some reason SE likes to hang if we don't execute an operation here.
|
||||
memcpy(tmp, mkey_keyseed_retail, 0x10);
|
||||
se_aes_crypt_block_ecb(12, 0, tmp, tmp);
|
||||
|
||||
// keyslot 14
|
||||
memcpy(tmp, new_masterkey_seed, 0x10);
|
||||
se_aes_unwrap_key(14, 12, tmp);
|
||||
|
||||
// keyslot 12
|
||||
memcpy(tmp, mkey_keyseed_retail, 0x10);
|
||||
se_aes_unwrap_key(12, 12, tmp);
|
||||
|
||||
// keyslot 13
|
||||
memcpy(tmp, new_per_console_key, 0x10);
|
||||
se_aes_unwrap_key(13, 15, tmp);
|
||||
|
||||
// keyslot 15
|
||||
memcpy(tmp, ckey_keyseed, 0x10);
|
||||
se_aes_unwrap_key(15, 13, tmp);
|
||||
|
||||
se_key_acc_ctrl(12, 0xFF);
|
||||
se_key_acc_ctrl(15, 0xFF);
|
||||
}
|
||||
case KB_FIRMWARE_VERSION_500:
|
||||
default:
|
||||
se_aes_unwrap_key(0x0A, 0x0F, console_keyseed_4xx);
|
||||
se_aes_unwrap_key(0x0F, 0x0F, console_keyseed);
|
||||
se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx);
|
||||
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
|
||||
break;
|
||||
}
|
||||
free(tmp);
|
||||
|
||||
// Package2 key
|
||||
se_key_acc_ctrl(0x08, 0x15);
|
||||
se_aes_unwrap_key(0x08, 0x0C, key8_keyseed);
|
||||
}
|
||||
|
||||
|
||||
|
@ -457,38 +387,39 @@ DPRINTF("decrypted and unpacked pkg1\n");
|
|||
{
|
||||
//Else we patch it to allow for an unsigned package2.
|
||||
patch_t *secmon_patchset = ctxt.pkg1_id->secmon_patchset;
|
||||
|
||||
if (secmon_patchset != NULL) {
|
||||
for (u32 i = 0; secmon_patchset[i].off != 0xFFFFFFFF; i++)
|
||||
*(vu32 *)(ctxt.pkg1_id->secmon_base + secmon_patchset[i].off) = secmon_patchset[i].val;
|
||||
|
||||
DPRINTF("loaded warmboot.bin and secmon\n");
|
||||
|
||||
//Read package2.
|
||||
if (!_read_emmc_pkg2(&ctxt))
|
||||
return 0;
|
||||
DPRINTF("loaded warmboot.bin and secmon\n");
|
||||
|
||||
//Read package2.
|
||||
if (!_read_emmc_pkg2(&ctxt))
|
||||
return 0;
|
||||
|
||||
DPRINTF("read pkg2\n");
|
||||
//Decrypt package2 and parse KIP1 blobs in INI1 section.
|
||||
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2);
|
||||
DPRINTF("read pkg2\n");
|
||||
//Decrypt package2 and parse KIP1 blobs in INI1 section.
|
||||
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2);
|
||||
|
||||
LIST_INIT(kip1_info);
|
||||
pkg2_parse_kips(&kip1_info, pkg2_hdr);
|
||||
LIST_INIT(kip1_info);
|
||||
pkg2_parse_kips(&kip1_info, pkg2_hdr);
|
||||
|
||||
DPRINTF("parsed ini1\n");
|
||||
|
||||
//Use the kernel included in package2 in case we didn't load one already.
|
||||
if (!ctxt.kernel)
|
||||
{
|
||||
ctxt.kernel = pkg2_hdr->data;
|
||||
ctxt.kernel_size = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
|
||||
}
|
||||
DPRINTF("parsed ini1\n");
|
||||
|
||||
//Use the kernel included in package2 in case we didn't load one already.
|
||||
if (!ctxt.kernel)
|
||||
{
|
||||
ctxt.kernel = pkg2_hdr->data;
|
||||
ctxt.kernel_size = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
|
||||
}
|
||||
|
||||
//Merge extra KIP1s into loaded ones.
|
||||
LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link)
|
||||
pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1);
|
||||
//Merge extra KIP1s into loaded ones.
|
||||
LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link)
|
||||
pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1);
|
||||
|
||||
//Rebuild and encrypt package2.
|
||||
pkg2_build_encrypt((void *)0xA9800000, ctxt.kernel, ctxt.kernel_size, &kip1_info);
|
||||
//Rebuild and encrypt package2.
|
||||
pkg2_build_encrypt((void *)0xA9800000, ctxt.kernel, ctxt.kernel_size, &kip1_info);
|
||||
DPRINTF("rebuilt pkg2\n");
|
||||
} else {
|
||||
//Read package2.
|
||||
|
@ -500,6 +431,14 @@ DPRINTF("decrypted and unpacked pkg1\n");
|
|||
}
|
||||
}
|
||||
|
||||
se_aes_key_clear(8);
|
||||
se_aes_key_clear(11);
|
||||
//se_aes_key_clear(13);
|
||||
//se_key_acc_ctrl(10, 0xFF);
|
||||
se_key_acc_ctrl(12, 0xFF);
|
||||
//se_key_acc_ctrl(13, 0xFF);
|
||||
//se_key_acc_ctrl(14, 0xFF);
|
||||
se_key_acc_ctrl(15, 0xFF);
|
||||
|
||||
//Clear 'BootConfig'.
|
||||
memset((void *)0x4003D000, 0, 0x3000);
|
||||
|
@ -530,6 +469,10 @@ DPRINTF("decrypted and unpacked pkg1\n");
|
|||
//Signal package2 available.
|
||||
*mb_in = 2;
|
||||
sleep(100);
|
||||
*mb_in = 3;
|
||||
sleep(100);
|
||||
|
||||
|
||||
|
||||
/*PMC(0x4) = 0x7FFFF3;
|
||||
PMC(0x2C4) = 0xFFFFFFFF;
|
||||
|
@ -544,7 +487,7 @@ DPRINTF("decrypted and unpacked pkg1\n");
|
|||
//display_end();
|
||||
|
||||
//Signal to continue boot.
|
||||
*mb_in = 3;
|
||||
*mb_in = 4;
|
||||
sleep(100);
|
||||
|
||||
//Halt ourselves in waitevent state.
|
||||
|
|
|
@ -21,5 +21,6 @@
|
|||
#include "ini.h"
|
||||
|
||||
int hos_launch(ini_sec_t *cfg);
|
||||
int keygen(u8 *keyblob, u32 kb, void *tsec_fw);
|
||||
|
||||
#endif
|
||||
|
|
98
ipl/main.c
98
ipl/main.c
|
@ -730,6 +730,103 @@ void dump_emmc_user() { dump_emmc_selected(DUMP_USER); }
|
|||
void dump_emmc_boot() { dump_emmc_selected(DUMP_BOOT); }
|
||||
void dump_emmc_rawnand() { dump_emmc_selected(DUMP_RAW); }
|
||||
|
||||
u32 save_to_file(void * buf, u32 size, const char * filename)
|
||||
{
|
||||
FIL fp;
|
||||
if (f_open(&fp, filename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
f_sync(&fp);
|
||||
f_write(&fp, buf, size, NULL);
|
||||
f_close(&fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dump_package1()
|
||||
{
|
||||
u8 * pkg1 = (u8 *)malloc(0x40000);
|
||||
u8 * warmboot = (u8 *)malloc(0x40000);
|
||||
u8 * secmon = (u8 *)malloc(0x40000);
|
||||
|
||||
gfx_clear(&gfx_ctxt, 0xFF000000);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
if (!sd_mount())
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kFailed to mount SD card (make sure that it is inserted).%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if(!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kFailed to init eMMC.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
goto out;
|
||||
}
|
||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||
|
||||
//Read package1.
|
||||
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||
const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kCould not identify package 1 version to read TSEC firmware (= '%s').%k\n", 0xFF0000FF, (char *)pkg1 + 0x10, 0xFFFFFFFF);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
// Read keyblob
|
||||
u8 * keyblob = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||
sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + pkg1_id->kb, 1, keyblob);
|
||||
|
||||
// decrypt
|
||||
keygen(keyblob, pkg1_id->kb, (u8 *)pkg1 + pkg1_id->tsec_off);
|
||||
pkg1_decrypt(pkg1_id, pkg1);
|
||||
|
||||
pkg1_unpack(warmboot, secmon, pkg1_id, pkg1);
|
||||
|
||||
// display info
|
||||
gfx_printf(&gfx_con, "%kSecure monitor addr: %08X\n", 0xFF0000FF, pkg1_id->secmon_base);
|
||||
gfx_printf(&gfx_con, "%kSecure monitor size: %08X\n", 0xFF0000FF, hdr->sm_size);
|
||||
gfx_printf(&gfx_con, "%kSecure monitor off: %08X\n", 0xFF0000FF, hdr->sm_off);
|
||||
|
||||
// dump package1
|
||||
if (save_to_file(pkg1, 0x40000, "pkg_decr.bin") == -1) {
|
||||
gfx_printf(&gfx_con, "Failed to create pkg_decr.bin\n");
|
||||
goto out;
|
||||
}
|
||||
gfx_puts(&gfx_con, "%kPackage1 dumped to pkg_decr.bin\n");
|
||||
|
||||
// dump sm
|
||||
if (save_to_file(secmon, 0x40000, "sm.bin") == -1) {
|
||||
gfx_puts(&gfx_con, "Failed to create sm.bin\n");
|
||||
goto out;
|
||||
}
|
||||
gfx_puts(&gfx_con, "Secure Monitor dumped to sm.bin\n");
|
||||
|
||||
// dump warmboot
|
||||
if (save_to_file(warmboot, 0x40000, "warmboot.bin") == -1) {
|
||||
gfx_puts(&gfx_con, "Failed to create warmboot.bin\n");
|
||||
goto out;
|
||||
}
|
||||
gfx_puts(&gfx_con, "Warmboot dumped to warmboot.bin\n");
|
||||
|
||||
|
||||
sdmmc_storage_end(&storage);
|
||||
gfx_puts(&gfx_con, "Done. Press any key.\n");
|
||||
|
||||
out:;
|
||||
free(pkg1);
|
||||
free(secmon);
|
||||
free(warmboot);
|
||||
sleep(100000);
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void launch_firmware()
|
||||
{
|
||||
ini_sec_t *cfg_sec = NULL;
|
||||
|
@ -845,6 +942,7 @@ ment_t ment_tools[] = {
|
|||
MDEF_HANDLER("Dump eMMC SYS", dump_emmc_system),
|
||||
MDEF_HANDLER("Dump eMMC USER", dump_emmc_user),
|
||||
MDEF_HANDLER("Dump eMMC BOOT", dump_emmc_boot),
|
||||
MDEF_HANDLER("Dump Package1", dump_package1),
|
||||
MDEF_END()
|
||||
};
|
||||
menu_t menu_tools = {
|
||||
|
|
33
ipl/pkg1.c
33
ipl/pkg1.c
|
@ -47,6 +47,22 @@ PATCHSET_DEF(_secmon_3_patchset,
|
|||
{ 0xAC8 + 0xADC, _NOP() } //Sections SHA2.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_5_patchset,
|
||||
//Patch package2 decryption and signature/hash checks.
|
||||
{ 0x1218 + 0x6E68, _NOP() }, //Header signature.
|
||||
{ 0x1218 + 0x6E74, _NOP() }, //Version.
|
||||
{ 0x1218 + 0x6FE4, _NOP() }, //Sections SHA2.
|
||||
{ 0x1218 + 0x2DC, _NOP() } //Unknown.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_6_patchset,
|
||||
{ 0x12b0 + 0x4d0, _NOP() },
|
||||
{ 0x12b0 + 0x4dc, _NOP() },
|
||||
{ 0x12b0 + 0x794, _NOP() },
|
||||
{ 0x12b0 + 0xb30, _NOP() }//,
|
||||
//{ 0x12b0 + 0xa18 , _NOP() } // BootConfig Retail Check
|
||||
);
|
||||
|
||||
/*
|
||||
* package1.1 header: <wb, ldr, sm>
|
||||
* package1.1 layout:
|
||||
|
@ -62,23 +78,12 @@ static const pkg1_id_t _pkg1_ids[] = {
|
|||
{ "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, 0x40014020, _secmon_1_patchset }, //1.0.0
|
||||
{ "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, _secmon_2_patchset }, //2.0.0
|
||||
{ "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, NULL }, //3.0.0
|
||||
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, NULL }, //3.0.1
|
||||
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, NULL }, //4.0.0
|
||||
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, NULL }, //5.0.0
|
||||
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, NULL }, //3.0.1
|
||||
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, _secmon_5_patchset }, //4.0.0
|
||||
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, _secmon_6_patchset }, //5.0.0
|
||||
{ NULL, 0, 0, 0, 0 } //End.
|
||||
};
|
||||
|
||||
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;
|
||||
} pk11_hdr_t;
|
||||
|
||||
const pkg1_id_t *pkg1_identify(u8 *pkg1)
|
||||
{
|
||||
|
|
13
ipl/pkg1.h
13
ipl/pkg1.h
|
@ -42,6 +42,19 @@ typedef struct _pkg1_id_t
|
|||
patch_t *secmon_patchset;
|
||||
} 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;
|
||||
} pk11_hdr_t;
|
||||
|
||||
const pkg1_id_t *pkg1_identify(u8 *pkg1);
|
||||
void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1);
|
||||
void pkg1_unpack(void *warmboot_dst, void *secmon_dst, const pkg1_id_t *id, u8 *pkg1);
|
||||
|
|
|
@ -172,3 +172,4 @@ DPRINTF("INI1 encrypted\n");
|
|||
memset(hdr->ctr, 0 , 0x10);
|
||||
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
|
||||
}
|
||||
|
||||
|
|
10
ipl/se.c
10
ipl/se.c
|
@ -67,7 +67,7 @@ static int _se_wait()
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int _se_execute(u32 op, void *dst, u32 dst_size, void *src, u32 src_size)
|
||||
static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||
{
|
||||
se_ll_t *ll_dst = NULL, *ll_src = NULL;
|
||||
|
||||
|
@ -99,7 +99,7 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, void *src, u32 src_size)
|
|||
return res;
|
||||
}
|
||||
|
||||
static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, void *src, u32 src_size)
|
||||
static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||
{
|
||||
u8 *block = (u8 *)malloc(0x10);
|
||||
memset(block, 0, 0x10);
|
||||
|
@ -156,7 +156,7 @@ void se_aes_key_clear(u32 ks)
|
|||
}
|
||||
}
|
||||
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, void *input)
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTAB);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
||||
|
@ -164,7 +164,7 @@ int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, void *input)
|
|||
return _se_execute(OP_START, NULL, 0, input, 0x10);
|
||||
}
|
||||
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, void *src)
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src)
|
||||
{
|
||||
if (enc)
|
||||
{
|
||||
|
@ -180,7 +180,7 @@ int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, void *src)
|
|||
return _se_execute(OP_START, dst, 0x10, src, 0x10);
|
||||
}
|
||||
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, void *src, u32 src_size, void *ctr)
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr)
|
||||
{
|
||||
SE(SE_SPARE_0_REG_OFFSET) = 1;
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
|
|
7
ipl/se.h
7
ipl/se.h
|
@ -23,8 +23,7 @@ void se_rsa_acc_ctrl(u32 rs, u32 flags);
|
|||
void se_key_acc_ctrl(u32 ks, u32 flags);
|
||||
void se_aes_key_set(u32 ks, void *key, u32 size);
|
||||
void se_aes_key_clear(u32 ks);
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, void *input);
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, void *src);
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, void *src, u32 src_size, void *ctr);
|
||||
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue