From 58eb5f6dd2a6c27a7efa6628f4eaefc4d89e0fea Mon Sep 17 00:00:00 2001 From: shchmue Date: Wed, 18 May 2022 08:09:52 -0600 Subject: [PATCH] Suport personalized SSL kek, dump SSL private key --- source/keys/key_sources.inl | 8 +++ source/keys/keys.c | 97 ++++++++++++++++++++++++++++++------ source/keys/keys.h | 2 + source/storage/nx_emmc_bis.h | 13 +++-- 4 files changed, 102 insertions(+), 18 deletions(-) diff --git a/source/keys/key_sources.inl b/source/keys/key_sources.inl index 02063b2..ef2f044 100644 --- a/source/keys/key_sources.inl +++ b/source/keys/key_sources.inl @@ -101,6 +101,8 @@ static const u8 aes_seal_key_mask_decrypt_device_unique_data[0x10] __attribute__ 0xA2, 0xAB, 0xBF, 0x9C, 0x92, 0x2F, 0xBB, 0xE3, 0x78, 0x79, 0x9B, 0xC0, 0xCC, 0xEA, 0xA5, 0x74}; static const u8 aes_seal_key_mask_import_es_device_key[0x10] __attribute__((aligned(4))) = { 0xE5, 0x4D, 0x9A, 0x02, 0xF0, 0x4F, 0x5F, 0xA8, 0xAD, 0x76, 0x0A, 0xF6, 0x32, 0x95, 0x59, 0xBB}; +static const u8 aes_seal_key_mask_decrypt_ssl_client_cert_key[0x10] __attribute__((aligned(4))) = { + 0xFD, 0x6A, 0x25, 0xE5, 0xD8, 0x38, 0x7F, 0x91, 0x49, 0xDA, 0xF8, 0x59, 0xA8, 0x28, 0xE6, 0x75}; static const u8 package2_key_source[0x10] __attribute__((aligned(4))) = { 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7}; static const u8 titlekek_source[0x10] __attribute__((aligned(4))) = { @@ -177,6 +179,12 @@ static const u8 ssl_rsa_kek_source_x[0x10] __attribute__((aligned(4))) = { 0X7F, 0X5B, 0XB0, 0X84, 0X7B, 0X25, 0XAA, 0X67, 0XFA, 0XC8, 0X4B, 0XE2, 0X3D, 0X7B, 0X69, 0X03}; static const u8 ssl_rsa_kek_source_y[0x10] __attribute__((aligned(4))) = { 0X9A, 0X38, 0X3B, 0XF4, 0X31, 0XD0, 0XBD, 0X81, 0X32, 0X53, 0X4B, 0XA9, 0X64, 0X39, 0X7D, 0XE3}; +static const u8 ssl_rsa_kek_source_y_dev[0x10] __attribute__((aligned(4))) = { + 0xD5, 0xD2, 0xFC, 0x00, 0xFD, 0x49, 0xDD, 0xF8, 0xEE, 0x7B, 0xC4, 0x4B, 0xE1, 0x4C, 0xAA, 0x99}; +static const u8 ssl_client_cert_kek_source[0x10] __attribute__((aligned(4))) = { + 0x64, 0xB8, 0x30, 0xDD, 0x0F, 0x3C, 0xB7, 0xFB, 0x4C, 0x16, 0x01, 0x97, 0xEA, 0x9D, 0x12, 0x10}; +static const u8 ssl_client_cert_key_source[0x10] __attribute__((aligned(4))) = { + 0x4D, 0x92, 0x5A, 0x69, 0x42, 0x23, 0xBB, 0x92, 0x59, 0x16, 0x3E, 0x51, 0x8C, 0x78, 0x14, 0x0F}; static const u8 device_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] __attribute__((aligned(4))) = { {0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.0.0 Device Master Kek Source. */ diff --git a/source/keys/keys.c b/source/keys/keys.c index 0b325f1..941a801 100644 --- a/source/keys/keys.c +++ b/source/keys/keys.c @@ -235,6 +235,14 @@ static void _derive_eticket_rsa_kek(key_derivation_ctx_t *keys, u32 ks, void *ou se_aes_crypt_block_ecb(ks, DECRYPT, out_rsa_kek, kek_source); } +static void _derive_ssl_rsa_kek(key_derivation_ctx_t *keys, u32 ks, void *out_rsa_kek, const void *master_key, const void *kekek_source, 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_decrypt_device_unique_data[i]; + _generate_kek(8, kekek_source, master_key, kek_seed, NULL); + se_aes_crypt_block_ecb(8, DECRYPT, out_rsa_kek, kek_source); +} + 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))) { _get_device_key(8, keys, keys->temp_key, 0); @@ -244,11 +252,7 @@ static void _derive_misc_keys(key_derivation_ctx_t *keys, bool is_dev) { if (_key_exists(keys->master_key[0])) { _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); - - 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]; - _generate_kek(8, ssl_rsa_kek_source_x, keys->master_key[0], keys->temp_key, NULL); - se_aes_crypt_block_ecb(8, DECRYPT, keys->ssl_rsa_kek, ssl_rsa_kek_source_y); + _derive_ssl_rsa_kek(keys, 8, keys->ssl_rsa_kek, keys->master_key[0], ssl_rsa_kek_source_x, is_dev ? ssl_rsa_kek_source_y_dev : ssl_rsa_kek_source_y); } } @@ -446,6 +450,74 @@ static bool _derive_sd_seed(key_derivation_ctx_t *keys) { return true; } +static bool _read_cal0(void *read_buffer) { + if (!emummc_storage_read(NX_EMMC_CALIBRATION_OFFSET / NX_EMMC_BLOCKSIZE, NX_EMMC_CALIBRATION_SIZE / NX_EMMC_BLOCKSIZE, read_buffer)) { + EPRINTF("Unable to read PRODINFO."); + return false; + } + + se_aes_xts_crypt(1, 0, DECRYPT, 0, read_buffer, read_buffer, XTS_CLUSTER_SIZE, NX_EMMC_CALIBRATION_SIZE / XTS_CLUSTER_SIZE); + + nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)read_buffer; + if (cal0->magic != MAGIC_CAL0) { + EPRINTF("Invalid CAL0 magic. Check BIS key 0."); + return false; + } + + return true; +} + +static bool _derive_personalized_ssl_key(key_derivation_ctx_t *keys, titlekey_buffer_t *titlekey_buffer) { + if (!_read_cal0(titlekey_buffer->read_buffer)) { + return false; + } + + nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)titlekey_buffer->read_buffer; + u32 keypair_generation = 0; + const void *ssl_device_key = NULL; + const void *ssl_iv = NULL; + u32 key_size = 0; + + if (cal0->ext_ssl_key_crc == crc16_calc(cal0->ext_ssl_key_iv, 0x13E)) { + ssl_device_key = cal0->ext_ssl_key; + ssl_iv = cal0->ext_ssl_key_iv; + key_size = 0x120; + + // settings sysmodule manually zeroes this out below cal version 9 + keypair_generation = cal0->version <= 8 ? 0 : cal0->ext_ssl_key_ver; + } else if (cal0->ssl_key_crc == crc16_calc(cal0->ssl_key_iv, 0x11E)) { + ssl_device_key = cal0->ssl_key; + ssl_iv = cal0->ssl_key_iv; + key_size = 0x100; + } else { + EPRINTF("Crc16 error reading device key."); + return false; + } + + if (keypair_generation) { + keypair_generation--; + _get_device_key(7, keys, keys->temp_key, keypair_generation); + _derive_ssl_rsa_kek(keys, 7, keys->ssl_rsa_kek_personalized, keys->temp_key, ssl_client_cert_kek_source, ssl_client_cert_key_source); + + memcpy(keys->temp_key, keys->ssl_rsa_kek_personalized, sizeof(keys->temp_key)); + } else { + memcpy(keys->temp_key, keys->ssl_rsa_kek, sizeof(keys->temp_key)); + } + + se_aes_key_set(6, keys->temp_key, sizeof(keys->temp_key)); + se_aes_crypt_ctr(6, &keys->ssl_rsa_key, sizeof(keys->ssl_rsa_key), ssl_device_key, sizeof(keys->ssl_rsa_key), ssl_iv); + + if (key_size == 0x120) { + if (_key_exists(keys->ssl_rsa_key + 0x100)) { + EPRINTF("Invalid SSL key."); + memset(&keys->ssl_rsa_key, 0, sizeof(keys->ssl_rsa_key)); + return false; + } + } + + return true; +} + static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *titlekey_buffer, bool is_dev) { if (!_key_exists(keys->eticket_rsa_kek)) { return false; @@ -453,19 +525,11 @@ static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit gfx_printf("%kTitlekeys... \n", colors[(color_idx++) % 6]); - if (!emummc_storage_read(NX_EMMC_CALIBRATION_OFFSET / NX_EMMC_BLOCKSIZE, NX_EMMC_CALIBRATION_SIZE / NX_EMMC_BLOCKSIZE, titlekey_buffer->read_buffer)) { - EPRINTF("Unable to read PRODINFO."); + if (!_read_cal0(titlekey_buffer->read_buffer)) { return false; } - se_aes_xts_crypt(1, 0, DECRYPT, 0, titlekey_buffer->read_buffer, titlekey_buffer->read_buffer, XTS_CLUSTER_SIZE, NX_EMMC_CALIBRATION_SIZE / XTS_CLUSTER_SIZE); - nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)titlekey_buffer->read_buffer; - if (cal0->magic != MAGIC_CAL0) { - EPRINTF("Invalid CAL0 magic. Check BIS key 0."); - return false; - } - u32 keypair_generation = 0; const void *eticket_device_key = NULL; const void *eticket_iv = NULL; @@ -575,6 +639,9 @@ static bool _derive_emmc_keys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit if (!res) { EPRINTF("Unable to derive titlekeys."); } + + _derive_personalized_ssl_key(keys, titlekey_buffer); + f_mount(NULL, "bis:", 1); nx_emmc_gpt_free(&gpt); @@ -751,8 +818,10 @@ static void _save_keys_to_sd(key_derivation_ctx_t *keys, titlekey_buffer_t *titl SAVE_KEY_VAR(sd_seed, keys->sd_seed); SAVE_KEY_VAR(secure_boot_key, keys->sbk); SAVE_KEY_VAR(ssl_rsa_kek, keys->ssl_rsa_kek); + SAVE_KEY_VAR(ssl_rsa_kek_personalized, keys->ssl_rsa_kek_personalized); SAVE_KEY(ssl_rsa_kek_source_x); SAVE_KEY(ssl_rsa_kek_source_y); + _save_key("ssl_rsa_key", keys->ssl_rsa_key, RSA_2048_KEY_SIZE, text_buffer); SAVE_KEY_FAMILY_VAR(titlekek, keys->titlekek, 0); SAVE_KEY(titlekek_source); SAVE_KEY_VAR(tsec_key, keys->tsec_key); diff --git a/source/keys/keys.h b/source/keys/keys.h index 0d65681..c0440d8 100644 --- a/source/keys/keys.h +++ b/source/keys/keys.h @@ -117,6 +117,8 @@ typedef struct { eticket_rsa_kek[AES_128_KEY_SIZE], eticket_rsa_kek_personalized[AES_128_KEY_SIZE], ssl_rsa_kek[AES_128_KEY_SIZE], + ssl_rsa_kek_personalized[AES_128_KEY_SIZE], + ssl_rsa_key[RSA_2048_KEY_SIZE + 0x20], // keyblob-derived families keyblob_key[KB_FIRMWARE_VERSION_600 + 1][AES_128_KEY_SIZE], keyblob_mac_key[KB_FIRMWARE_VERSION_600 + 1][AES_128_KEY_SIZE], diff --git a/source/storage/nx_emmc_bis.h b/source/storage/nx_emmc_bis.h index 59b766e..a1cfaa6 100644 --- a/source/storage/nx_emmc_bis.h +++ b/source/storage/nx_emmc_bis.h @@ -112,8 +112,10 @@ typedef struct _nx_emmc_cal0_t u8 crc16_pad16[0x10]; u8 ecc_p33_ticket_cert[0x180]; u8 crc16_pad17[0x10]; - u8 ssl_key[0x110]; - u8 crc16_pad18[0x10]; + u8 ssl_key_iv[0x10]; + u8 ssl_key[0x100]; + u8 crc16_pad18[0xE]; + u16 ssl_key_crc; u32 ssl_cert_size; u8 crc16_pad19[0xC]; u8 ssl_cert[0x800]; @@ -170,8 +172,11 @@ typedef struct _nx_emmc_cal0_t u32 ext_ecc_rsa2048_eticket_key_ver; u8 crc16_pad38[0xA]; u16 ext_ecc_rsa2048_eticket_key_crc; - u8 ext_ssl_key[0x130]; - u8 crc16_pad39[0x10]; + u8 ext_ssl_key_iv[0x10]; + u8 ext_ssl_key[0x120]; + u32 ext_ssl_key_ver; + u8 crc16_pad39[0xA]; + u16 ext_ssl_key_crc; u8 ext_gc_key[0x130]; u8 crc16_pad40[0x10];