hos: refactor keyblob to eks and kb to mkey

Use the official name for keyblob which is EKS.
For that reason the keyblob version enum is renamed to master key version.
This commit is contained in:
CTCaer
2025-08-08 15:29:02 +03:00
parent f083dcd280
commit 885cc195c0
16 changed files with 334 additions and 322 deletions

View File

@@ -66,29 +66,7 @@ typedef struct _secmon_mailbox_t
u32 out;
} secmon_mailbox_t;
typedef struct _tsec_keys_t
{
u8 tsec[SE_KEY_128_SIZE];
u8 tsec_root[SE_KEY_128_SIZE];
u8 tmp[SE_KEY_128_SIZE];
} tsec_keys_t;
typedef struct _kb_keys_t
{
u8 master_kekseed[SE_KEY_128_SIZE];
u8 random_data[0x70];
u8 package1_key[SE_KEY_128_SIZE];
} kb_keys_t;
typedef struct _kb_t
{
u8 cmac[SE_KEY_128_SIZE];
u8 ctr[SE_AES_IV_SIZE];
kb_keys_t keys;
u8 padding[0x150];
} kb_t;
static const u8 keyblob_keyseeds[HOS_KB_VERSION_600 - HOS_KB_VERSION_100 + 1][SE_KEY_128_SIZE] = {
static const u8 eks_keyseeds[HOS_MKEY_VER_600 - HOS_MKEY_VER_100 + 1][SE_KEY_128_SIZE] = {
{ 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 }, // 1.0.0.
{ 0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC }, // 3.0.0.
{ 0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B }, // 3.0.1.
@@ -110,7 +88,7 @@ static const u8 master_kekseed_620[SE_KEY_128_SIZE] =
{ 0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A };
//!TODO: Update on tsec/mkey changes.
static const u8 master_kekseed_t210_tsec_v4[HOS_KB_VERSION_MAX - HOS_KB_VERSION_810 + 1][SE_KEY_128_SIZE] = {
static const u8 master_kekseed_t210_tsec_v4[HOS_MKEY_VER_MAX - HOS_MKEY_VER_810 + 1][SE_KEY_128_SIZE] = {
{ 0xDE, 0xDC, 0xE3, 0x39, 0x30, 0x88, 0x16, 0xF8, 0xAE, 0x97, 0xAD, 0xEC, 0x64, 0x2D, 0x41, 0x41 }, // 8.1.0.
{ 0x1A, 0xEC, 0x11, 0x82, 0x2B, 0x32, 0x38, 0x7A, 0x2B, 0xED, 0xBA, 0x01, 0x47, 0x7E, 0x3B, 0x67 }, // 9.0.0.
{ 0x30, 0x3F, 0x02, 0x7E, 0xD8, 0x38, 0xEC, 0xD7, 0x93, 0x25, 0x34, 0xB5, 0x30, 0xEB, 0xCA, 0x7A }, // 9.1.0.
@@ -126,7 +104,7 @@ static const u8 master_kekseed_t210_tsec_v4[HOS_KB_VERSION_MAX - HOS_KB_VERSION_
};
//!TODO: Update on mkey changes.
static const u8 master_kekseed_t210b01[HOS_KB_VERSION_MAX - HOS_KB_VERSION_600 + 1][SE_KEY_128_SIZE] = {
static const u8 master_kekseed_t210b01[HOS_MKEY_VER_MAX - HOS_MKEY_VER_600 + 1][SE_KEY_128_SIZE] = {
{ 0x77, 0x60, 0x5A, 0xD2, 0xEE, 0x6E, 0xF8, 0x3C, 0x3F, 0x72, 0xE2, 0x59, 0x9D, 0xAC, 0x5E, 0x56 }, // 6.0.0.
{ 0x1E, 0x80, 0xB8, 0x17, 0x3E, 0xC0, 0x60, 0xAA, 0x11, 0xBE, 0x1A, 0x4A, 0xA6, 0x6F, 0xE4, 0xAE }, // 6.2.0.
{ 0x94, 0x08, 0x67, 0xBD, 0x0A, 0x00, 0x38, 0x84, 0x11, 0xD3, 0x1A, 0xDB, 0xDD, 0x8D, 0xF1, 0x8A }, // 7.0.0.
@@ -303,13 +281,13 @@ out:
}
}
static void _hos_eks_clear(u32 kb)
static void _hos_eks_clear(u32 mkey)
{
// Check if Erista based unit.
if (h_cfg.t210b01)
return;
if (h_cfg.eks && kb >= HOS_KB_VERSION_700)
if (h_cfg.eks && mkey >= HOS_MKEY_VER_700)
{
// Check if current Master key is enabled.
if (h_cfg.eks->enabled)
@@ -338,16 +316,22 @@ out:
}
}
static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool is_exo)
typedef struct _tsec_keys_t
{
u8 tsec[SE_KEY_128_SIZE];
u8 tsec_root[SE_KEY_128_SIZE];
u8 tmp[SE_KEY_128_SIZE];
} tsec_keys_t;
static int _hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt, bool stock, bool is_exo)
{
static bool sbk_is_set = true;
u32 retries = 0;
bool use_tsec = false;
tsec_keys_t tsec_keys;
kb_t *kb_data = (kb_t *)keyblob;
if (kb > HOS_KB_VERSION_MAX)
if (mkey > HOS_MKEY_VER_MAX)
return 0;
// Do Mariko keygen.
@@ -357,7 +341,7 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock
se_aes_unwrap_key(10, 14, console_keyseed_4xx);
// Derive master key.
se_aes_unwrap_key(7, 12, master_kekseed_t210b01[kb - HOS_KB_VERSION_600]);
se_aes_unwrap_key(7, 12, master_kekseed_t210b01[mkey - HOS_MKEY_VER_600]);
se_aes_unwrap_key(7, 7, master_keyseed_retail);
// Derive latest pkg2 key.
@@ -381,15 +365,15 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock
_hos_eks_get();
// Use tsec keygen for old firmware or if EKS keys does not exist for newer.
if (kb <= HOS_KB_VERSION_620 || !h_cfg.eks || (h_cfg.eks->enabled != HOS_EKS_TSEC_VER))
if (mkey <= HOS_MKEY_VER_620 || !h_cfg.eks || (h_cfg.eks->enabled != HOS_EKS_TSEC_VER))
use_tsec = true;
if (kb <= HOS_KB_VERSION_600)
if (mkey <= HOS_MKEY_VER_600)
{
tsec_ctxt->size = 0xF00;
tsec_ctxt->type = TSEC_FW_TYPE_OLD;
}
else if (kb == HOS_KB_VERSION_620)
else if (mkey == HOS_MKEY_VER_620)
{
tsec_ctxt->size = 0x2900;
tsec_ctxt->type = TSEC_FW_TYPE_EMU;
@@ -439,7 +423,7 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock
}
}
if (kb >= HOS_KB_VERSION_700)
if (mkey >= HOS_MKEY_VER_700)
{
// For 7.0.0 and up, save EKS slot if it doesn't exist.
if (use_tsec)
@@ -450,8 +434,8 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock
// Use 8.1.0 for 7.0.0 otherwise the proper one.
u32 mkey_idx = 0;
if (kb >= HOS_KB_VERSION_810)
mkey_idx = kb - HOS_KB_VERSION_810;
if (mkey >= HOS_MKEY_VER_810)
mkey_idx = mkey - HOS_MKEY_VER_810;
if (!is_exo)
{
@@ -462,7 +446,8 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock
}
else
{
se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, keyblob_keyseeds[0]);
// Decrypt eks and set keyslots.
se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tmp);
// Derive device keys.
@@ -480,7 +465,7 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock
se_aes_unwrap_key(8, 13, package2_keyseed);
}
}
else if (kb == HOS_KB_VERSION_620)
else if (mkey == HOS_MKEY_VER_620)
{
// Set TSEC key.
se_aes_key_set(12, tsec_keys.tsec, SE_KEY_128_SIZE);
@@ -497,8 +482,8 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock
}
else
{
// Decrypt keyblob and set keyslots for Exosphere 2.
se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, keyblob_keyseeds[0]);
// Decrypt eks and set keyslots for Exosphere 2.
se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tmp);
// Derive device keys.
@@ -524,54 +509,54 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock
// Set TSEC key.
se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE);
// Derive keyblob keys from TSEC+SBK.
se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, keyblob_keyseeds[0]);
// Derive eks keys from TSEC+SBK.
se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tsec);
se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, keyblob_keyseeds[kb]);
se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[mkey]);
se_aes_unwrap_key(13, 14, tsec_keys.tsec);
// Clear SBK.
//se_aes_key_clear(14);
/*
// Verify keyblob CMAC.
// Verify eks CMAC.
u8 cmac[SE_KEY_128_SIZE];
se_aes_unwrap_key(11, 13, cmac_keyseed);
se_aes_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)kb_data->ctr, sizeof(kb_data->ctr) + sizeof(kb_data->keys));
if (!memcmp(kb_data->cmac, cmac, SE_KEY_128_SIZE))
se_aes_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)eks->ctr, sizeof(eks->ctr) + sizeof(eks->keys));
if (!memcmp(eks->cmac, cmac, SE_KEY_128_SIZE))
return 0;
*/
se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, cmac_keyseed);
se_aes_unwrap_key(11, 13, cmac_keyseed);
// Decrypt keyblob and set keyslots.
se_aes_crypt_ctr(13, &kb_data->keys, sizeof(kb_keys_t), &kb_data->keys, sizeof(kb_keys_t), kb_data->ctr);
se_aes_key_set(11, kb_data->keys.package1_key, SE_KEY_128_SIZE);
se_aes_key_set(12, kb_data->keys.master_kekseed, SE_KEY_128_SIZE);
se_aes_key_set(13, kb_data->keys.master_kekseed, SE_KEY_128_SIZE);
// Decrypt eks and set keyslots.
se_aes_crypt_ctr(13, &eks->keys, sizeof(eks_keys_t), &eks->keys, sizeof(eks_keys_t), eks->ctr);
se_aes_key_set(11, eks->keys.package1_key, SE_KEY_128_SIZE);
se_aes_key_set(12, eks->keys.master_kekseed, SE_KEY_128_SIZE);
se_aes_key_set(13, eks->keys.master_kekseed, SE_KEY_128_SIZE);
se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tsec, master_keyseed_retail);
if (!is_exo)
{
switch (kb)
switch (mkey)
{
case HOS_KB_VERSION_100:
case HOS_KB_VERSION_300:
case HOS_KB_VERSION_301:
case HOS_MKEY_VER_100:
case HOS_MKEY_VER_300:
case HOS_MKEY_VER_301:
se_aes_unwrap_key(13, 15, console_keyseed);
se_aes_unwrap_key(12, 12, master_keyseed_retail);
break;
case HOS_KB_VERSION_400:
case HOS_MKEY_VER_400:
se_aes_unwrap_key(13, 15, console_keyseed_4xx);
se_aes_unwrap_key(15, 15, console_keyseed);
se_aes_unwrap_key(14, 12, master_keyseed_4xx);
se_aes_unwrap_key(12, 12, master_keyseed_retail);
sbk_is_set = false;
break;
case HOS_KB_VERSION_500:
case HOS_KB_VERSION_600:
case HOS_MKEY_VER_500:
case HOS_MKEY_VER_600:
se_aes_unwrap_key(10, 15, console_keyseed_4xx);
se_aes_unwrap_key(15, 15, console_keyseed);
se_aes_unwrap_key(14, 12, master_keyseed_4xx);
@@ -644,13 +629,15 @@ try_load:
return 0;
}
gfx_printf("Identified pkg1 and mkey %d\n\n", ctxt->pkg1_id->kb);
gfx_printf("Identified pkg1 and mkey %d\n\n", ctxt->pkg1_id->mkey);
// Read the correct keyblob for older HOS versions.
if (ctxt->pkg1_id->kb <= HOS_KB_VERSION_600)
// Read the correct eks for older HOS versions.
if (ctxt->pkg1_id->mkey <= HOS_MKEY_VER_600)
{
ctxt->keyblob = (u8 *)zalloc(EMMC_BLOCKSIZE);
emummc_storage_read(PKG1_HOS_KEYBLOBS_OFFSET / EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob);
const u32 eks_size = sizeof(pkg1_eks_t);
ctxt->eks = (pkg1_eks_t *)malloc(eks_size);
emummc_storage_read(PKG1_HOS_EKS_OFFSET + (ctxt->pkg1_id->mkey * eks_size) / EMMC_BLOCKSIZE,
eks_size / EMMC_BLOCKSIZE, ctxt->eks);
}
return 1;
@@ -699,7 +686,7 @@ static void _free_launch_components(launch_ctxt_t *ctxt)
{
// Free the malloc'ed guaranteed addresses.
free(ctxt->pkg3);
free(ctxt->keyblob);
free(ctxt->eks);
free(ctxt->pkg1);
free(ctxt->pkg2);
free(ctxt->warmboot);
@@ -750,7 +737,7 @@ static bool _get_fs_exfat_compatible(link_t *info, u32 *hos_revision)
void hos_launch(ini_sec_t *cfg)
{
u8 kb;
u8 mkey;
u32 secmon_base;
u32 warmboot_base;
bool is_exo = false;
@@ -792,7 +779,7 @@ void hos_launch(ini_sec_t *cfg)
goto error;
}
// Read package1 and the correct keyblob.
// Read package1 and the correct eks.
if (!_read_emmc_pkg1(&ctxt))
{
// Check if stock is enabled and device can boot in OFW.
@@ -809,7 +796,7 @@ void hos_launch(ini_sec_t *cfg)
goto error;
}
kb = ctxt.pkg1_id->kb;
mkey = ctxt.pkg1_id->mkey;
bool emummc_enabled = emu_cfg.enabled && !h_cfg.emummc_force_disable;
@@ -874,7 +861,7 @@ void hos_launch(ini_sec_t *cfg)
tsec_ctxt.pkg11_off = ctxt.pkg1_id->pkg11_off;
// Generate keys.
if (!_hos_keygen(ctxt.keyblob, kb, &tsec_ctxt, ctxt.stock, is_exo))
if (!_hos_keygen(ctxt.eks, mkey, &tsec_ctxt, ctxt.stock, is_exo))
goto error;
gfx_puts("Generated keys\n");
@@ -882,7 +869,7 @@ void hos_launch(ini_sec_t *cfg)
if (!ctxt.warmboot || !ctxt.secmon)
{
// Decrypt PK1 or PK11.
if (kb <= HOS_KB_VERSION_600 || h_cfg.t210b01)
if (mkey <= HOS_MKEY_VER_600 || h_cfg.t210b01)
{
if (!pkg1_decrypt(ctxt.pkg1_id, ctxt.pkg1))
{
@@ -903,7 +890,7 @@ void hos_launch(ini_sec_t *cfg)
}
// Unpack PK11.
if (h_cfg.t210b01 || (kb <= HOS_KB_VERSION_620 && !emummc_enabled))
if (h_cfg.t210b01 || (mkey <= HOS_MKEY_VER_620 && !emummc_enabled))
{
// Skip T210B01 OEM header.
u32 pk1_offset = 0;
@@ -924,7 +911,7 @@ void hos_launch(ini_sec_t *cfg)
}
// Configure and manage Warmboot binary.
if (!pkg1_warmboot_config(&ctxt, warmboot_base, ctxt.pkg1_id->fuses, kb))
if (!pkg1_warmboot_config(&ctxt, warmboot_base, ctxt.pkg1_id->fuses, mkey))
{
// Can only happen on T210B01.
_hos_crit_error("\nFailed to match warmboot with fuses!\nIf you continue, sleep wont work!");
@@ -942,7 +929,7 @@ void hos_launch(ini_sec_t *cfg)
else if (!h_cfg.t210b01)
{
// Patch warmboot on T210 to allow downgrading.
if (kb >= HOS_KB_VERSION_700)
if (mkey >= HOS_MKEY_VER_700)
{
_hos_crit_error("No warmboot provided!");
goto error;
@@ -970,13 +957,13 @@ void hos_launch(ini_sec_t *cfg)
gfx_puts("Read pkg2\n");
// Decrypt package2 and parse KIP1 blobs in INI1 section.
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2, kb, is_exo);
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2, mkey, is_exo);
if (!pkg2_hdr)
{
_hos_crit_error("Pkg2 decryption failed!\npkg1/pkg2 mismatch or old hekate!");
// Clear EKS slot, in case something went wrong with tsec keygen.
_hos_eks_clear(kb);
_hos_eks_clear(mkey);
goto error;
}
@@ -1043,7 +1030,7 @@ void hos_launch(ini_sec_t *cfg)
pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1);
// Check if FS is compatible with exFAT and if 5.1.0.
if (!ctxt.stock && (sd_fs.fs_type == FS_EXFAT || kb == HOS_KB_VERSION_500 || ctxt.pkg1_id->fuses == 13))
if (!ctxt.stock && (sd_fs.fs_type == FS_EXFAT || mkey == HOS_MKEY_VER_500 || ctxt.pkg1_id->fuses == 13))
{
bool exfat_compat = _get_fs_exfat_compatible(&kip1_info, &ctxt.exo_ctx.hos_revision);
@@ -1099,25 +1086,25 @@ void hos_launch(ini_sec_t *cfg)
u32 pkg1_state_pkg2_ready = PKG1_STATE_PKG2_READY;
// Finalize per firmware key access. Skip access control if Exosphere 2.
switch (kb | (is_exo << 7))
switch (mkey | (is_exo << 7))
{
case HOS_KB_VERSION_100:
case HOS_KB_VERSION_300:
case HOS_KB_VERSION_301:
case HOS_MKEY_VER_100:
case HOS_MKEY_VER_300:
case HOS_MKEY_VER_301:
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG);
se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG);
pkg1_state_pkg2_ready = PKG1_STATE_PKG2_READY_OLD;
break;
case HOS_KB_VERSION_400:
case HOS_KB_VERSION_500:
case HOS_KB_VERSION_600:
case HOS_MKEY_VER_400:
case HOS_MKEY_VER_500:
case HOS_MKEY_VER_600:
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG);
se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG);
break;
}
// Clear BCT area for retail units and copy it over if dev unit.
if (kb <= HOS_KB_VERSION_500 && !is_exo)
if (mkey <= HOS_MKEY_VER_500 && !is_exo)
{
memset((void *)SECMON_BCT_CFG_ADDR, 0, SZ_4K + SZ_8K);
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV)
@@ -1131,11 +1118,11 @@ void hos_launch(ini_sec_t *cfg)
}
// Finalize MC carveout.
if (kb <= HOS_KB_VERSION_301 && !is_exo)
if (mkey <= HOS_MKEY_VER_301 && !is_exo)
mc_config_carveout();
// Lock SE before starting 'SecureMonitor' if < 6.2.0, otherwise lock bootrom and ipatches.
_se_lock(kb <= HOS_KB_VERSION_600 && !is_exo);
// Lock SE before starting secmon if < 6.2.0, otherwise lock bootrom and ipatches.
_se_lock(mkey <= HOS_MKEY_VER_600 && !is_exo);
// Reset sysctr0 counters. Mandatory for 6.2.0 and up.
for (u32 i = 0; i < SYSCTR0_COUNTERS; i++)
@@ -1146,14 +1133,14 @@ void hos_launch(ini_sec_t *cfg)
// Set secmon mailbox address and clear it.
volatile secmon_mailbox_t *secmon_mailbox;
if (kb >= HOS_KB_VERSION_700 || is_exo)
if (mkey >= HOS_MKEY_VER_700 || is_exo)
{
memset((void *)SECMON7_MAILBOX_ADDR, 0, 0x200);
secmon_mailbox = (secmon_mailbox_t *)(SECMON7_MAILBOX_ADDR + SECMON_STATE_OFFSET);
}
else
{
if (kb <= HOS_KB_VERSION_301)
if (mkey <= HOS_MKEY_VER_301)
memset((void *)SECMON_MAILBOX_ADDR, 0, 0x200);
secmon_mailbox = (secmon_mailbox_t *)(SECMON_MAILBOX_ADDR + SECMON_STATE_OFFSET);
}
@@ -1162,7 +1149,7 @@ void hos_launch(ini_sec_t *cfg)
secmon_mailbox->in = pkg1_state_pkg2_ready;
secmon_mailbox->out = SECMON_STATE_NOT_READY;
// Disable display. This must be executed before secmon to provide support for all fw versions.
// Disable display.
display_end();
clock_disable_host1x();

View File

@@ -27,34 +27,34 @@
//!TODO: Update on mkey changes.
enum {
HOS_KB_VERSION_100 = 0,
HOS_KB_VERSION_300 = 1,
HOS_KB_VERSION_301 = 2,
HOS_KB_VERSION_400 = 3,
HOS_KB_VERSION_500 = 4,
HOS_KB_VERSION_600 = 5,
HOS_KB_VERSION_620 = 6,
HOS_KB_VERSION_700 = 7,
HOS_KB_VERSION_810 = 8,
HOS_KB_VERSION_900 = 9,
HOS_KB_VERSION_910 = 10,
HOS_KB_VERSION_1210 = 11,
HOS_KB_VERSION_1300 = 12,
HOS_KB_VERSION_1400 = 13,
HOS_KB_VERSION_1500 = 14,
HOS_KB_VERSION_1600 = 15,
HOS_KB_VERSION_1700 = 16,
HOS_KB_VERSION_1800 = 17,
HOS_KB_VERSION_1900 = 18,
HOS_KB_VERSION_2000 = 19,
HOS_KB_VERSION_MAX = HOS_KB_VERSION_2000
HOS_MKEY_VER_100 = 0,
HOS_MKEY_VER_300 = 1,
HOS_MKEY_VER_301 = 2,
HOS_MKEY_VER_400 = 3,
HOS_MKEY_VER_500 = 4,
HOS_MKEY_VER_600 = 5,
HOS_MKEY_VER_620 = 6,
HOS_MKEY_VER_700 = 7,
HOS_MKEY_VER_810 = 8,
HOS_MKEY_VER_900 = 9,
HOS_MKEY_VER_910 = 10,
HOS_MKEY_VER_1210 = 11,
HOS_MKEY_VER_1300 = 12,
HOS_MKEY_VER_1400 = 13,
HOS_MKEY_VER_1500 = 14,
HOS_MKEY_VER_1600 = 15,
HOS_MKEY_VER_1700 = 16,
HOS_MKEY_VER_1800 = 17,
HOS_MKEY_VER_1900 = 18,
HOS_MKEY_VER_2000 = 19,
HOS_MKEY_VER_MAX = HOS_MKEY_VER_2000
};
#define HOS_TSEC_VERSION 4 //! TODO: Update on TSEC Root Key changes.
#define HOS_PKG11_MAGIC 0x31314B50
#define HOS_EKS_MAGIC 0x31534B45 // EKS1.
#define HOS_EKS_TSEC_VER (HOS_KB_VERSION_700 + HOS_TSEC_VERSION)
#define HOS_EKS_TSEC_VER (HOS_MKEY_VER_700 + HOS_TSEC_VERSION)
// Use official Mariko secmon when in stock. Needs access to TZRAM.
//#define HOS_MARIKO_STOCK_SECMON
@@ -84,7 +84,7 @@ static_assert(sizeof(hos_eks_mbr_t) == 64, "HOS EKS size is wrong!");
typedef struct _launch_ctxt_t
{
void *keyblob;
pkg1_eks_t *eks;
void *pkg1;
const pkg1_id_t *pkg1_id;

View File

@@ -141,7 +141,7 @@ static const u8 sec_map_100[3] = { PK11_SECTION_SM, PK11_SECTION_LD, PK11_SECTIO
static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTION_SM };
static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB };
// Timestamp KB FU TSEC PK11 SECMON Warmboot
// Timestamp MK FU TSEC PK11 SECMON Warmboot
static const pkg1_id_t _pkg1_ids[] = {
{ "20161121", 0, 1, 0x1900, 0x3FE0, SM_100_ADR, 0x8000D000, _secmon_1_patchset }, // 1.0.0 (Patched relocator).
{ "20170210", 0, 2, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_2_patchset }, // 2.0.0 - 2.3.0.
@@ -280,9 +280,9 @@ void pkg1_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01)
else if (t210b01)
{
// For T210B01 we patch 6.X.X as is. Otherwise we decompress the program payload.
if (ctxt->pkg1_id->kb == HOS_KB_VERSION_600)
if (ctxt->pkg1_id->mkey == HOS_MKEY_VER_600)
secmon_patchset = _secmon_6_mariko_patchset;
else if (ctxt->pkg1_id->kb == HOS_KB_VERSION_620)
else if (ctxt->pkg1_id->mkey == HOS_MKEY_VER_620)
secmon_patchset = _secmon_620_mariko_patchset;
else
{
@@ -291,9 +291,9 @@ void pkg1_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01)
memset((void *)TZRAM_PROG_ADDR, 0, 0x38800);
// Get size of compressed program payload and set patch offset.
u32 idx = ctxt->pkg1_id->kb - HOS_KB_VERSION_700;
u32 idx = ctxt->pkg1_id->mkey - HOS_MKEY_VER_700;
u32 patch_offset = TZRAM_PROG_PK2_SIG_PATCH;
if (ctxt->pkg1_id->kb > HOS_KB_VERSION_910 || !memcmp(ctxt->pkg1_id->id, "20200303", 8)) //TODO: Add 11.0.0 support.
if (ctxt->pkg1_id->mkey >= HOS_MKEY_VER_1210 || !memcmp(ctxt->pkg1_id->id, "20200303", 8)) //TODO: Add 11.0.0 support.
{
idx++;
patch_offset = TZRAM_PROG_PK2_SIG_PATCH_1000;
@@ -323,7 +323,7 @@ void pkg1_warmboot_patch(void *hos_ctxt)
const patch_t *warmboot_patchset;
// Patch warmboot on T210 to allow downgrading.
switch (ctxt->pkg1_id->kb)
switch (ctxt->pkg1_id->mkey)
{
case 0:
warmboot_patchset = _warmboot_1_patchset;
@@ -352,7 +352,7 @@ static void _warmboot_filename(char *out, u32 fuses)
strcat(out, ".bin");
}
int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base, u32 fuses_fw, u8 kb)
int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base, u32 fuses_fw, u8 mkey)
{
launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt;
int res = 1;
@@ -420,15 +420,16 @@ int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base, u32 fuses_fw, u8 kb)
}
else
{
// Set warmboot address in PMC if required.
if (kb <= HOS_KB_VERSION_301)
// Set Warmboot address in PMC if required.
if (mkey <= HOS_MKEY_VER_301)
PMC(APBDEV_PMC_SCRATCH1) = warmboot_base;
// Set Warmboot Physical Address ID for 3.0.0 - 3.0.2.
if (kb == HOS_KB_VERSION_300)
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0xE3; // Warmboot 3.0.0 PA address id.
else if (kb == HOS_KB_VERSION_301)
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA address id.
// Set Warmboot Physical Address ID for 3.0.0 - 3.0.2. For 4.0.0 and up, secmon does it.
// The check is already patched so it's actually irrelevant.
if (mkey == HOS_MKEY_VER_300)
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0xE3; // Warmboot 3.0.0 PA ID.
else if (mkey == HOS_MKEY_VER_301)
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA ID.
}
return res;

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2022-2024 CTCaer
* Copyright (c) 2022-2025 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -29,7 +29,7 @@
#define PKG1_BOOTLOADER_SIZE SZ_256K
#define PKG1_BOOTLOADER_MAIN_OFFSET 0x100000
#define PKG1_BOOTLOADER_BACKUP_OFFSET 0x140000
#define PKG1_HOS_KEYBLOBS_OFFSET 0x180000
#define PKG1_HOS_EKS_OFFSET 0x180000
#define PKG1_ERISTA_ON_MARIKO_MAGIC 0xE59FD00C // For 4.0.0 Erista and up.
#define PKG1_MARIKO_ON_ERISTA_MAGIC 0x40010040 // Mariko pkg1 entrypoint.
@@ -59,6 +59,21 @@ typedef struct _bl_hdr_t210b01_t
/* 0x160 */ u8 rsvd[0x10];
} bl_hdr_t210b01_t;
typedef struct _eks_keys_t
{
u8 master_kekseed[SE_KEY_128_SIZE];
u8 random_data[0x70];
u8 package1_key[SE_KEY_128_SIZE];
} eks_keys_t;
typedef struct _pkg1_eks_t
{
u8 cmac[SE_KEY_128_SIZE];
u8 ctr[SE_AES_IV_SIZE];
eks_keys_t keys;
u8 padding[0x150];
} pkg1_eks_t;
typedef struct _pk1_hdr_t
{
/* 0x00 */ u32 si_sha256; // Secure Init.
@@ -73,7 +88,7 @@ typedef struct _pk1_hdr_t
typedef struct _pkg1_id_t
{
const char *id;
u16 kb;
u16 mkey;
u16 fuses;
u16 tsec_off;
u16 pkg11_off;
@@ -84,14 +99,14 @@ typedef struct _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;
/* 0x00 */ u32 magic;
/* 0x04 */ u32 wb_size;
/* 0x08 */ u32 wb_off;
/* 0x0C */ u32 pad;
/* 0x10 */ u32 ldr_size;
/* 0x14 */ u32 ldr_off;
/* 0x18 */ u32 sm_size;
/* 0x1C */ u32 sm_off;
} pk11_hdr_t;
const pkg1_id_t *pkg1_get_latest();
@@ -100,7 +115,7 @@ 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);
void pkg1_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01);
void pkg1_warmboot_patch(void *hos_ctxt);
int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base, u32 fuses_fw, u8 kb);
int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base, u32 fuses_fw, u8 mkey);
void pkg1_warmboot_rsa_mod(u32 warmboot_base);
#endif

View File

@@ -38,16 +38,6 @@ u32 pkg2_newkern_ini1_start;
u32 pkg2_newkern_ini1_end;
u32 pkg2_newkern_ini1_rela;
enum kip_offset_section
{
KIP_TEXT = 0,
KIP_RODATA = 1,
KIP_DATA = 2,
KIP_BSS = 3,
KIP_UNKSEC1 = 4,
KIP_UNKSEC2 = 5
};
#define KIP_PATCH_SECTION_SHIFT (29)
#define KIP_PATCH_SECTION_MASK (7 << KIP_PATCH_SECTION_SHIFT)
#define KIP_PATCH_OFFSET_MASK (~KIP_PATCH_SECTION_MASK)
@@ -697,7 +687,7 @@ static const u8 mkey_vector_7xx[SE_KEY_128_SIZE] =
{ 0xEA, 0x60, 0xB3, 0xEA, 0xCE, 0x8F, 0x24, 0x46, 0x7D, 0x33, 0x9C, 0xD1, 0xBC, 0x24, 0x98, 0x29 };
u8 pkg2_keyslot;
pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb, bool is_exo)
pkg2_hdr_t *pkg2_decrypt(void *data, u8 mkey, bool is_exo)
{
u8 *pdata = (u8 *)data;
@@ -713,7 +703,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb, bool is_exo)
pkg2_keyslot = 8;
// Decrypt 7.0.0 pkg2 via 8.1.0 mkey on Erista.
if (!h_cfg.t210b01 && kb == HOS_KB_VERSION_700)
if (!h_cfg.t210b01 && mkey == HOS_MKEY_VER_700)
{
u8 tmp_mkey[SE_KEY_128_SIZE];
@@ -802,7 +792,7 @@ void pkg2_build_encrypt(void *dst, void *hos_ctxt, link_t *kips_info, bool is_ex
launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt;
u32 meso_magic = *(u32 *)(ctxt->kernel + 4);
u32 kernel_size = ctxt->kernel_size;
u8 kb = ctxt->pkg1_id->kb;
u8 mkey = ctxt->pkg1_id->mkey;
u8 *pdst = (u8 *)dst;
// Force new Package2 if Mesosphere.
@@ -811,10 +801,10 @@ void pkg2_build_encrypt(void *dst, void *hos_ctxt, link_t *kips_info, bool is_ex
ctxt->new_pkg2 = true;
// Set key version. For Erista 7.0.0, use 8.1.0 because of a bug in Exo2?
u8 key_ver = kb ? kb + 1 : 0;
u8 key_ver = mkey ? mkey + 1 : 0;
if (pkg2_keyslot == 9)
{
key_ver = HOS_KB_VERSION_810 + 1;
key_ver = HOS_MKEY_VER_810 + 1;
pkg2_keyslot = 8;
}

View File

@@ -90,6 +90,18 @@ typedef struct _pkg2_ini1_t
u32 pad;
} pkg2_ini1_t;
enum kip_offset_section
{
KIP_TEXT = 0,
KIP_RODATA = 1,
KIP_DATA = 2,
KIP_BSS = 3,
KIP_UNKSEC1 = 4,
KIP_UNKSEC2 = 5
};
#define KIP1_NUM_SECTIONS 6
typedef struct _pkg2_kip1_sec_t
{
u32 offset;
@@ -98,12 +110,10 @@ typedef struct _pkg2_kip1_sec_t
u32 attrib;
} pkg2_kip1_sec_t;
#define KIP1_NUM_SECTIONS 6
typedef struct _pkg2_kip1_t
{
/* 0x000 */ u32 magic;
/* 0x004 */ u8 name[12];
/* 0x004 */ char name[12];
/* 0x010 */ u64 tid;
/* 0x018 */ u32 proc_cat;
/* 0x01C */ u8 main_thrd_prio;
@@ -160,7 +170,7 @@ void pkg2_get_ids(kip1_id_t **ids, u32 *entries);
const char *pkg2_patch_kips(link_t *info, char *patch_names);
const pkg2_kernel_id_t *pkg2_identify(const u8 *hash);
pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb, bool is_exo);
pkg2_hdr_t *pkg2_decrypt(void *data, u8 mkey, bool is_exo);
void pkg2_build_encrypt(void *dst, void *hos_ctxt, link_t *kips_info, bool is_exo);
#endif

View File

@@ -133,7 +133,7 @@ int parse_pkg3(launch_ctxt_t *ctxt, const char *path)
bool experimental = false;
// Skip if stock and Exosphere and warmboot are not needed.
bool pkg1_old = ctxt->pkg1_id->kb <= HOS_KB_VERSION_620; // Should check if t210b01?
bool pkg1_old = ctxt->pkg1_id->mkey <= HOS_MKEY_VER_620; // Should check if t210b01?
bool emummc_disabled = !emu_cfg.enabled || h_cfg.emummc_force_disable;
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
@@ -155,8 +155,8 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
//! TODO: Replace current HOS version decoding (as it's bound to break in the future).
// Old exosphere target versioning.
if (ctxt->pkg1_id->kb >= HOS_KB_VERSION_1210) // 12.1.0+
exo_fw_no = ctxt->pkg1_id->kb + 4;
if (ctxt->pkg1_id->mkey >= HOS_MKEY_VER_1210) // 12.1.0+
exo_fw_no = ctxt->pkg1_id->mkey + 4;
else if (ctxt->pkg1_id->fuses <= 3 || ctxt->pkg1_id->fuses >= 10) // 1.0.0 - 3.0.0, 8.1.0 - 12.0.3.
exo_fw_no = ctxt->pkg1_id->fuses;
else
@@ -169,7 +169,7 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
exo_fw_no++;
// Set 12.1.0 specific revision.
if (ctxt->pkg1_id->kb == HOS_KB_VERSION_1210)
if (ctxt->pkg1_id->mkey == HOS_MKEY_VER_1210)
ctxt->exo_ctx.hos_revision = 1;
// Feed old exosphere target versioning to new.

View File

@@ -33,7 +33,6 @@
#define OUT_FILENAME_SZ 128
#define NUM_SECTORS_PER_ITER 8192 // 4MB Cache.
extern hekate_config h_cfg;
extern volatile boot_cfg_t *b_cfg;
void load_emummc_cfg(emummc_cfg_t *emu_info)

View File

@@ -1142,7 +1142,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
char path[128];
u8 kb = 0;
u8 mkey = 0;
u8 *pkg1 = (u8 *)zalloc(SZ_256K);
u8 *warmboot = (u8 *)zalloc(SZ_256K);
u8 *secmon = (u8 *)zalloc(SZ_256K);
@@ -1163,7 +1163,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
// Read package1.
static const u32 BOOTLOADER_SIZE = SZ_256K;
static const u32 BOOTLOADER_MAIN_OFFSET = 0x100000;
static const u32 HOS_KEYBLOBS_OFFSET = 0x180000;
static const u32 HOS_EKS_OFFSET = 0x180000;
char *build_date = malloc(32);
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header.
@@ -1197,22 +1197,25 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
goto out_free;
}
kb = pkg1_id->kb;
mkey = pkg1_id->mkey;
tsec_ctxt_t tsec_ctxt = {0};
tsec_ctxt.fw = (void *)(pkg1 + pkg1_id->tsec_off);
tsec_ctxt.pkg1 = (void *)pkg1;
tsec_ctxt.pkg11_off = pkg1_id->pkg11_off;
// Read keyblob.
u8 *keyblob = (u8 *)zalloc(EMMC_BLOCKSIZE);
sdmmc_storage_read(&emmc_storage, HOS_KEYBLOBS_OFFSET / EMMC_BLOCKSIZE + kb, 1, keyblob);
// Read the correct eks for older HOS versions.
const u32 eks_size = sizeof(pkg1_eks_t);
pkg1_eks_t *eks = (pkg1_eks_t *)malloc(eks_size);
emmc_set_partition(EMMC_BOOT0);
sdmmc_storage_read(&emmc_storage, HOS_EKS_OFFSET + (mkey * eks_size) / EMMC_BLOCKSIZE,
eks_size / EMMC_BLOCKSIZE, eks);
// Decrypt.
hos_keygen(keyblob, kb, &tsec_ctxt);
free(keyblob);
// Generate keys.
hos_keygen(eks, mkey, &tsec_ctxt);
free(eks);
if (h_cfg.t210b01 || kb <= HOS_KB_VERSION_600)
if (h_cfg.t210b01 || mkey <= HOS_MKEY_VER_600)
{
if (!pkg1_decrypt(pkg1_id, pkg1))
{
@@ -1224,7 +1227,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
}
}
if (h_cfg.t210b01 || kb <= HOS_KB_VERSION_620)
if (h_cfg.t210b01 || mkey <= HOS_MKEY_VER_620)
{
pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1 + pk1_offset);
pk11_hdr_t *hdr_pk11 = (pk11_hdr_t *)(pkg1 + pk1_offset + pkg1_id->pkg11_off + 0x20);
@@ -1312,7 +1315,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
res = sd_save_to_file(pkg2, pkg2_size, path);
// Decrypt package2 and parse KIP1 blobs in INI1 section.
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, kb);
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, mkey);
if (!pkg2_hdr)
{
strcat(txt_buf, "#FFDD00 Pkg2 decryption failed!#");
@@ -1327,7 +1330,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
}
// Clear EKS slot, in case something went wrong with tsec keygen.
hos_eks_clear(kb);
hos_eks_clear(mkey);
goto out;
}
@@ -1428,7 +1431,7 @@ out_free:
emmc_end();
sd_unmount();
if (kb >= HOS_KB_VERSION_620)
if (mkey >= HOS_MKEY_VER_620)
se_aes_key_clear(8);
out_end:
// Enable buttons.

View File

@@ -28,29 +28,7 @@
u8 *cal0_buf = NULL;
static u8 *bis_keys = NULL;
typedef struct _tsec_keys_t
{
u8 tsec[SE_KEY_128_SIZE];
u8 tsec_root[SE_KEY_128_SIZE];
u8 tmp[SE_KEY_128_SIZE];
} tsec_keys_t;
typedef struct _kb_keys_t
{
u8 master_kekseed[SE_KEY_128_SIZE];
u8 random_data[0x70];
u8 package1_key[SE_KEY_128_SIZE];
} kb_keys_t;
typedef struct _kb_t
{
u8 cmac[SE_KEY_128_SIZE];
u8 ctr[SE_AES_IV_SIZE];
kb_keys_t keys;
u8 padding[0x150];
} kb_t;
static const u8 keyblob_keyseeds[HOS_KB_VERSION_600 - HOS_KB_VERSION_100 + 1][SE_KEY_128_SIZE] = {
static const u8 eks_keyseeds[HOS_MKEY_VER_600 - HOS_MKEY_VER_100 + 1][SE_KEY_128_SIZE] = {
{ 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 }, // 1.0.0.
{ 0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC }, // 3.0.0.
{ 0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B }, // 3.0.1.
@@ -77,7 +55,7 @@ static const u8 master_kekseed_t210_max[SE_KEY_128_SIZE] =
{ 0xA1, 0x7D, 0x34, 0xDB, 0x2D, 0x9D, 0xDA, 0xE5, 0xF8, 0x15, 0x63, 0x4C, 0x8F, 0xE7, 0x6C, 0xD8 }; // 20.0.0.
//!TODO: Update on mkey changes.
static const u8 master_kekseed_t210b01[HOS_KB_VERSION_MAX - HOS_KB_VERSION_600 + 1][SE_KEY_128_SIZE] = {
static const u8 master_kekseed_t210b01[HOS_MKEY_VER_MAX - HOS_MKEY_VER_600 + 1][SE_KEY_128_SIZE] = {
{ 0x77, 0x60, 0x5A, 0xD2, 0xEE, 0x6E, 0xF8, 0x3C, 0x3F, 0x72, 0xE2, 0x59, 0x9D, 0xAC, 0x5E, 0x56 }, // 6.0.0.
{ 0x1E, 0x80, 0xB8, 0x17, 0x3E, 0xC0, 0x60, 0xAA, 0x11, 0xBE, 0x1A, 0x4A, 0xA6, 0x6F, 0xE4, 0xAE }, // 6.2.0.
{ 0x94, 0x08, 0x67, 0xBD, 0x0A, 0x00, 0x38, 0x84, 0x11, 0xD3, 0x1A, 0xDB, 0xDD, 0x8D, 0xF1, 0x8A }, // 7.0.0.
@@ -105,7 +83,7 @@ const u8 package2_keyseed[SE_KEY_128_SIZE] =
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
//!TODO: Update on mkey changes.
static const u8 mkey_vectors[HOS_KB_VERSION_MAX + 1][SE_KEY_128_SIZE] = {
static const u8 mkey_vectors[HOS_MKEY_VER_MAX + 1][SE_KEY_128_SIZE] = {
{ 0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D }, // Zeroes encrypted with mkey 00.
{ 0x29, 0x4C, 0x04, 0xC8, 0xEB, 0x10, 0xED, 0x9D, 0x51, 0x64, 0x97, 0xFB, 0xF3, 0x4D, 0x50, 0xDD }, // Mkey 00 encrypted with mkey 01.
{ 0xDE, 0xCF, 0xEB, 0xEB, 0x10, 0xAE, 0x74, 0xD8, 0xAD, 0x7C, 0xF4, 0x9E, 0x62, 0xE0, 0xE8, 0x72 }, // Mkey 01 encrypted with mkey 02.
@@ -129,7 +107,7 @@ static const u8 mkey_vectors[HOS_KB_VERSION_MAX + 1][SE_KEY_128_SIZE] = {
};
//!TODO: Update on mkey changes.
static const u8 new_console_keyseed[HOS_KB_VERSION_MAX - HOS_KB_VERSION_400 + 1][SE_KEY_128_SIZE] = {
static const u8 new_console_keyseed[HOS_MKEY_VER_MAX - HOS_MKEY_VER_400 + 1][SE_KEY_128_SIZE] = {
{ 0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D }, // 4.x New Device Key Source.
{ 0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C }, // 5.x New Device Key Source.
{ 0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4 }, // 6.x New Device Key Source.
@@ -150,7 +128,7 @@ static const u8 new_console_keyseed[HOS_KB_VERSION_MAX - HOS_KB_VERSION_400 + 1]
};
//!TODO: Update on mkey changes.
static const u8 new_console_kekseed[HOS_KB_VERSION_MAX - HOS_KB_VERSION_400 + 1][SE_KEY_128_SIZE] = {
static const u8 new_console_kekseed[HOS_MKEY_VER_MAX - HOS_MKEY_VER_400 + 1][SE_KEY_128_SIZE] = {
{ 0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D }, // 4.x New Device Keygen Source.
{ 0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E }, // 5.x New Device Keygen Source.
{ 0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF }, // 6.x New Device Keygen Source.
@@ -300,13 +278,13 @@ out:
}
}
void hos_eks_clear(u32 kb)
void hos_eks_clear(u32 mkey)
{
// Check if Erista based unit.
if (h_cfg.t210b01)
return;
if (h_cfg.eks && kb >= HOS_KB_VERSION_700)
if (h_cfg.eks && mkey >= HOS_MKEY_VER_700)
{
// Check if current Master key is enabled.
if (h_cfg.eks->enabled)
@@ -335,14 +313,20 @@ out:
}
}
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
typedef struct _tsec_keys_t
{
u8 tsec[SE_KEY_128_SIZE];
u8 tsec_root[SE_KEY_128_SIZE];
u8 tmp[SE_KEY_128_SIZE];
} tsec_keys_t;
int hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt)
{
u32 retries = 0;
bool use_tsec = false;
tsec_keys_t tsec_keys;
kb_t *kb_data = (kb_t *)keyblob;
if (kb > HOS_KB_VERSION_MAX)
if (mkey > HOS_MKEY_VER_MAX)
return 0;
// Do Mariko keygen.
@@ -352,7 +336,7 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
se_aes_unwrap_key(10, 14, console_keyseed_4xx);
// Derive master key.
se_aes_unwrap_key(7, 12, master_kekseed_t210b01[kb - HOS_KB_VERSION_600]);
se_aes_unwrap_key(7, 12, master_kekseed_t210b01[mkey - HOS_MKEY_VER_600]);
se_aes_unwrap_key(7, 7, master_keyseed_retail);
// Derive latest pkg2 key.
@@ -367,15 +351,15 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
_hos_eks_get();
// Use tsec keygen for old firmware or if EKS keys does not exist for newer.
if (kb <= HOS_KB_VERSION_620 || !h_cfg.eks || (h_cfg.eks->enabled != HOS_EKS_TSEC_VER))
if (mkey <= HOS_MKEY_VER_620 || !h_cfg.eks || (h_cfg.eks->enabled != HOS_EKS_TSEC_VER))
use_tsec = true;
if (kb <= HOS_KB_VERSION_600)
if (mkey <= HOS_MKEY_VER_600)
{
tsec_ctxt->size = 0xF00;
tsec_ctxt->type = TSEC_FW_TYPE_OLD;
}
else if (kb == HOS_KB_VERSION_620)
else if (mkey == HOS_MKEY_VER_620)
{
tsec_ctxt->size = 0x2900;
tsec_ctxt->type = TSEC_FW_TYPE_EMU;
@@ -425,7 +409,7 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
}
}
if (kb >= HOS_KB_VERSION_700)
if (mkey >= HOS_MKEY_VER_700)
{
// For 7.0.0 and up, save EKS slot if it doesn't exist.
if (use_tsec)
@@ -434,8 +418,8 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
free(tsec_ctxt->fw);
}
// Decrypt keyblob and set keyslots.
se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, keyblob_keyseeds[0]);
// Decrypt eks and set keyslots.
se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tmp);
// Derive device keys.
@@ -451,15 +435,15 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
// Package2 key.
se_aes_unwrap_key(8, 7, package2_keyseed);
}
else if (kb == HOS_KB_VERSION_620)
else if (mkey == HOS_MKEY_VER_620)
{
// Set TSEC key.
se_aes_key_set(12, tsec_keys.tsec, SE_KEY_128_SIZE);
// Set TSEC root key.
se_aes_key_set(13, tsec_keys.tsec_root, SE_KEY_128_SIZE);
// Decrypt keyblob and set keyslots.
se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, keyblob_keyseeds[0]);
// Decrypt eks and set keyslots.
se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tmp);
// Derive device keys.
@@ -480,48 +464,48 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
// Set TSEC key.
se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE);
// Derive keyblob keys from TSEC+SBK.
se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, keyblob_keyseeds[0]);
// Derive eks keys from TSEC+SBK.
se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tsec);
se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, keyblob_keyseeds[kb]);
se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[mkey]);
se_aes_unwrap_key(13, 14, tsec_keys.tsec);
/*
// Verify keyblob CMAC.
// Verify eks CMAC.
u8 cmac[SE_KEY_128_SIZE];
se_aes_unwrap_key(11, 13, cmac_keyseed);
se_aes_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)kb_data->ctr, sizeof(kb_data->ctr) + sizeof(kb_data->keys));
if (!memcmp(kb_data->cmac, cmac, SE_KEY_128_SIZE))
se_aes_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)eks->ctr, sizeof(eks->ctr) + sizeof(eks->keys));
if (!memcmp(eks->cmac, cmac, SE_KEY_128_SIZE))
return 0;
*/
se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, cmac_keyseed);
se_aes_unwrap_key(11, 13, cmac_keyseed);
// Decrypt keyblob and set keyslots.
se_aes_crypt_ctr(13, &kb_data->keys, sizeof(kb_keys_t), &kb_data->keys, sizeof(kb_keys_t), kb_data->ctr);
se_aes_key_set(11, kb_data->keys.package1_key, SE_KEY_128_SIZE);
se_aes_key_set(12, kb_data->keys.master_kekseed, SE_KEY_128_SIZE);
se_aes_key_set(13, kb_data->keys.master_kekseed, SE_KEY_128_SIZE);
// Decrypt eks and set keyslots.
se_aes_crypt_ctr(13, &eks->keys, sizeof(eks_keys_t), &eks->keys, sizeof(eks_keys_t), eks->ctr);
se_aes_key_set(11, eks->keys.package1_key, SE_KEY_128_SIZE);
se_aes_key_set(12, eks->keys.master_kekseed, SE_KEY_128_SIZE);
se_aes_key_set(13, eks->keys.master_kekseed, SE_KEY_128_SIZE);
se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tsec, master_keyseed_retail);
switch (kb)
switch (mkey)
{
case HOS_KB_VERSION_100:
case HOS_KB_VERSION_300:
case HOS_KB_VERSION_301:
case HOS_MKEY_VER_100:
case HOS_MKEY_VER_300:
case HOS_MKEY_VER_301:
se_aes_unwrap_key(13, 15, console_keyseed);
se_aes_unwrap_key(12, 12, master_keyseed_retail);
break;
case HOS_KB_VERSION_400:
case HOS_MKEY_VER_400:
se_aes_unwrap_key(13, 15, console_keyseed_4xx);
se_aes_unwrap_key(15, 15, console_keyseed);
//se_aes_unwrap_key(14, 12, master_keyseed_4xx); // In this context it's useless. So don't kill SBK.
se_aes_unwrap_key(12, 12, master_keyseed_retail);
break;
case HOS_KB_VERSION_500:
case HOS_KB_VERSION_600:
case HOS_MKEY_VER_500:
case HOS_MKEY_VER_600:
se_aes_unwrap_key(10, 15, console_keyseed_4xx);
se_aes_unwrap_key(15, 15, console_keyseed);
//se_aes_unwrap_key(14, 12, master_keyseed_4xx); // In this context it's useless. So don't kill SBK.
@@ -559,7 +543,7 @@ static void _hos_validate_mkey()
} while (mkey_idx - 1);
se_aes_key_clear(2);
hos_eks_clear(HOS_KB_VERSION_MAX);
hos_eks_clear(HOS_MKEY_VER_MAX);
}
static void _hos_bis_print_key(u32 idx, u8 *key)
@@ -578,14 +562,14 @@ static void _hos_bis_print_key(u32 idx, u8 *key)
int hos_bis_keygen()
{
u32 keygen_rev = 0;
u32 console_key_slot = 15; // HOS_KB_VERSION_MAX. Only for Erista.
u32 console_key_slot = 15; // HOS_MKEY_VER_MAX. Only for Erista.
tsec_ctxt_t tsec_ctxt = {0};
if (!bis_keys)
bis_keys = malloc(SE_KEY_128_SIZE * 6);
// Run initial keygen.
hos_keygen(NULL, HOS_KB_VERSION_MAX, &tsec_ctxt);
hos_keygen(NULL, HOS_MKEY_VER_MAX, &tsec_ctxt);
// All Mariko use new device keygen. New keygen was introduced in 4.0.0.
// We check unconditionally in order to support downgrades.
@@ -599,7 +583,7 @@ int hos_bis_keygen()
u32 mkey_idx = sizeof(mkey_vectors) / SE_KEY_128_SIZE;
// Keygen revision uses bootloader version, which starts from 1.
keygen_rev -= (HOS_KB_VERSION_400 + 1);
keygen_rev -= (HOS_MKEY_VER_400 + 1);
// Derive mkey 0.
do
@@ -649,7 +633,7 @@ int hos_bis_keygen()
se_aes_crypt_block_ecb(2, DECRYPT, bis_keys + (4 * SE_KEY_128_SIZE), bis_keyseed[4]);
se_aes_crypt_block_ecb(2, DECRYPT, bis_keys + (5 * SE_KEY_128_SIZE), bis_keyseed[5]);
// Validate key because HOS_KB_VERSION_MAX.
// Validate key because HOS_MKEY_VER_MAX.
if (!h_cfg.t210b01)
_hos_validate_mkey();
@@ -718,13 +702,13 @@ int hos_dump_cal0()
cal0_buf = NULL;
// Clear EKS keys.
hos_eks_clear(HOS_KB_VERSION_MAX);
hos_eks_clear(HOS_MKEY_VER_MAX);
return 2;
}
u32 hash[8];
se_calc_sha256_oneshot(hash, (u8 *)cal0 + 0x40, cal0->body_size);
se_calc_sha256_oneshot(hash, (u8 *)&cal0->cfg_id1, cal0->body_size);
if (memcmp(hash, cal0->body_sha256, 0x20))
return 3;

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2025 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -27,34 +27,34 @@
//!TODO: Update on mkey changes.
enum {
HOS_KB_VERSION_100 = 0,
HOS_KB_VERSION_300 = 1,
HOS_KB_VERSION_301 = 2,
HOS_KB_VERSION_400 = 3,
HOS_KB_VERSION_500 = 4,
HOS_KB_VERSION_600 = 5,
HOS_KB_VERSION_620 = 6,
HOS_KB_VERSION_700 = 7,
HOS_KB_VERSION_810 = 8,
HOS_KB_VERSION_900 = 9,
HOS_KB_VERSION_910 = 10,
HOS_KB_VERSION_1210 = 11,
HOS_KB_VERSION_1300 = 12,
HOS_KB_VERSION_1400 = 13,
HOS_KB_VERSION_1500 = 14,
HOS_KB_VERSION_1600 = 15,
HOS_KB_VERSION_1700 = 16,
HOS_KB_VERSION_1800 = 17,
HOS_KB_VERSION_1900 = 18,
HOS_KB_VERSION_2000 = 19,
HOS_KB_VERSION_MAX = HOS_KB_VERSION_2000
HOS_MKEY_VER_100 = 0,
HOS_MKEY_VER_300 = 1,
HOS_MKEY_VER_301 = 2,
HOS_MKEY_VER_400 = 3,
HOS_MKEY_VER_500 = 4,
HOS_MKEY_VER_600 = 5,
HOS_MKEY_VER_620 = 6,
HOS_MKEY_VER_700 = 7,
HOS_MKEY_VER_810 = 8,
HOS_MKEY_VER_900 = 9,
HOS_MKEY_VER_910 = 10,
HOS_MKEY_VER_1210 = 11,
HOS_MKEY_VER_1300 = 12,
HOS_MKEY_VER_1400 = 13,
HOS_MKEY_VER_1500 = 14,
HOS_MKEY_VER_1600 = 15,
HOS_MKEY_VER_1700 = 16,
HOS_MKEY_VER_1800 = 17,
HOS_MKEY_VER_1900 = 18,
HOS_MKEY_VER_2000 = 19,
HOS_MKEY_VER_MAX = HOS_MKEY_VER_2000
};
#define HOS_TSEC_VERSION 4 //! TODO: Update on TSEC Root Key changes.
#define HOS_PKG11_MAGIC 0x31314B50
#define HOS_EKS_MAGIC 0x31534B45 // EKS1.
#define HOS_EKS_TSEC_VER (HOS_KB_VERSION_700 + HOS_TSEC_VERSION)
#define HOS_EKS_TSEC_VER (HOS_MKEY_VER_700 + HOS_TSEC_VERSION)
typedef struct _hos_eks_mbr_t
{
@@ -71,8 +71,6 @@ static_assert(sizeof(hos_eks_mbr_t) == 64, "HOS EKS size is wrong!");
typedef struct _launch_ctxt_t
{
void *keyblob;
void *pkg1;
const pkg1_id_t *pkg1_id;
@@ -85,18 +83,19 @@ typedef struct _launch_ctxt_t
u32 pkg2_size;
bool new_pkg2;
void *kernel;
u32 kernel_size;
void *kernel;
u32 kernel_size;
link_t kip1_list;
char* kip1_patches;
char *kip1_patches;
ini_sec_t *cfg;
} launch_ctxt_t;
extern u8 *cal0_buf;
void hos_eks_clear(u32 kb);
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt);
void hos_eks_clear(u32 mkey);
int hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt);
int hos_bis_keygen();
void hos_bis_keys_clear();
int hos_dump_cal0();

View File

@@ -37,7 +37,7 @@ static const u8 sec_map_100[3] = { PK11_SECTION_SM, PK11_SECTION_LD, PK11_SECTIO
static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTION_SM };
static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB };
// Timestamp KB TSEC PK11 SECMON Warmboot
// Timestamp MK TSEC PK11 SECMON Warmboot
static const pkg1_id_t _pkg1_ids[] = {
{ "20161121", 0, 0x1900, 0x3FE0, 0x40014020, 0x8000D000 }, // 1.0.0.
{ "20170210", 0, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000 }, // 2.0.0 - 2.3.0.
@@ -121,9 +121,9 @@ const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t
u32 sec_size[3] = { hdr->wb_size, hdr->ldr_size, hdr->sm_size };
// Get correct header mapping.
if (id->kb == HOS_KB_VERSION_100 && !memcmp(id->id, "20161121", 8))
if (id->mkey == HOS_MKEY_VER_100 && !memcmp(id->id, "20161121", 8))
sec_map = sec_map_100;
else if (id->kb <= HOS_KB_VERSION_301)
else if (id->mkey <= HOS_MKEY_VER_301)
sec_map = sec_map_2xx;
else
sec_map = sec_map_4xx;

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2022-2023 CTCaer
* Copyright (c) 2022-2025 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -39,6 +39,21 @@ typedef struct _bl_hdr_t210b01_t
/* 0x160 */ u8 rsvd[0x10];
} bl_hdr_t210b01_t;
typedef struct _eks_keys_t
{
u8 master_kekseed[SE_KEY_128_SIZE];
u8 random_data[0x70];
u8 package1_key[SE_KEY_128_SIZE];
} eks_keys_t;
typedef struct _pkg1_eks_t
{
u8 cmac[SE_KEY_128_SIZE];
u8 ctr[SE_AES_IV_SIZE];
eks_keys_t keys;
u8 padding[0x150];
} pkg1_eks_t;
typedef struct _pk1_hdr_t
{
/* 0x00 */ u32 si_sha256; // Secure Init.
@@ -53,8 +68,8 @@ typedef struct _pk1_hdr_t
typedef struct _pkg1_id_t
{
const char *id;
u32 kb;
u32 tsec_off;
u16 mkey;
u16 tsec_off;
u32 pkg11_off;
u32 secmon_base;
u32 warmboot_base;
@@ -62,14 +77,14 @@ typedef struct _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;
/* 0x00 */ u32 magic;
/* 0x04 */ u32 wb_size;
/* 0x08 */ u32 wb_off;
/* 0x0C */ u32 pad;
/* 0x10 */ u32 ldr_size;
/* 0x14 */ u32 ldr_off;
/* 0x18 */ u32 sm_size;
/* 0x1C */ u32 sm_off;
} pk11_hdr_t;
const pkg1_id_t *pkg1_identify(u8 *pkg1, char *build_date);

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2025 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -90,7 +90,7 @@ void pkg2_get_newkern_info(u8 *kern_data)
}
//!TODO: Update on mkey changes.
static const u8 mkey_vector_7xx[HOS_KB_VERSION_MAX - HOS_KB_VERSION_810 + 1][SE_KEY_128_SIZE] =
static const u8 mkey_vector_7xx[HOS_MKEY_VER_MAX - HOS_MKEY_VER_810 + 1][SE_KEY_128_SIZE] =
{
// Master key 7 encrypted with 8. (7.0.0 with 8.1.0)
{ 0xEA, 0x60, 0xB3, 0xEA, 0xCE, 0x8F, 0x24, 0x46, 0x7D, 0x33, 0x9C, 0xD1, 0xBC, 0x24, 0x98, 0x29 },
@@ -133,7 +133,7 @@ static bool _pkg2_key_unwrap_validate(pkg2_hdr_t *tmp_test, pkg2_hdr_t *hdr, u8
return (tmp_test->magic == PKG2_MAGIC);
}
pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
pkg2_hdr_t *pkg2_decrypt(void *data, u8 mkey)
{
pkg2_hdr_t mkey_test;
u8 *pdata = (u8 *)data;
@@ -154,13 +154,13 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
goto key_found;
// Decrypt older pkg2 via new mkeys.
if ((kb >= HOS_KB_VERSION_700) && (kb < HOS_KB_VERSION_MAX))
if ((mkey >= HOS_MKEY_VER_700) && (mkey < HOS_MKEY_VER_MAX))
{
u8 tmp_mkey[SE_KEY_128_SIZE];
u8 decr_slot = 7; // THK mkey or T210B01 mkey.
u8 mkey_seeds_cnt = sizeof(mkey_vector_7xx) / SE_KEY_128_SIZE;
u8 mkey_seeds_idx = mkey_seeds_cnt; // Real index + 1.
u8 mkey_seeds_min_idx = mkey_seeds_cnt - (HOS_KB_VERSION_MAX - kb);
u8 mkey_seeds_min_idx = mkey_seeds_cnt - (HOS_MKEY_VER_MAX - mkey);
while (mkey_seeds_cnt)
{
@@ -196,11 +196,11 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
key_found:
// Decrypt header.
se_aes_crypt_ctr(pkg2_keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
//gfx_hexdump((u32)hdr, hdr, 0x100);
if (hdr->magic != PKG2_MAGIC)
return NULL;
// Decrypt sections.
for (u32 i = 0; i < 4; i++)
{
DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
@@ -208,7 +208,6 @@ DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
continue;
se_aes_crypt_ctr(pkg2_keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * SE_AES_IV_SIZE]);
//gfx_hexdump((u32)pdata, pdata, 0x100);
pdata += hdr->sec_size[i];
}

View File

@@ -38,18 +38,18 @@ extern u32 pkg2_newkern_ini1_end;
typedef struct _pkg2_hdr_t
{
u8 ctr[0x10];
u8 sec_ctr[0x40];
u32 magic;
u32 base;
u32 pad0;
u8 pkg2_ver;
u8 bl_ver;
u16 pad1;
u32 sec_size[4];
u32 sec_off[4];
u8 sec_sha256[0x80];
u8 data[];
/* 0x000 */ u8 ctr[0x10];
/* 0x010 */ u8 sec_ctr[0x40];
/* 0x050 */ u32 magic;
/* 0x054 */ u32 base;
/* 0x058 */ u32 pad0;
/* 0x05C */ u8 pkg2_ver;
/* 0x05D */ u8 bl_ver;
/* 0x05E */ u16 pad1;
/* 0x060 */ u32 sec_size[4];
/* 0x070 */ u32 sec_off[4];
/* 0x080 */ u8 sec_sha256[0x80];
/* 0x100 */ u8 data[];
} pkg2_hdr_t;
typedef struct _pkg2_ini1_t
@@ -60,6 +60,18 @@ typedef struct _pkg2_ini1_t
u32 pad;
} pkg2_ini1_t;
enum kip_offset_section
{
KIP_TEXT = 0,
KIP_RODATA = 1,
KIP_DATA = 2,
KIP_BSS = 3,
KIP_UNKSEC1 = 4,
KIP_UNKSEC2 = 5
};
#define KIP1_NUM_SECTIONS 6
typedef struct _pkg2_kip1_sec_t
{
u32 offset;
@@ -68,21 +80,19 @@ typedef struct _pkg2_kip1_sec_t
u32 attrib;
} pkg2_kip1_sec_t;
#define KIP1_NUM_SECTIONS 6
typedef struct _pkg2_kip1_t
{
u32 magic;
u8 name[12];
u64 tid;
u32 proc_cat;
u8 main_thrd_prio;
u8 def_cpu_core;
u8 res;
u8 flags;
pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS];
u32 caps[0x20];
u8 data[];
/* 0x000 */ u32 magic;
/* 0x004 */ char name[12];
/* 0x010 */ u64 tid;
/* 0x018 */ u32 proc_cat;
/* 0x01C */ u8 main_thrd_prio;
/* 0x01D */ u8 def_cpu_core;
/* 0x01E */ u8 res;
/* 0x01F */ u8 flags;
/* 0x020 */ pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS];
/* 0x080 */ u32 caps[0x20];
/* 0x100 */ u8 data[];
} pkg2_kip1_t;
typedef struct _pkg2_kip1_info_t
@@ -95,6 +105,6 @@ typedef struct _pkg2_kip1_info_t
void pkg2_get_newkern_info(u8 *kern_data);
u32 pkg2_calc_kip1_size(pkg2_kip1_t *kip1);
pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb);
pkg2_hdr_t *pkg2_decrypt(void *data, u8 mkey);
#endif