keys: Add helper func for eticket rsa kek

This commit is contained in:
shchmue 2022-02-10 08:45:06 -07:00
parent 514343db9b
commit 54412f5a9d

View file

@ -73,7 +73,7 @@ static ALWAYS_INLINE u32 _read_be_u32(const void *buffer, u32 offset) {
static int _key_exists(const void *data) { return memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) != 0; }; static int _key_exists(const void *data) { return memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) != 0; };
static void _save_key(const char *name, const void *data, u32 len, char *outbuf); static void _save_key(const char *name, const void *data, u32 len, char *outbuf);
static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf); static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf);
static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed); static void _generate_kek(u32 ks, const void *key_source, const void *master_key, const void *kek_seed, const void *key_seed);
static void _generate_specific_aes_key(u32 ks, key_derivation_ctx_t *keys, void *out_key, const void *key_source, u32 key_generation); static void _generate_specific_aes_key(u32 ks, key_derivation_ctx_t *keys, void *out_key, const void *key_source, u32 key_generation);
static void _get_device_key(u32 ks, key_derivation_ctx_t *keys, void *out_device_key, u32 revision); static void _get_device_key(u32 ks, key_derivation_ctx_t *keys, void *out_device_key, u32 revision);
// titlekey functions // titlekey functions
@ -226,6 +226,14 @@ static void _derive_non_unique_keys(key_derivation_ctx_t *keys, bool is_dev) {
} }
} }
static void _derive_eticket_rsa_kek(key_derivation_ctx_t *keys, u32 ks, void *out_rsa_kek, const void *master_key, const void *kek_source) {
u8 kek_seed[AES_128_KEY_SIZE];
for (u32 i = 0; i < AES_128_KEY_SIZE; i++)
kek_seed[i] = aes_kek_generation_source[i] ^ aes_seal_key_mask_import_es_device_key[i];
_generate_kek(ks, eticket_rsa_kekek_source, master_key, kek_seed, NULL);
se_aes_crypt_block_ecb(ks, DECRYPT, out_rsa_kek, kek_source);
}
static void _derive_misc_keys(key_derivation_ctx_t *keys, bool is_dev) { static void _derive_misc_keys(key_derivation_ctx_t *keys, bool is_dev) {
if (_key_exists(keys->device_key) || (_key_exists(keys->master_key[0]) && _key_exists(keys->device_key_4x))) { if (_key_exists(keys->device_key) || (_key_exists(keys->master_key[0]) && _key_exists(keys->device_key_4x))) {
_get_device_key(8, keys, keys->temp_key, 0); _get_device_key(8, keys, keys->temp_key, 0);
@ -234,10 +242,7 @@ static void _derive_misc_keys(key_derivation_ctx_t *keys, bool is_dev) {
} }
if (_key_exists(keys->master_key[0])) { if (_key_exists(keys->master_key[0])) {
for (u32 i = 0; i < AES_128_KEY_SIZE; i++) _derive_eticket_rsa_kek(keys, 8, keys->eticket_rsa_kek, keys->master_key[0], is_dev ? eticket_rsa_kek_source_dev : eticket_rsa_kek_source);
keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_seal_key_mask_import_es_device_key[i];
_generate_kek(8, eticket_rsa_kekek_source, keys->master_key[0], keys->temp_key, NULL);
se_aes_crypt_block_ecb(8, DECRYPT, keys->eticket_rsa_kek, is_dev ? eticket_rsa_kek_source_dev : eticket_rsa_kek_source);
for (u32 i = 0; i < AES_128_KEY_SIZE; i++) for (u32 i = 0; i < AES_128_KEY_SIZE; i++)
keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_seal_key_mask_decrypt_device_unique_data[i]; keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_seal_key_mask_decrypt_device_unique_data[i];
@ -440,7 +445,7 @@ static bool _derive_sd_seed(key_derivation_ctx_t *keys) {
return true; return true;
} }
static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *titlekey_buffer) { static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *titlekey_buffer, bool is_dev) {
if (!_key_exists(keys->eticket_rsa_kek)) { if (!_key_exists(keys->eticket_rsa_kek)) {
return false; return false;
} }
@ -482,12 +487,8 @@ static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit
if (keypair_generation) { if (keypair_generation) {
keypair_generation--; keypair_generation--;
for (u32 i = 0; i < AES_128_KEY_SIZE; i++) _get_device_key(7, keys, keys->temp_key, keypair_generation);
keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_seal_key_mask_import_es_device_key[i]; _derive_eticket_rsa_kek(keys, 7, keys->eticket_rsa_kek_personalized, keys->temp_key, is_dev ? eticket_rsa_kek_source_dev : eticket_rsa_kek_source);
u32 temp_device_key[AES_128_KEY_SIZE / 4] = {0};
_get_device_key(7, keys, temp_device_key, keypair_generation);
_generate_kek(7, eticket_rsa_kekek_source, temp_device_key, keys->temp_key, NULL);
se_aes_crypt_block_ecb(7, DECRYPT, keys->eticket_rsa_kek_personalized, eticket_rsa_kek_source);
memcpy(keys->temp_key, keys->eticket_rsa_kek_personalized, sizeof(keys->temp_key)); memcpy(keys->temp_key, keys->eticket_rsa_kek_personalized, sizeof(keys->temp_key));
} else { } else {
memcpy(keys->temp_key, keys->eticket_rsa_kek, sizeof(keys->temp_key)); memcpy(keys->temp_key, keys->eticket_rsa_kek, sizeof(keys->temp_key));
@ -498,10 +499,8 @@ static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit
// Check public exponent is 65537 big endian // Check public exponent is 65537 big endian
if (_read_be_u32(rsa_keypair.public_exponent, 0) != 65537) { if (_read_be_u32(rsa_keypair.public_exponent, 0) != 65537) {
for (u32 i = 0; i < AES_128_KEY_SIZE; i++) // try legacy kek source
keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_seal_key_mask_import_es_device_key[i]; _derive_eticket_rsa_kek(keys, 7, keys->temp_key, keys->master_key[0], eticket_rsa_kek_source_legacy);
_generate_kek(8, eticket_rsa_kekek_source, keys->master_key[0], keys->temp_key, NULL);
se_aes_crypt_block_ecb(8, DECRYPT, keys->temp_key, eticket_rsa_kek_source_legacy);
se_aes_key_set(6, keys->temp_key, sizeof(keys->temp_key)); se_aes_key_set(6, keys->temp_key, sizeof(keys->temp_key));
se_aes_crypt_ctr(6, &rsa_keypair, sizeof(rsa_keypair), eticket_device_key, sizeof(rsa_keypair), eticket_iv); se_aes_crypt_ctr(6, &rsa_keypair, sizeof(rsa_keypair), eticket_device_key, sizeof(rsa_keypair), eticket_iv);
@ -530,7 +529,7 @@ static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit
return true; return true;
} }
static bool _derive_emmc_keys(key_derivation_ctx_t *keys, titlekey_buffer_t *titlekey_buffer) { static bool _derive_emmc_keys(key_derivation_ctx_t *keys, titlekey_buffer_t *titlekey_buffer, bool is_dev) {
// Set BIS keys. // Set BIS keys.
// PRODINFO/PRODINFOF // PRODINFO/PRODINFOF
se_aes_key_set(0, keys->bis_key[0] + 0x00, AES_128_KEY_SIZE); se_aes_key_set(0, keys->bis_key[0] + 0x00, AES_128_KEY_SIZE);
@ -571,7 +570,7 @@ static bool _derive_emmc_keys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit
EPRINTF("Unable to get SD seed."); EPRINTF("Unable to get SD seed.");
} }
bool res = _derive_titlekeys(keys, titlekey_buffer); bool res = _derive_titlekeys(keys, titlekey_buffer, is_dev);
if (!res) { if (!res) {
EPRINTF("Unable to derive titlekeys."); EPRINTF("Unable to derive titlekeys.");
} }
@ -882,7 +881,7 @@ static void _derive_keys() {
if (!emmc_storage.initialized) { if (!emmc_storage.initialized) {
EPRINTF("eMMC not initialized.\nSkipping SD seed and titlekeys."); EPRINTF("eMMC not initialized.\nSkipping SD seed and titlekeys.");
} else if (_key_exists(keys->bis_key[2])) { } else if (_key_exists(keys->bis_key[2])) {
_derive_emmc_keys(keys, titlekey_buffer); _derive_emmc_keys(keys, titlekey_buffer, is_dev);
} else { } else {
EPRINTF("Missing needed BIS keys.\nSkipping SD seed and titlekeys."); EPRINTF("Missing needed BIS keys.\nSkipping SD seed and titlekeys.");
} }
@ -963,7 +962,7 @@ static void _save_key_family(const char *name, const void *data, u32 start_key,
free(temp_name); free(temp_name);
} }
static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed) { static void _generate_kek(u32 ks, const void *key_source, const void *master_key, const void *kek_seed, const void *key_seed) {
if (!_key_exists(key_source) || !_key_exists(master_key) || !_key_exists(kek_seed)) if (!_key_exists(key_source) || !_key_exists(master_key) || !_key_exists(kek_seed))
return; return;