hekate/Nyx: remove Sept completely
- remove any reference to sept and parsing of it - completely refactor and simplify keygen - use new Atmo tsec keygen for 7.0.0 and up - simplify all info/tools that depend on hos keygen and bis keys
This commit is contained in:
@@ -22,7 +22,6 @@
|
||||
|
||||
#include "hos.h"
|
||||
#include "hos_config.h"
|
||||
#include "sept.h"
|
||||
#include "secmon_exo.h"
|
||||
#include "../config.h"
|
||||
#include <display/di.h>
|
||||
@@ -84,7 +83,7 @@ typedef struct _tsec_keys_t
|
||||
|
||||
typedef struct _kb_keys_t
|
||||
{
|
||||
u8 master_keyseed[SE_KEY_128_SIZE];
|
||||
u8 master_kekseed[SE_KEY_128_SIZE];
|
||||
u8 random_data[0x70];
|
||||
u8 package1_key[SE_KEY_128_SIZE];
|
||||
} kb_keys_t;
|
||||
@@ -112,12 +111,17 @@ static const u8 cmac_keyseed[SE_KEY_128_SIZE] =
|
||||
static const u8 master_keyseed_retail[SE_KEY_128_SIZE] =
|
||||
{ 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C };
|
||||
|
||||
static const u8 master_keyseed_4xx_5xx_610[SE_KEY_128_SIZE] =
|
||||
static const u8 master_keyseed_4xx[SE_KEY_128_SIZE] =
|
||||
{ 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 };
|
||||
|
||||
static const u8 master_keyseed_620[SE_KEY_128_SIZE] =
|
||||
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 mkey changes.
|
||||
static const u8 master_kekseed_t210_max[SE_KEY_128_SIZE] =
|
||||
{ 0x84, 0x67, 0xB6, 0x7F, 0x13, 0x11, 0xAE, 0xE6, 0x58, 0x9B, 0x19, 0xAF, 0x13, 0x6C, 0x80, 0x7A }; // 12.1.0.
|
||||
|
||||
//!TODO: Update on mkey changes.
|
||||
static const u8 master_kekseed_t210b01[][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.
|
||||
@@ -131,7 +135,7 @@ static const u8 master_kekseed_t210b01[][SE_KEY_128_SIZE] = {
|
||||
static const u8 console_keyseed[SE_KEY_128_SIZE] =
|
||||
{ 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 };
|
||||
|
||||
static const u8 console_keyseed_4xx_5xx[SE_KEY_128_SIZE] =
|
||||
static const u8 console_keyseed_4xx[SE_KEY_128_SIZE] =
|
||||
{ 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
|
||||
|
||||
const u8 package2_keyseed[SE_KEY_128_SIZE] =
|
||||
@@ -214,7 +218,7 @@ bool hos_eks_rw_try(u8 *buf, bool write)
|
||||
return false;
|
||||
}
|
||||
|
||||
void hos_eks_get()
|
||||
static void _hos_eks_get()
|
||||
{
|
||||
// Check if Erista based unit.
|
||||
if (h_cfg.t210b01)
|
||||
@@ -230,11 +234,10 @@ void hos_eks_get()
|
||||
|
||||
// Decrypt EKS blob.
|
||||
hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x80);
|
||||
se_aes_crypt_ecb(14, 0, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
|
||||
se_aes_crypt_ecb(14, DECRYPT, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
|
||||
|
||||
// Check if valid and for this unit.
|
||||
if (eks->magic == HOS_EKS_MAGIC &&
|
||||
(eks->lot0 == FUSE(FUSE_OPT_LOT_CODE_0) || eks->lot0 == FUSE(FUSE_PRIVATE_KEY0)))
|
||||
if (eks->magic == HOS_EKS_MAGIC && eks->lot0 == FUSE(FUSE_OPT_LOT_CODE_0))
|
||||
{
|
||||
h_cfg.eks = eks;
|
||||
return;
|
||||
@@ -245,82 +248,63 @@ out:
|
||||
}
|
||||
}
|
||||
|
||||
void hos_eks_save(u32 kb)
|
||||
static void _hos_eks_save(u32 kb)
|
||||
{
|
||||
// Check if Erista based unit.
|
||||
if (h_cfg.t210b01)
|
||||
return;
|
||||
|
||||
if (kb >= KB_FIRMWARE_VERSION_700)
|
||||
// EKS save. Only for 7.0.0 and up.
|
||||
bool new_eks = false;
|
||||
if (!h_cfg.eks)
|
||||
{
|
||||
u32 key_idx = 0;
|
||||
if (kb >= KB_FIRMWARE_VERSION_810)
|
||||
key_idx = 1;
|
||||
h_cfg.eks = calloc(512 , 1);
|
||||
new_eks = true;
|
||||
}
|
||||
|
||||
bool new_eks = false;
|
||||
if (!h_cfg.eks)
|
||||
// If matching blob doesn't exist, create it.
|
||||
if (h_cfg.eks->enabled < kb)
|
||||
{
|
||||
// Read EKS blob.
|
||||
u8 *mbr = calloc(512 , 1);
|
||||
if (!hos_eks_rw_try(mbr, false))
|
||||
{
|
||||
h_cfg.eks = calloc(512 , 1);
|
||||
new_eks = true;
|
||||
if (new_eks)
|
||||
{
|
||||
free(h_cfg.eks);
|
||||
h_cfg.eks = NULL;
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
// If matching blob doesn't exist, create it.
|
||||
bool update_eks = key_idx ? (h_cfg.eks->enabled[key_idx] < kb) : !h_cfg.eks->enabled[0];
|
||||
// If old EKS version was found, update it.
|
||||
update_eks |= h_cfg.eks->lot0 != FUSE(FUSE_OPT_LOT_CODE_0);
|
||||
if (update_eks)
|
||||
{
|
||||
// Read EKS blob.
|
||||
u8 *mbr = calloc(512 , 1);
|
||||
if (!hos_eks_rw_try(mbr, false))
|
||||
{
|
||||
if (new_eks)
|
||||
{
|
||||
free(h_cfg.eks);
|
||||
h_cfg.eks = NULL;
|
||||
}
|
||||
// Get keys.
|
||||
u8 *keys = (u8 *)calloc(0x2000, 1);
|
||||
se_get_aes_keys(keys + 0x1000, keys, SE_KEY_128_SIZE);
|
||||
|
||||
goto out;
|
||||
}
|
||||
// Set magic and personalized info.
|
||||
h_cfg.eks->magic = HOS_EKS_MAGIC;
|
||||
h_cfg.eks->enabled = KB_FIRMWARE_VERSION_MAX;
|
||||
h_cfg.eks->lot0 = FUSE(FUSE_OPT_LOT_CODE_0);
|
||||
|
||||
// Get keys.
|
||||
u8 *keys = (u8 *)calloc(0x2000, 1);
|
||||
se_get_aes_keys(keys + 0x1000, keys, SE_KEY_128_SIZE);
|
||||
// Copy new keys.
|
||||
memcpy(h_cfg.eks->tsec, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(h_cfg.eks->troot, keys + 13 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(h_cfg.eks->troot_dev, keys + 11 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
|
||||
// Set magic and personalized info.
|
||||
h_cfg.eks->magic = HOS_EKS_MAGIC;
|
||||
h_cfg.eks->enabled[key_idx] = kb;
|
||||
h_cfg.eks->lot0 = FUSE(FUSE_OPT_LOT_CODE_0);
|
||||
// Encrypt EKS blob.
|
||||
u8 *eks = calloc(512 , 1);
|
||||
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
|
||||
se_aes_crypt_ecb(14, ENCRYPT, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
|
||||
|
||||
// Copy new keys.
|
||||
memcpy(h_cfg.eks->dkg, keys + 10 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(h_cfg.eks->dkk, keys + 15 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
// Write EKS blob to SD.
|
||||
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
|
||||
hos_eks_rw_try(mbr, true);
|
||||
|
||||
if (!h_cfg.aes_slots_new)
|
||||
{
|
||||
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
}
|
||||
else // New sept slots.
|
||||
{
|
||||
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 13 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
}
|
||||
|
||||
// Encrypt EKS blob.
|
||||
u8 *eks = calloc(512 , 1);
|
||||
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
|
||||
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
|
||||
|
||||
// Write EKS blob to SD.
|
||||
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
|
||||
hos_eks_rw_try(mbr, true);
|
||||
|
||||
free(eks);
|
||||
free(keys);
|
||||
free(eks);
|
||||
free(keys);
|
||||
out:
|
||||
free(mbr);
|
||||
}
|
||||
free(mbr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,12 +316,8 @@ void hos_eks_clear(u32 kb)
|
||||
|
||||
if (h_cfg.eks && kb >= KB_FIRMWARE_VERSION_700)
|
||||
{
|
||||
u32 key_idx = 0;
|
||||
if (kb >= KB_FIRMWARE_VERSION_810)
|
||||
key_idx = 1;
|
||||
|
||||
// Check if Current Master key is enabled.
|
||||
if (h_cfg.eks->enabled[key_idx])
|
||||
// Check if current Master key is enabled.
|
||||
if (h_cfg.eks->enabled)
|
||||
{
|
||||
// Read EKS blob.
|
||||
u8 *mbr = calloc(512 , 1);
|
||||
@@ -345,20 +325,17 @@ void hos_eks_clear(u32 kb)
|
||||
goto out;
|
||||
|
||||
// Disable current Master key version.
|
||||
h_cfg.eks->enabled[key_idx] = 0;
|
||||
h_cfg.eks->enabled = 0;
|
||||
|
||||
// Encrypt EKS blob.
|
||||
u8 *eks = calloc(512 , 1);
|
||||
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
|
||||
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
|
||||
se_aes_crypt_ecb(14, ENCRYPT, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
|
||||
|
||||
// Write EKS blob to SD.
|
||||
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
|
||||
hos_eks_rw_try(mbr, true);
|
||||
|
||||
EMC(EMC_SCRATCH0) &= ~EMC_SEPT_RUN;
|
||||
h_cfg.sept_run = false;
|
||||
|
||||
free(eks);
|
||||
out:
|
||||
free(mbr);
|
||||
@@ -369,7 +346,7 @@ out:
|
||||
int hos_keygen_t210b01(u32 kb)
|
||||
{
|
||||
// Use SBK as Device key 4x unsealer and KEK for mkey in T210B01 units.
|
||||
se_aes_unwrap_key(10, 14, console_keyseed_4xx_5xx);
|
||||
se_aes_unwrap_key(10, 14, console_keyseed_4xx);
|
||||
|
||||
// Derive master key.
|
||||
se_aes_unwrap_key(7, 12, &master_kekseed_t210b01[kb - KB_FIRMWARE_VERSION_600]);
|
||||
@@ -381,9 +358,12 @@ int hos_keygen_t210b01(u32 kb)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt)
|
||||
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool is_exo)
|
||||
{
|
||||
static bool sbk_wiped = false;
|
||||
|
||||
u32 retries = 0;
|
||||
bool use_tsec = false;
|
||||
tsec_keys_t tsec_keys;
|
||||
kb_t *kb_data = (kb_t *)keyblob;
|
||||
|
||||
@@ -393,76 +373,114 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos
|
||||
if (h_cfg.t210b01)
|
||||
return hos_keygen_t210b01(kb);
|
||||
|
||||
if (kb <= KB_FIRMWARE_VERSION_600)
|
||||
tsec_ctxt->size = 0xF00;
|
||||
else if (kb == KB_FIRMWARE_VERSION_620)
|
||||
tsec_ctxt->size = 0x2900;
|
||||
else if (kb == KB_FIRMWARE_VERSION_700)
|
||||
tsec_ctxt->size = 0x3000;
|
||||
else
|
||||
tsec_ctxt->size = 0x3300;
|
||||
// Do Erista keygen.
|
||||
|
||||
// Prepare smmu tsec page for 6.2.0.
|
||||
if (kb == KB_FIRMWARE_VERSION_620)
|
||||
// SBK is wiped. Try to restore it from fuses.
|
||||
if (sbk_wiped)
|
||||
{
|
||||
if (fuse_set_sbk())
|
||||
sbk_wiped = false;
|
||||
else
|
||||
return 1; // Continue with current SE keys.
|
||||
}
|
||||
|
||||
// Use HOS EKS if it exists.
|
||||
_hos_eks_get();
|
||||
|
||||
// Use tsec keygen for old firmware or if EKS keys do not exist for newer.
|
||||
if (kb <= KB_FIRMWARE_VERSION_620 || !h_cfg.eks || (h_cfg.eks && h_cfg.eks->enabled < kb))
|
||||
use_tsec = true;
|
||||
|
||||
if (kb <= KB_FIRMWARE_VERSION_600)
|
||||
{
|
||||
tsec_ctxt->size = 0xF00;
|
||||
tsec_ctxt->type = TSEC_FW_TYPE_OLD;
|
||||
}
|
||||
else if (kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
tsec_ctxt->size = 0x2900;
|
||||
tsec_ctxt->type = TSEC_FW_TYPE_EMU;
|
||||
|
||||
// Prepare smmu tsec page for 6.2.0.
|
||||
u8 *tsec_paged = (u8 *)page_alloc(3);
|
||||
memcpy(tsec_paged, (void *)tsec_ctxt->fw, tsec_ctxt->size);
|
||||
tsec_ctxt->fw = tsec_paged;
|
||||
}
|
||||
else if (use_tsec) // 7.0.0+
|
||||
{
|
||||
/*
|
||||
* 7.0.0/8.1.0 tsec fw are 0x3000/0x3300.
|
||||
* Unused here because of THK.
|
||||
*/
|
||||
|
||||
// Use custom TSEC Hovi Keygen firmware.
|
||||
tsec_ctxt->fw = sd_file_read("bootloader/sys/thk.bin", NULL);
|
||||
if (!tsec_ctxt->fw)
|
||||
{
|
||||
_hos_crit_error("\nFailed to load thk.bin");
|
||||
return 0;
|
||||
}
|
||||
|
||||
tsec_ctxt->size = 0x1F00;
|
||||
tsec_ctxt->type = TSEC_FW_TYPE_NEW;
|
||||
}
|
||||
else if (h_cfg.eks)
|
||||
{
|
||||
// EKS found. Set TSEC keys.
|
||||
se_aes_key_set(12, h_cfg.eks->tsec, SE_KEY_128_SIZE);
|
||||
se_aes_key_set(13, h_cfg.eks->troot, SE_KEY_128_SIZE);
|
||||
se_aes_key_set(11, h_cfg.eks->troot_dev, SE_KEY_128_SIZE);
|
||||
}
|
||||
|
||||
// Get TSEC key.
|
||||
if (kb <= KB_FIRMWARE_VERSION_620)
|
||||
while (use_tsec && tsec_query(&tsec_keys, tsec_ctxt) < 0)
|
||||
{
|
||||
while (tsec_query(&tsec_keys, kb, tsec_ctxt) < 0)
|
||||
{
|
||||
memset(&tsec_keys, 0x00, 0x20);
|
||||
retries++;
|
||||
memset(&tsec_keys, 0x00, 0x20);
|
||||
retries++;
|
||||
|
||||
// We rely on racing conditions, make sure we cover even the unluckiest cases.
|
||||
if (retries > 15)
|
||||
{
|
||||
_hos_crit_error("\nFailed to get TSEC keys. Please try again.");
|
||||
return 0;
|
||||
}
|
||||
// We rely on racing conditions, make sure we cover even the unluckiest cases.
|
||||
if (retries > 15)
|
||||
{
|
||||
_hos_crit_error("\nFailed to get TSEC keys. Please try again.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (kb >= KB_FIRMWARE_VERSION_700)
|
||||
{
|
||||
// Use HOS EKS if it exists.
|
||||
u32 key_idx = 0;
|
||||
if (kb >= KB_FIRMWARE_VERSION_810)
|
||||
key_idx = 1;
|
||||
|
||||
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= kb)
|
||||
// For 7.0.0 and up, save EKS slot if it doesn't exist.
|
||||
if (use_tsec)
|
||||
{
|
||||
// Set Device keygen key to slot 10.
|
||||
se_aes_key_set(10, h_cfg.eks->dkg, SE_KEY_128_SIZE);
|
||||
// Set Device key to slot 15.
|
||||
se_aes_key_set(15, h_cfg.eks->dkk, SE_KEY_128_SIZE);
|
||||
|
||||
if (!h_cfg.aes_slots_new)
|
||||
{
|
||||
// Set Master key to slot 12.
|
||||
se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, SE_KEY_128_SIZE);
|
||||
// Set FW Device key key to slot 13.
|
||||
se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, SE_KEY_128_SIZE);
|
||||
// Lock FDK.
|
||||
se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
|
||||
}
|
||||
else // New exosphere.
|
||||
{
|
||||
// Set Master key to slot 13.
|
||||
se_aes_key_set(13, h_cfg.eks->keys[key_idx].mkk, SE_KEY_128_SIZE);
|
||||
// Set FW Device key key to slot 12.
|
||||
se_aes_key_set(12, h_cfg.eks->keys[key_idx].fdk, SE_KEY_128_SIZE);
|
||||
// Lock FDK.
|
||||
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
|
||||
}
|
||||
_hos_eks_save(kb);
|
||||
free(tsec_ctxt->fw);
|
||||
}
|
||||
|
||||
se_aes_key_clear(8);
|
||||
se_aes_unwrap_key(8, !h_cfg.aes_slots_new ? 12 : 13, package2_keyseed);
|
||||
if (!is_exo)
|
||||
{
|
||||
// Derive Package2 key in secmon compatible way.
|
||||
se_aes_unwrap_key(7, 13, master_kekseed_t210_max);
|
||||
se_aes_unwrap_key(7, 7, master_keyseed_retail);
|
||||
se_aes_unwrap_key(8, 7, package2_keyseed);
|
||||
}
|
||||
else
|
||||
{
|
||||
se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(15, 14, tsec_keys.tmp);
|
||||
|
||||
// Derive device keys.
|
||||
se_aes_unwrap_key(10, 15, console_keyseed_4xx);
|
||||
se_aes_unwrap_key(15, 15, console_keyseed);
|
||||
|
||||
// Derive master kek.
|
||||
se_aes_unwrap_key(13, 13, master_kekseed_t210_max);
|
||||
|
||||
// Derive device master key and master key.
|
||||
se_aes_unwrap_key(12, 13, master_keyseed_4xx);
|
||||
se_aes_unwrap_key(13, 13, master_keyseed_retail);
|
||||
|
||||
// Package2 key.
|
||||
se_aes_unwrap_key(8, 13, package2_keyseed);
|
||||
}
|
||||
}
|
||||
else if (kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
@@ -471,39 +489,33 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos
|
||||
// Set TSEC root key.
|
||||
se_aes_key_set(13, tsec_keys.tsec_root, SE_KEY_128_SIZE);
|
||||
|
||||
if (!(emu_cfg.enabled && !h_cfg.emummc_force_disable) && hos_ctxt->stock)
|
||||
if (!is_exo)
|
||||
{
|
||||
// Package2 key.
|
||||
// Derive Package2 key in secmon compatible way.
|
||||
se_aes_key_set(8, tsec_keys.tsec_root, SE_KEY_128_SIZE);
|
||||
se_aes_unwrap_key(8, 8, master_keyseed_620);
|
||||
se_aes_unwrap_key(8, 8, master_kekseed_620);
|
||||
se_aes_unwrap_key(8, 8, master_keyseed_retail);
|
||||
se_aes_unwrap_key(8, 8, package2_keyseed);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Decrypt keyblob and set keyslots
|
||||
se_aes_crypt_block_ecb(12, 0, tsec_keys.tmp, keyblob_keyseeds[0]);
|
||||
// Decrypt keyblob and set keyslots for Exosphere 2.
|
||||
se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(15, 14, tsec_keys.tmp);
|
||||
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
|
||||
|
||||
// Derive device keys.
|
||||
se_aes_unwrap_key(10, 15, console_keyseed_4xx);
|
||||
se_aes_unwrap_key(15, 15, console_keyseed);
|
||||
|
||||
se_aes_unwrap_key(13, 13, master_keyseed_620);
|
||||
// Derive master kek.
|
||||
se_aes_unwrap_key(13, 13, master_kekseed_620);
|
||||
|
||||
if (!h_cfg.aes_slots_new)
|
||||
{
|
||||
se_aes_unwrap_key(14, 13, master_keyseed_4xx_5xx_610);
|
||||
se_aes_unwrap_key(12, 13, master_keyseed_retail);
|
||||
}
|
||||
else // New exosphere.
|
||||
{
|
||||
se_aes_unwrap_key(12, 13, master_keyseed_4xx_5xx_610);
|
||||
se_aes_unwrap_key(13, 13, master_keyseed_retail);
|
||||
}
|
||||
// Derive device master key and master key.
|
||||
se_aes_unwrap_key(12, 13, master_keyseed_4xx);
|
||||
se_aes_unwrap_key(13, 13, master_keyseed_retail);
|
||||
|
||||
// Package2 key.
|
||||
se_aes_unwrap_key(8, !h_cfg.aes_slots_new ? 12 : 13, package2_keyseed);
|
||||
|
||||
h_cfg.se_keygen_done = 1;
|
||||
se_aes_unwrap_key(8, 13, package2_keyseed);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -515,13 +527,13 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos
|
||||
se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE);
|
||||
|
||||
// Derive keyblob keys from TSEC+SBK.
|
||||
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[0]);
|
||||
se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(15, 14, tsec_keys.tsec);
|
||||
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[kb]);
|
||||
se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, keyblob_keyseeds[kb]);
|
||||
se_aes_unwrap_key(13, 14, tsec_keys.tsec);
|
||||
|
||||
// Clear SBK.
|
||||
se_aes_key_clear(14);
|
||||
//se_aes_key_clear(14);
|
||||
|
||||
/*
|
||||
// Verify keyblob CMAC.
|
||||
@@ -532,18 +544,18 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos
|
||||
return 0;
|
||||
*/
|
||||
|
||||
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, cmac_keyseed);
|
||||
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_data->keys), &kb_data->keys, sizeof(kb_data->keys), kb_data->ctr);
|
||||
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_keyseed, SE_KEY_128_SIZE);
|
||||
se_aes_key_set(13, kb_data->keys.master_keyseed, 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);
|
||||
|
||||
se_aes_crypt_block_ecb(12, 0, tsec_keys.tsec, master_keyseed_retail);
|
||||
se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tsec, master_keyseed_retail);
|
||||
|
||||
if (!h_cfg.aes_slots_new)
|
||||
if (!is_exo)
|
||||
{
|
||||
switch (kb)
|
||||
{
|
||||
@@ -554,31 +566,33 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos
|
||||
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
||||
break;
|
||||
case KB_FIRMWARE_VERSION_400:
|
||||
se_aes_unwrap_key(13, 15, console_keyseed_4xx_5xx);
|
||||
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_5xx_610);
|
||||
se_aes_unwrap_key(14, 12, master_keyseed_4xx);
|
||||
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
||||
sbk_wiped = true;
|
||||
break;
|
||||
case KB_FIRMWARE_VERSION_500:
|
||||
case KB_FIRMWARE_VERSION_600:
|
||||
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
|
||||
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_5xx_610);
|
||||
se_aes_unwrap_key(14, 12, master_keyseed_4xx);
|
||||
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
||||
sbk_wiped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // New exosphere.
|
||||
else // Exosphere 2.
|
||||
{
|
||||
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
|
||||
se_aes_unwrap_key(10, 15, console_keyseed_4xx);
|
||||
se_aes_unwrap_key(15, 15, console_keyseed);
|
||||
se_aes_unwrap_key(13, 12, master_keyseed_retail);
|
||||
se_aes_unwrap_key(12, 12, master_keyseed_4xx_5xx_610);
|
||||
se_aes_unwrap_key(12, 12, master_keyseed_4xx);
|
||||
}
|
||||
|
||||
// Package2 key.
|
||||
se_key_acc_ctrl(8, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
|
||||
se_aes_unwrap_key(8, !h_cfg.aes_slots_new ? 12 : 13, package2_keyseed);
|
||||
se_aes_unwrap_key(8, !is_exo ? 12 : 13, package2_keyseed);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -722,14 +736,12 @@ int hos_launch(ini_sec_t *cfg)
|
||||
u8 kb;
|
||||
u32 secmon_base;
|
||||
u32 warmboot_base;
|
||||
launch_ctxt_t ctxt;
|
||||
bool exo_new = false;
|
||||
tsec_ctxt_t tsec_ctxt;
|
||||
bool is_exo = false;
|
||||
launch_ctxt_t ctxt = {0};
|
||||
tsec_ctxt_t tsec_ctxt = {0};
|
||||
volatile secmon_mailbox_t *secmon_mailbox;
|
||||
|
||||
minerva_change_freq(FREQ_1600);
|
||||
memset(&ctxt, 0, sizeof(launch_ctxt_t));
|
||||
memset(&tsec_ctxt, 0, sizeof(tsec_ctxt_t));
|
||||
list_init(&ctxt.kip1_list);
|
||||
|
||||
ctxt.cfg = cfg;
|
||||
@@ -780,7 +792,7 @@ int hos_launch(ini_sec_t *cfg)
|
||||
goto error;
|
||||
}
|
||||
|
||||
ctxt.atmosphere = true; // Set atmosphere patching in case of Stock emuMMC and no fss0.
|
||||
ctxt.atmosphere = true; // Set atmosphere patching in case of no fss0.
|
||||
config_kip1patch(&ctxt, "emummc");
|
||||
}
|
||||
else if (!emu_cfg.enabled && ctxt.emummc_forced)
|
||||
@@ -817,34 +829,22 @@ int hos_launch(ini_sec_t *cfg)
|
||||
|
||||
gfx_puts("Loaded config, pkg1 and keyblob\n");
|
||||
|
||||
// Check if secmon is new exosphere.
|
||||
// Check if secmon is exosphere.
|
||||
if (ctxt.secmon)
|
||||
exo_new = !memcmp((void *)((u8 *)ctxt.secmon + ctxt.secmon_size - 4), "LENY", 4);
|
||||
is_exo = !memcmp((void *)((u8 *)ctxt.secmon + ctxt.secmon_size - 4), "LENY", 4);
|
||||
const pkg1_id_t *pk1_latest = pkg1_get_latest();
|
||||
secmon_base = exo_new ? pk1_latest->secmon_base : ctxt.pkg1_id->secmon_base;
|
||||
warmboot_base = exo_new ? pk1_latest->warmboot_base : ctxt.pkg1_id->warmboot_base;
|
||||
h_cfg.aes_slots_new = exo_new;
|
||||
secmon_base = is_exo ? pk1_latest->secmon_base : ctxt.pkg1_id->secmon_base;
|
||||
warmboot_base = is_exo ? pk1_latest->warmboot_base : ctxt.pkg1_id->warmboot_base;
|
||||
|
||||
// Generate keys.
|
||||
if (!h_cfg.se_keygen_done)
|
||||
{
|
||||
tsec_ctxt.fw = (u8 *)ctxt.pkg1 + ctxt.pkg1_id->tsec_off;
|
||||
tsec_ctxt.pkg1 = ctxt.pkg1;
|
||||
tsec_ctxt.pkg11_off = ctxt.pkg1_id->pkg11_off;
|
||||
tsec_ctxt.secmon_base = secmon_base;
|
||||
tsec_ctxt.fw = (u8 *)ctxt.pkg1 + ctxt.pkg1_id->tsec_off;
|
||||
tsec_ctxt.pkg1 = ctxt.pkg1;
|
||||
tsec_ctxt.pkg11_off = ctxt.pkg1_id->pkg11_off;
|
||||
tsec_ctxt.secmon_base = secmon_base;
|
||||
|
||||
if (kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
|
||||
{
|
||||
_hos_crit_error("Failed to run sept");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!hos_keygen(ctxt.keyblob, kb, &tsec_ctxt, &ctxt))
|
||||
goto error;
|
||||
gfx_puts("Generated keys\n");
|
||||
if (kb <= KB_FIRMWARE_VERSION_600)
|
||||
h_cfg.se_keygen_done = 1;
|
||||
}
|
||||
if (!hos_keygen(ctxt.keyblob, kb, &tsec_ctxt, ctxt.stock, is_exo))
|
||||
goto error;
|
||||
gfx_puts("Generated keys\n");
|
||||
|
||||
// Decrypt and unpack package1 if we require parts of it.
|
||||
if (!ctxt.warmboot || !ctxt.secmon)
|
||||
@@ -870,7 +870,7 @@ int hos_launch(ini_sec_t *cfg)
|
||||
pk1_offset = sizeof(bl_hdr_t210b01_t);
|
||||
|
||||
pkg1_unpack((void *)warmboot_base, &ctxt.warmboot_size,
|
||||
!exo_new ? (void *)ctxt.pkg1_id->secmon_base : NULL, NULL,
|
||||
!is_exo ? (void *)ctxt.pkg1_id->secmon_base : NULL, NULL,
|
||||
ctxt.pkg1_id, ctxt.pkg1 + pk1_offset);
|
||||
|
||||
gfx_puts("Decrypted & unpacked pkg1\n");
|
||||
@@ -929,19 +929,16 @@ int 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);
|
||||
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2, kb, is_exo);
|
||||
if (!pkg2_hdr)
|
||||
{
|
||||
_hos_crit_error("Pkg2 decryption failed!");
|
||||
EPRINTFARGS("Is hekate%s updated?", kb >= KB_FIRMWARE_VERSION_700 ? " or Sept" : "");
|
||||
EPRINTF("Is hekate updated?");
|
||||
|
||||
// Clear EKS slot, in case something went wrong with sept keygen.
|
||||
if (kb >= KB_FIRMWARE_VERSION_700)
|
||||
hos_eks_clear(kb);
|
||||
// Clear EKS slot, in case something went wrong with tsec keygen.
|
||||
hos_eks_clear(kb);
|
||||
goto error;
|
||||
}
|
||||
else if (kb >= KB_FIRMWARE_VERSION_700)
|
||||
hos_eks_save(kb); // Save EKS slot if it doesn't exist.
|
||||
|
||||
LIST_INIT(kip1_info);
|
||||
if (!pkg2_parse_kips(&kip1_info, pkg2_hdr, &ctxt.new_pkg2))
|
||||
@@ -1056,8 +1053,11 @@ int hos_launch(ini_sec_t *cfg)
|
||||
se_aes_key_clear(8);
|
||||
se_aes_key_clear(11);
|
||||
|
||||
// Finalize per firmware key access. Skip access control if new exosphere.
|
||||
switch (kb | (exo_new << 7))
|
||||
// Clear derived master key in case of Erista and 7.0.0+
|
||||
se_aes_key_clear(9);
|
||||
|
||||
// Finalize per firmware key access. Skip access control if Exosphere 2.
|
||||
switch (kb | (is_exo << 7))
|
||||
{
|
||||
case KB_FIRMWARE_VERSION_100:
|
||||
case KB_FIRMWARE_VERSION_300:
|
||||
@@ -1079,7 +1079,7 @@ int hos_launch(ini_sec_t *cfg)
|
||||
}
|
||||
|
||||
// Clear BCT area for retail units and copy it over if dev unit.
|
||||
if (kb <= KB_FIRMWARE_VERSION_500 && !exo_new)
|
||||
if (kb <= KB_FIRMWARE_VERSION_500 && !is_exo)
|
||||
{
|
||||
memset((void *)SECMON_BCT_CFG_ADDR, 0, 0x3000);
|
||||
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV)
|
||||
@@ -1094,19 +1094,19 @@ int hos_launch(ini_sec_t *cfg)
|
||||
free(bootConfigBuf);
|
||||
|
||||
// Config Exosphère if booting full Atmosphère.
|
||||
if (ctxt.atmosphere && ctxt.secmon)
|
||||
config_exosphere(&ctxt, warmboot_base, exo_new);
|
||||
if (is_exo)
|
||||
config_exosphere(&ctxt, warmboot_base);
|
||||
|
||||
// Unmount SD card and eMMC.
|
||||
sd_end();
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
|
||||
// Finalize MC carveout.
|
||||
if (kb <= KB_FIRMWARE_VERSION_301 && !exo_new)
|
||||
if (kb <= KB_FIRMWARE_VERSION_301 && !is_exo)
|
||||
mc_config_carveout();
|
||||
|
||||
// Lock SE before starting 'SecureMonitor' if < 6.2.0, otherwise lock bootrom and ipatches.
|
||||
_se_lock(kb <= KB_FIRMWARE_VERSION_600 && !exo_new);
|
||||
_se_lock(kb <= KB_FIRMWARE_VERSION_600 && !is_exo);
|
||||
|
||||
// Reset sysctr0 counters.
|
||||
if (kb >= KB_FIRMWARE_VERSION_620)
|
||||
@@ -1116,7 +1116,7 @@ int hos_launch(ini_sec_t *cfg)
|
||||
//pmc_scratch_lock(PMC_SEC_LOCK_LP0_PARAMS);
|
||||
|
||||
// Set secmon mailbox address and clear it.
|
||||
if (kb >= KB_FIRMWARE_VERSION_700 || exo_new)
|
||||
if (kb >= KB_FIRMWARE_VERSION_700 || is_exo)
|
||||
{
|
||||
memset((void *)SECMON7_MAILBOX_ADDR, 0, 0x200);
|
||||
secmon_mailbox = (secmon_mailbox_t *)(SECMON7_MAILBOX_ADDR + SECMON_STATE_OFFSET);
|
||||
@@ -1172,6 +1172,6 @@ int hos_launch(ini_sec_t *cfg)
|
||||
|
||||
error:
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
h_cfg.aes_slots_new = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user