eks: Upgrade to new version and support BIS keys

This commit is contained in:
CTCaer 2020-06-14 13:42:48 +03:00
parent 242bbdada5
commit 92d013dd65
6 changed files with 107 additions and 100 deletions

View file

@ -183,24 +183,16 @@ void _sysctr0_reset()
bool hos_eks_rw_try(u8 *buf, bool write) bool hos_eks_rw_try(u8 *buf, bool write)
{ {
mbr_t *mbr = (mbr_t *)buf;
for (u32 i = 0; i < 3; i++) for (u32 i = 0; i < 3; i++)
{ {
if (!write) if (!write)
{ {
if (sdmmc_storage_read(&sd_storage, 0, 1, mbr)) if (sdmmc_storage_read(&sd_storage, 0, 1, buf))
{ return true;
if (mbr->partitions[0].status != 0xFF &&
mbr->partitions[0].start_sct &&
mbr->partitions[0].size_sct)
return true;
else
return false;
}
} }
else else
{ {
if (sdmmc_storage_write(&sd_storage, 0, 1, mbr)) if (sdmmc_storage_write(&sd_storage, 0, 1, buf))
return true; return true;
} }
} }
@ -219,15 +211,12 @@ void hos_eks_get()
goto out; goto out;
// Decrypt EKS blob. // Decrypt EKS blob.
hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x10); hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x60);
se_aes_crypt_ecb(14, 0, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t)); se_aes_crypt_ecb(14, 0, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Check if valid and for this unit. // Check if valid and for this unit.
if (eks->enabled && if (eks->magic == HOS_EKS_MAGIC &&
eks->magic == HOS_EKS_MAGIC && eks->sbk_low == FUSE(FUSE_PRIVATE_KEY0))
eks->magic2 == HOS_EKS_MAGIC &&
eks->sbk_low[0] == FUSE(FUSE_PRIVATE_KEY0) &&
eks->sbk_low[1] == FUSE(FUSE_PRIVATE_KEY1))
{ {
h_cfg.eks = eks; h_cfg.eks = eks;
return; return;
@ -242,10 +231,9 @@ void hos_eks_save(u32 kb)
{ {
if (kb >= KB_FIRMWARE_VERSION_700) if (kb >= KB_FIRMWARE_VERSION_700)
{ {
// Only 6 Master keys for now. u32 key_idx = 0;
u8 key_idx = kb - KB_FIRMWARE_VERSION_700; if (kb >= KB_FIRMWARE_VERSION_810)
if (key_idx > 5) key_idx = 1;
return;
bool new_eks = false; bool new_eks = false;
if (!h_cfg.eks) if (!h_cfg.eks)
@ -255,7 +243,8 @@ void hos_eks_save(u32 kb)
} }
// If matching blob doesn't exist, create it. // If matching blob doesn't exist, create it.
if (!(h_cfg.eks->enabled & (1 << key_idx))) bool update_eks = key_idx ? (h_cfg.eks->enabled[key_idx] < kb) : !h_cfg.eks->enabled[0];
if (update_eks)
{ {
// Read EKS blob. // Read EKS blob.
u8 *mbr = calloc(512 , 1); u8 *mbr = calloc(512 , 1);
@ -276,16 +265,15 @@ void hos_eks_save(u32 kb)
// Set magic and personalized info. // Set magic and personalized info.
h_cfg.eks->magic = HOS_EKS_MAGIC; h_cfg.eks->magic = HOS_EKS_MAGIC;
h_cfg.eks->magic2 = HOS_EKS_MAGIC; h_cfg.eks->enabled[key_idx] = kb;
h_cfg.eks->enabled |= 1 << key_idx; h_cfg.eks->sbk_low = FUSE(FUSE_PRIVATE_KEY0);
h_cfg.eks->sbk_low[0] = FUSE(FUSE_PRIVATE_KEY0);
h_cfg.eks->sbk_low[1] = FUSE(FUSE_PRIVATE_KEY1);
// Copy new keys. // Copy new keys.
memcpy(h_cfg.eks->keys[key_idx].dkg, keys + 10 * 0x10, 0x10); memcpy(h_cfg.eks->dkg, keys + 10 * 0x10, 0x10);
memcpy(h_cfg.eks->dkk, keys + 15 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * 0x10, 0x10); memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10); memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].dkk, keys + 15 * 0x10, 0x10);
// Encrypt EKS blob. // Encrypt EKS blob.
u8 *eks = calloc(512 , 1); u8 *eks = calloc(512 , 1);
@ -293,8 +281,7 @@ void hos_eks_save(u32 kb)
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), 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. // Write EKS blob to SD.
memset(mbr, 0, 0x10); memcpy(mbr + 0x60, eks, sizeof(hos_eks_mbr_t));
memcpy(mbr + 0x10, eks, sizeof(hos_eks_mbr_t));
hos_eks_rw_try(mbr, true); hos_eks_rw_try(mbr, true);
@ -310,9 +297,12 @@ void hos_eks_clear(u32 kb)
{ {
if (h_cfg.eks && kb >= KB_FIRMWARE_VERSION_700) 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. // Check if Current Master key is enabled.
u8 key_idx = kb - KB_FIRMWARE_VERSION_700; if (h_cfg.eks->enabled[key_idx])
if (h_cfg.eks->enabled & (1 << key_idx))
{ {
// Read EKS blob. // Read EKS blob.
u8 *mbr = calloc(512 , 1); u8 *mbr = calloc(512 , 1);
@ -320,7 +310,7 @@ void hos_eks_clear(u32 kb)
goto out; goto out;
// Disable current Master key version. // Disable current Master key version.
h_cfg.eks->enabled &= ~(1 << key_idx); h_cfg.eks->enabled[key_idx] = 0;
// Encrypt EKS blob. // Encrypt EKS blob.
u8 *eks = calloc(512 , 1); u8 *eks = calloc(512 , 1);
@ -328,9 +318,12 @@ void hos_eks_clear(u32 kb)
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), 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. // Write EKS blob to SD.
memcpy(mbr + 0x10, eks, sizeof(hos_eks_mbr_t)); memcpy(mbr + 0x60, eks, sizeof(hos_eks_mbr_t));
hos_eks_rw_try(mbr, true); hos_eks_rw_try(mbr, true);
EMC(EMC_SCRATCH0) &= ~EMC_SEPT_RUN;
h_cfg.sept_run = false;
free(eks); free(eks);
out: out:
free(mbr); free(mbr);
@ -383,17 +376,20 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c
if (kb >= KB_FIRMWARE_VERSION_700) if (kb >= KB_FIRMWARE_VERSION_700)
{ {
// Use HOS EKS if it exists. // Use HOS EKS if it exists.
u8 key_idx = kb - KB_FIRMWARE_VERSION_700; u32 key_idx = 0;
if (h_cfg.eks && (h_cfg.eks->enabled & (1 << key_idx))) if (kb >= KB_FIRMWARE_VERSION_810)
key_idx = 1;
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= kb)
{ {
// Set Device keygen key to slot 10. // Set Device keygen key to slot 10.
se_aes_key_set(10, h_cfg.eks->keys[key_idx].dkg, 0x10); se_aes_key_set(10, h_cfg.eks->dkg, 0x10);
// Set Device key to slot 15.
se_aes_key_set(15, h_cfg.eks->dkk, 0x10);
// Set Master key to slot 12. // Set Master key to slot 12.
se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, 0x10); se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, 0x10);
// Set FW Device key key to slot 13. // Set FW Device key key to slot 13.
se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, 0x10); se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, 0x10);
// Set Device key to slot 15.
se_aes_key_set(15, h_cfg.eks->keys[key_idx].dkk, 0x10);
// Lock FDK. // 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); se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);

View file

@ -52,23 +52,30 @@ typedef struct _exo_ctxt_t
typedef struct _hos_eks_keys_t typedef struct _hos_eks_keys_t
{ {
u8 dkg[0x10];
u8 mkk[0x10]; u8 mkk[0x10];
u8 fdk[0x10]; u8 fdk[0x10];
u8 dkk[0x10];
} hos_eks_keys_t; } hos_eks_keys_t;
typedef struct _hos_eks_bis_keys_t
{
u8 crypt[0x10];
u8 tweak[0x10];
} hos_eks_bis_keys_t;
typedef struct _hos_eks_mbr_t typedef struct _hos_eks_mbr_t
{ {
u32 magic; u32 magic;
u32 enabled; u8 enabled[6];
u32 sbk_low[2]; u8 enabled_bis;
u8 rsvd;
u32 sbk_low;
u8 dkg[0x10];
u8 dkk[0x10];
hos_eks_keys_t keys[6]; hos_eks_keys_t keys[6];
u32 magic2; hos_eks_bis_keys_t bis_keys[3];
u32 rsvd2[3];
} hos_eks_mbr_t; } hos_eks_mbr_t;
static_assert(sizeof(hos_eks_mbr_t) == 416, "HOS EKS storage bigger than MBR!"); static_assert(sizeof(hos_eks_mbr_t) == 336, "HOS EKS size is wrong!");
typedef struct _launch_ctxt_t typedef struct _launch_ctxt_t
{ {

View file

@ -113,11 +113,13 @@ void check_sept(ini_sec_t *cfg_sec)
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run) if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
{ {
u8 key_idx = pkg1_id->kb - KB_FIRMWARE_VERSION_700; u32 key_idx = 0;
if (h_cfg.eks && (h_cfg.eks->enabled & (1 << key_idx))) if (pkg1_id->kb >= KB_FIRMWARE_VERSION_810)
key_idx = 1;
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= pkg1_id->kb)
{ {
h_cfg.sept_run = true; h_cfg.sept_run = true;
EMC(EMC_SCRATCH0) |= EMC_SEPT_RUN;
goto out_free; goto out_free;
} }

View file

@ -92,24 +92,16 @@ static const u8 console_keyseed_4xx_5xx[0x10] =
bool hos_eks_rw_try(u8 *buf, bool write) bool hos_eks_rw_try(u8 *buf, bool write)
{ {
mbr_t *mbr = (mbr_t *)buf;
for (u32 i = 0; i < 3; i++) for (u32 i = 0; i < 3; i++)
{ {
if (!write) if (!write)
{ {
if (sdmmc_storage_read(&sd_storage, 0, 1, mbr)) if (sdmmc_storage_read(&sd_storage, 0, 1, buf))
{ return true;
if (mbr->partitions[0].status != 0xFF &&
mbr->partitions[0].start_sct &&
mbr->partitions[0].size_sct)
return true;
else
return false;
}
} }
else else
{ {
if (sdmmc_storage_write(&sd_storage, 0, 1, mbr)) if (sdmmc_storage_write(&sd_storage, 0, 1, buf))
return true; return true;
} }
} }
@ -128,15 +120,12 @@ void hos_eks_get()
goto out; goto out;
// Decrypt EKS blob. // Decrypt EKS blob.
hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x10); hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x60);
se_aes_crypt_ecb(14, 0, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t)); se_aes_crypt_ecb(14, 0, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Check if valid and for this unit. // Check if valid and for this unit.
if (eks->enabled && if (eks->magic == HOS_EKS_MAGIC &&
eks->magic == HOS_EKS_MAGIC && eks->sbk_low == FUSE(FUSE_PRIVATE_KEY0))
eks->magic2 == HOS_EKS_MAGIC &&
eks->sbk_low[0] == FUSE(FUSE_PRIVATE_KEY0) &&
eks->sbk_low[1] == FUSE(FUSE_PRIVATE_KEY1))
{ {
h_cfg.eks = eks; h_cfg.eks = eks;
return; return;
@ -151,10 +140,9 @@ void hos_eks_save(u32 kb)
{ {
if (kb >= KB_FIRMWARE_VERSION_700) if (kb >= KB_FIRMWARE_VERSION_700)
{ {
// Only 6 Master keys for now. u32 key_idx = 0;
u8 key_idx = kb - KB_FIRMWARE_VERSION_700; if (kb >= KB_FIRMWARE_VERSION_810)
if (key_idx > 5) key_idx = 1;
return;
bool new_eks = false; bool new_eks = false;
if (!h_cfg.eks) if (!h_cfg.eks)
@ -164,7 +152,8 @@ void hos_eks_save(u32 kb)
} }
// If matching blob doesn't exist, create it. // If matching blob doesn't exist, create it.
if (!(h_cfg.eks->enabled & (1 << key_idx))) bool update_eks = key_idx ? (h_cfg.eks->enabled[key_idx] < kb) : !h_cfg.eks->enabled[0];
if (update_eks)
{ {
// Read EKS blob. // Read EKS blob.
u8 *mbr = calloc(512 , 1); u8 *mbr = calloc(512 , 1);
@ -185,16 +174,15 @@ void hos_eks_save(u32 kb)
// Set magic and personalized info. // Set magic and personalized info.
h_cfg.eks->magic = HOS_EKS_MAGIC; h_cfg.eks->magic = HOS_EKS_MAGIC;
h_cfg.eks->magic2 = HOS_EKS_MAGIC; h_cfg.eks->enabled[key_idx] = kb;
h_cfg.eks->enabled |= 1 << key_idx; h_cfg.eks->sbk_low = FUSE(FUSE_PRIVATE_KEY0);
h_cfg.eks->sbk_low[0] = FUSE(FUSE_PRIVATE_KEY0);
h_cfg.eks->sbk_low[1] = FUSE(FUSE_PRIVATE_KEY1);
// Copy new keys. // Copy new keys.
memcpy(h_cfg.eks->keys[key_idx].dkg, keys + 10 * 0x10, 0x10); memcpy(h_cfg.eks->dkg, keys + 10 * 0x10, 0x10);
memcpy(h_cfg.eks->dkk, keys + 15 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * 0x10, 0x10); memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10); memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].dkk, keys + 15 * 0x10, 0x10);
// Encrypt EKS blob. // Encrypt EKS blob.
u8 *eks = calloc(512 , 1); u8 *eks = calloc(512 , 1);
@ -202,8 +190,7 @@ void hos_eks_save(u32 kb)
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), 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. // Write EKS blob to SD.
memset(mbr, 0, 0x10); memcpy(mbr + 0x60, eks, sizeof(hos_eks_mbr_t));
memcpy(mbr + 0x10, eks, sizeof(hos_eks_mbr_t));
hos_eks_rw_try(mbr, true); hos_eks_rw_try(mbr, true);
@ -219,9 +206,12 @@ void hos_eks_clear(u32 kb)
{ {
if (h_cfg.eks && kb >= KB_FIRMWARE_VERSION_700) 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. // Check if Current Master key is enabled.
u8 key_idx = kb - KB_FIRMWARE_VERSION_700; if (h_cfg.eks->enabled[key_idx])
if (h_cfg.eks->enabled & (1 << key_idx))
{ {
// Read EKS blob. // Read EKS blob.
u8 *mbr = calloc(512 , 1); u8 *mbr = calloc(512 , 1);
@ -229,7 +219,7 @@ void hos_eks_clear(u32 kb)
goto out; goto out;
// Disable current Master key version. // Disable current Master key version.
h_cfg.eks->enabled &= ~(1 << key_idx); h_cfg.eks->enabled[key_idx] = 0;
// Encrypt EKS blob. // Encrypt EKS blob.
u8 *eks = calloc(512 , 1); u8 *eks = calloc(512 , 1);
@ -237,9 +227,12 @@ void hos_eks_clear(u32 kb)
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), 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. // Write EKS blob to SD.
memcpy(mbr + 0x10, eks, sizeof(hos_eks_mbr_t)); memcpy(mbr + 0x60, eks, sizeof(hos_eks_mbr_t));
hos_eks_rw_try(mbr, true); hos_eks_rw_try(mbr, true);
EMC(EMC_SCRATCH0) &= ~EMC_SEPT_RUN;
h_cfg.sept_run = false;
free(eks); free(eks);
out: out:
free(mbr); free(mbr);
@ -292,20 +285,20 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
if (kb >= KB_FIRMWARE_VERSION_700) if (kb >= KB_FIRMWARE_VERSION_700)
{ {
// Use HOS EKS if it exists. // Use HOS EKS if it exists.
u8 key_idx = kb - KB_FIRMWARE_VERSION_700; u32 key_idx = 0;
if (h_cfg.eks && (h_cfg.eks->enabled & (1 << key_idx))) if (kb >= KB_FIRMWARE_VERSION_810)
key_idx = 1;
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= kb)
{ {
// Set Device keygen key to slot 10. // Set Device keygen key to slot 10.
se_aes_key_set(10, h_cfg.eks->keys[key_idx].dkg, 0x10); se_aes_key_set(10, h_cfg.eks->dkg, 0x10);
// Set Master key to slot 12. // Set Master key to slot 12.
se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, 0x10); se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, 0x10);
// Set FW Device key key to slot 13. // Set FW Device key key to slot 13.
se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, 0x10); se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, 0x10);
// Set Device key to slot 15. // Set Device key to slot 15.
se_aes_key_set(15, h_cfg.eks->keys[key_idx].dkk, 0x10); se_aes_key_set(15, h_cfg.eks->dkk, 0x10);
// 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);
} }
se_aes_key_clear(8); se_aes_key_clear(8);

View file

@ -44,23 +44,30 @@
typedef struct _hos_eks_keys_t typedef struct _hos_eks_keys_t
{ {
u8 dkg[0x10];
u8 mkk[0x10]; u8 mkk[0x10];
u8 fdk[0x10]; u8 fdk[0x10];
u8 dkk[0x10];
} hos_eks_keys_t; } hos_eks_keys_t;
typedef struct _hos_eks_bis_keys_t
{
u8 crypt[0x10];
u8 tweak[0x10];
} hos_eks_bis_keys_t;
typedef struct _hos_eks_mbr_t typedef struct _hos_eks_mbr_t
{ {
u32 magic; u32 magic;
u32 enabled; u8 enabled[6];
u32 sbk_low[2]; u8 enabled_bis;
u8 rsvd;
u32 sbk_low;
u8 dkg[0x10];
u8 dkk[0x10];
hos_eks_keys_t keys[6]; hos_eks_keys_t keys[6];
u32 magic2; hos_eks_bis_keys_t bis_keys[3];
u32 rsvd2[3];
} hos_eks_mbr_t; } hos_eks_mbr_t;
static_assert(sizeof(hos_eks_mbr_t) == 416, "HOS EKS storage bigger than MBR!"); static_assert(sizeof(hos_eks_mbr_t) == 336, "HOS EKS size is wrong!");
typedef struct _launch_ctxt_t typedef struct _launch_ctxt_t
{ {

View file

@ -109,11 +109,13 @@ void check_sept()
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run) if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
{ {
u8 key_idx = pkg1_id->kb - KB_FIRMWARE_VERSION_700; u32 key_idx = 0;
if (h_cfg.eks && (h_cfg.eks->enabled & (1 << key_idx))) if (pkg1_id->kb >= KB_FIRMWARE_VERSION_810)
key_idx = 1;
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= pkg1_id->kb)
{ {
h_cfg.sept_run = true; h_cfg.sept_run = true;
EMC(EMC_SCRATCH0) |= EMC_SEPT_RUN;
goto out_free; goto out_free;
} }