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:
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user