mirror of
https://github.com/CTCaer/hekate
synced 2024-12-22 19:31:12 +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
207
ipl/hos.c
207
ipl/hos.c
|
@ -32,11 +32,20 @@
|
||||||
#include "pkg2.h"
|
#include "pkg2.h"
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
|
||||||
/*#include "gfx.h"
|
#include "gfx.h"
|
||||||
extern gfx_ctxt_t gfx_ctxt;
|
extern gfx_ctxt_t gfx_ctxt;
|
||||||
extern gfx_con_t gfx_con;
|
extern gfx_con_t gfx_con;
|
||||||
#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)*/
|
#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)
|
||||||
#define DPRINTF(...)
|
//#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
|
#define NUM_KEYBLOB_KEYS 5
|
||||||
static const u8 keyblob_keyseeds[NUM_KEYBLOB_KEYS][0x10] = {
|
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] =
|
static const u8 cmac_keyseed[0x10] =
|
||||||
{ 0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5 };
|
{ 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 };
|
{ 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 };
|
{ 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 };
|
||||||
|
|
||||||
static const u8 key8_keyseed[] =
|
static const u8 key8_keyseed[] =
|
||||||
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
|
{ 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 };
|
{ 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 };
|
{ 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
|
// <-- 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(0x0D, 0x15);
|
||||||
se_key_acc_ctrl(13, 0x15);
|
se_key_acc_ctrl(0x0E, 0x15);
|
||||||
|
|
||||||
//Get TSEC key.
|
//Get TSEC key.
|
||||||
if (tsec_query(tmp, 1, tsec_fw) < 0)
|
if (tsec_query(tmp, 1, tsec_fw) < 0)
|
||||||
return 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.
|
//TODO: verify keyblob CMAC.
|
||||||
//se_aes_unwrap_key(11, 13, cmac_keyseed);
|
//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))
|
//if (!memcmp(keyblob, tmp, 0x10))
|
||||||
// return 0;
|
// return 0;
|
||||||
|
|
||||||
|
se_aes_crypt_block_ecb(0x0D, 0, tmp, cmac_keyseed);
|
||||||
|
se_aes_unwrap_key(0x0B, 0x0D, cmac_keyseed);
|
||||||
|
|
||||||
|
//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_block_ecb(0x0C, 0, tmp, master_keyseed_retail);
|
||||||
|
|
||||||
switch (kb) {
|
switch (kb) {
|
||||||
// 1.0.0~2.0.0 FW
|
case KB_FIRMWARE_VERSION_100_200:
|
||||||
case 0: {
|
case KB_FIRMWARE_VERSION_300:
|
||||||
|
se_aes_unwrap_key(0x0D, 0x0F, console_keyseed);
|
||||||
//Derive keyblob key from TSEC+SBK.
|
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
|
||||||
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);
|
|
||||||
|
|
||||||
//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);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 4.0.0~5.0.1 FW
|
case KB_FIRMWARE_VERSION_400:
|
||||||
case 3:
|
se_aes_unwrap_key(0x0D, 0x0F, console_keyseed_4xx);
|
||||||
case 4: {
|
se_aes_unwrap_key(0x0F, 0x0F, console_keyseed);
|
||||||
se_key_acc_ctrl(14, 0x15);
|
se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx);
|
||||||
se_key_acc_ctrl(15, 0x15);
|
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
|
||||||
|
break;
|
||||||
|
|
||||||
// keyslot 15
|
case KB_FIRMWARE_VERSION_500:
|
||||||
memcpy(tmp, keyblob_keyseeds[0], 0x10);
|
default:
|
||||||
se_aes_crypt_block_ecb(13, 0, tmp, tmp);
|
se_aes_unwrap_key(0x0A, 0x0F, console_keyseed_4xx);
|
||||||
se_aes_unwrap_key(15, 14, tmp);
|
se_aes_unwrap_key(0x0F, 0x0F, console_keyseed);
|
||||||
|
se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx);
|
||||||
// keyslot 13
|
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
|
||||||
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);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
free(tmp);
|
|
||||||
|
// Package2 key
|
||||||
|
se_key_acc_ctrl(0x08, 0x15);
|
||||||
|
se_aes_unwrap_key(0x08, 0x0C, key8_keyseed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -457,6 +387,7 @@ DPRINTF("decrypted and unpacked pkg1\n");
|
||||||
{
|
{
|
||||||
//Else we patch it to allow for an unsigned package2.
|
//Else we patch it to allow for an unsigned package2.
|
||||||
patch_t *secmon_patchset = ctxt.pkg1_id->secmon_patchset;
|
patch_t *secmon_patchset = ctxt.pkg1_id->secmon_patchset;
|
||||||
|
|
||||||
if (secmon_patchset != NULL) {
|
if (secmon_patchset != NULL) {
|
||||||
for (u32 i = 0; secmon_patchset[i].off != 0xFFFFFFFF; i++)
|
for (u32 i = 0; secmon_patchset[i].off != 0xFFFFFFFF; i++)
|
||||||
*(vu32 *)(ctxt.pkg1_id->secmon_base + secmon_patchset[i].off) = secmon_patchset[i].val;
|
*(vu32 *)(ctxt.pkg1_id->secmon_base + secmon_patchset[i].off) = secmon_patchset[i].val;
|
||||||
|
@ -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'.
|
//Clear 'BootConfig'.
|
||||||
memset((void *)0x4003D000, 0, 0x3000);
|
memset((void *)0x4003D000, 0, 0x3000);
|
||||||
|
@ -530,6 +469,10 @@ DPRINTF("decrypted and unpacked pkg1\n");
|
||||||
//Signal package2 available.
|
//Signal package2 available.
|
||||||
*mb_in = 2;
|
*mb_in = 2;
|
||||||
sleep(100);
|
sleep(100);
|
||||||
|
*mb_in = 3;
|
||||||
|
sleep(100);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*PMC(0x4) = 0x7FFFF3;
|
/*PMC(0x4) = 0x7FFFF3;
|
||||||
PMC(0x2C4) = 0xFFFFFFFF;
|
PMC(0x2C4) = 0xFFFFFFFF;
|
||||||
|
@ -544,7 +487,7 @@ DPRINTF("decrypted and unpacked pkg1\n");
|
||||||
//display_end();
|
//display_end();
|
||||||
|
|
||||||
//Signal to continue boot.
|
//Signal to continue boot.
|
||||||
*mb_in = 3;
|
*mb_in = 4;
|
||||||
sleep(100);
|
sleep(100);
|
||||||
|
|
||||||
//Halt ourselves in waitevent state.
|
//Halt ourselves in waitevent state.
|
||||||
|
|
|
@ -21,5 +21,6 @@
|
||||||
#include "ini.h"
|
#include "ini.h"
|
||||||
|
|
||||||
int hos_launch(ini_sec_t *cfg);
|
int hos_launch(ini_sec_t *cfg);
|
||||||
|
int keygen(u8 *keyblob, u32 kb, void *tsec_fw);
|
||||||
|
|
||||||
#endif
|
#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_boot() { dump_emmc_selected(DUMP_BOOT); }
|
||||||
void dump_emmc_rawnand() { dump_emmc_selected(DUMP_RAW); }
|
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()
|
void launch_firmware()
|
||||||
{
|
{
|
||||||
ini_sec_t *cfg_sec = NULL;
|
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 SYS", dump_emmc_system),
|
||||||
MDEF_HANDLER("Dump eMMC USER", dump_emmc_user),
|
MDEF_HANDLER("Dump eMMC USER", dump_emmc_user),
|
||||||
MDEF_HANDLER("Dump eMMC BOOT", dump_emmc_boot),
|
MDEF_HANDLER("Dump eMMC BOOT", dump_emmc_boot),
|
||||||
|
MDEF_HANDLER("Dump Package1", dump_package1),
|
||||||
MDEF_END()
|
MDEF_END()
|
||||||
};
|
};
|
||||||
menu_t menu_tools = {
|
menu_t menu_tools = {
|
||||||
|
|
31
ipl/pkg1.c
31
ipl/pkg1.c
|
@ -47,6 +47,22 @@ PATCHSET_DEF(_secmon_3_patchset,
|
||||||
{ 0xAC8 + 0xADC, _NOP() } //Sections SHA2.
|
{ 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 header: <wb, ldr, sm>
|
||||||
* package1.1 layout:
|
* package1.1 layout:
|
||||||
|
@ -63,22 +79,11 @@ static const pkg1_id_t _pkg1_ids[] = {
|
||||||
{ "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, _secmon_2_patchset }, //2.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
|
{ "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, NULL }, //3.0.0
|
||||||
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, NULL }, //3.0.1
|
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, NULL }, //3.0.1
|
||||||
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, NULL }, //4.0.0
|
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, _secmon_5_patchset }, //4.0.0
|
||||||
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, NULL }, //5.0.0
|
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, _secmon_6_patchset }, //5.0.0
|
||||||
{ NULL, 0, 0, 0, 0 } //End.
|
{ 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)
|
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;
|
patch_t *secmon_patchset;
|
||||||
} pkg1_id_t;
|
} 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);
|
const pkg1_id_t *pkg1_identify(u8 *pkg1);
|
||||||
void pkg1_decrypt(const pkg1_id_t *id, 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);
|
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);
|
memset(hdr->ctr, 0 , 0x10);
|
||||||
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
|
*(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;
|
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;
|
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;
|
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);
|
u8 *block = (u8 *)malloc(0x10);
|
||||||
memset(block, 0, 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_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);
|
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);
|
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)
|
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);
|
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_SPARE_0_REG_OFFSET) = 1;
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
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_key_acc_ctrl(u32 ks, u32 flags);
|
||||||
void se_aes_key_set(u32 ks, void *key, u32 size);
|
void se_aes_key_set(u32 ks, void *key, u32 size);
|
||||||
void se_aes_key_clear(u32 ks);
|
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);
|
||||||
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);
|
||||||
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);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue