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:
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user