keys: Remove key source search, begin rewrite

This commit is contained in:
shchmue 2020-07-13 11:31:51 -06:00
parent 73fce1da86
commit 49dfca45a5
2 changed files with 119 additions and 419 deletions

View File

@ -84,6 +84,35 @@ static const u8 new_device_key_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VER
{0x14, 0xB8, 0x74, 0x12, 0xCB, 0xBD, 0x0B, 0x8F, 0x20, 0xFB, 0x30, 0xDA, 0x27, 0xE4, 0x58, 0x94}, /* 9.1.0 New Device Key Source. */
};
static const u8 fs_keys[13][0x20] = {
{0x1F, 0x12, 0x91, 0x3A, 0x4A, 0xCB, 0xF0, 0x0D, 0x4C, 0xDE, 0x3A, 0xF6, 0xD5, 0x23, 0x88, 0x2A}, // header key source
{0x5A, 0x3E, 0xD8, 0x4F, 0xDE, 0xC0, 0xD8, 0x26, 0x31, 0xF7, 0xE2, 0x5D, 0x19, 0x7B, 0xF5, 0xD0,
0x1C, 0x9B, 0x7B, 0xFA, 0xF6, 0x28, 0x18, 0x3D, 0x71, 0xF6, 0x4D, 0x73, 0xF1, 0x50, 0xB9, 0xD2}, // encrypted header key
{0x7F, 0x59, 0x97, 0x1E, 0x62, 0x9F, 0x36, 0xA1, 0x30, 0x98, 0x06, 0x6F, 0x21, 0x44, 0xC3, 0x0D}, // kak appli
{0x32, 0x7D, 0x36, 0x08, 0x5A, 0xD1, 0x75, 0x8D, 0xAB, 0x4E, 0x6F, 0xBA, 0xA5, 0x55, 0xD8, 0x82}, // kak ocean
{0x87, 0x45, 0xF1, 0xBB, 0xA6, 0xBE, 0x79, 0x64, 0x7D, 0x04, 0x8B, 0xA6, 0x7B, 0x5F, 0xDA, 0x4A}, // kak system
{0xd8, 0x9c, 0x23, 0x6e, 0xc9, 0x12, 0x4e, 0x43, 0xc8, 0x2b, 0x03, 0x87, 0x43, 0xf9, 0xcf, 0x1b}, // save mac kek source
{0xe4, 0xcd, 0x3d, 0x4a, 0xd5, 0x0f, 0x74, 0x28, 0x45, 0xa4, 0x87, 0xe5, 0xa0, 0x63, 0xea, 0x1f}, // save mac key source
{0x04, 0x89, 0xef, 0x5d, 0x32, 0x6e, 0x1a, 0x59, 0xc4, 0xb7, 0xab, 0x8c, 0x36, 0x7a, 0xab, 0x17}, // save mac sd kek source
{0x6f, 0x64, 0x59, 0x47, 0xc5, 0x61, 0x46, 0xf9, 0xff, 0xa0, 0x45, 0xd5, 0x95, 0x33, 0x29, 0x18}, // save mac sd key source
{0x37, 0x0c, 0x34, 0x5e, 0x12, 0xe4, 0xce, 0xfe, 0x21, 0xb5, 0x8e, 0x64, 0xdb, 0x52, 0xaf, 0x35,
0x4f, 0x2c, 0xa5, 0xa3, 0xfc, 0x99, 0x9a, 0x47, 0xc0, 0x3e, 0xe0, 0x04, 0x48, 0x5b, 0x2f, 0xd0}, // sd custom key source
{0x88, 0x35, 0x8d, 0x9c, 0x62, 0x9b, 0xa1, 0xa0, 0x01, 0x47, 0xdb, 0xe0, 0x62, 0x1b, 0x54, 0x32}, // sd card kek source
{0x58, 0x41, 0xa2, 0x84, 0x93, 0x5b, 0x56, 0x27, 0x8b, 0x8e, 0x1f, 0xc5, 0x18, 0xe9, 0x9f, 0x2b,
0x67, 0xc7, 0x93, 0xf0, 0xf2, 0x4f, 0xde, 0xd0, 0x75, 0x49, 0x5d, 0xca, 0x00, 0x6d, 0x99, 0xc2}, // sd nca key source
{0x24, 0x49, 0xb7, 0x22, 0x72, 0x67, 0x03, 0xa8, 0x19, 0x65, 0xe6, 0xe3, 0xea, 0x58, 0x2f, 0xdd,
0x9a, 0x95, 0x15, 0x17, 0xb1, 0x6e, 0x8f, 0x7f, 0x1f, 0x68, 0x26, 0x31, 0x52, 0xea, 0x29, 0x6a} // sd nca save source
};
static const u8 es_keys[3][0x10] = {
{0xdb, 0xa4, 0x51, 0x12, 0x4c, 0xa0, 0xa9, 0x83, 0x68, 0x14, 0xf5, 0xed, 0x95, 0xe3, 0x12, 0x5b},
{0x46, 0x6e, 0x57, 0xb7, 0x4a, 0x44, 0x7f, 0x02, 0xf3, 0x21, 0xcd, 0xe5, 0x8f, 0x2f, 0x55, 0x35},
{0x7f, 0x5b, 0xb0, 0x84, 0x7b, 0x25, 0xaa, 0x67, 0xfa, 0xc8, 0x4b, 0xe2, 0x3d, 0x7b, 0x69, 0x03}
};
static const u8 ssl_keys[0x10] = {
0x9a, 0x38, 0x3b, 0xf4, 0x31, 0xd0, 0xbd, 0x81, 0x32, 0x53, 0x4b, 0xa9, 0x64, 0x39, 0x7d, 0xe3};
static const u8 new_device_keygen_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] = {
{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. */
@ -113,66 +142,3 @@ static const u8 bis_key_source[3][0x20] = {
0x52, 0xC2, 0xE9, 0xEB, 0x09, 0xE3, 0xEE, 0x29, 0x32, 0xA1, 0x0C, 0x1F, 0xB6, 0xA0, 0x92, 0x6C,
0x4D, 0x12, 0xE1, 0x4B, 0x2A, 0x47, 0x4C, 0x1C, 0x09, 0xCB, 0x03, 0x59, 0xF0, 0x15, 0xF4, 0xE4}
};
static const u8 fs_hashes_sha256[13][0x20] = {
{ // header_kek_source
0x18, 0x88, 0xca, 0xed, 0x55, 0x51, 0xb3, 0xed, 0xe0, 0x14, 0x99, 0xe8, 0x7c, 0xe0, 0xd8, 0x68,
0x27, 0xf8, 0x08, 0x20, 0xef, 0xb2, 0x75, 0x92, 0x10, 0x55, 0xaa, 0x4e, 0x2a, 0xbd, 0xff, 0xc2},
{ // header_key_source
0x8f, 0x78, 0x3e, 0x46, 0x85, 0x2d, 0xf6, 0xbe, 0x0b, 0xa4, 0xe1, 0x92, 0x73, 0xc4, 0xad, 0xba,
0xee, 0x16, 0x38, 0x00, 0x43, 0xe1, 0xb8, 0xc4, 0x18, 0xc4, 0x08, 0x9a, 0x8b, 0xd6, 0x4a, 0xa6},
{ // key_area_key_application_source
0x04, 0xad, 0x66, 0x14, 0x3c, 0x72, 0x6b, 0x2a, 0x13, 0x9f, 0xb6, 0xb2, 0x11, 0x28, 0xb4, 0x6f,
0x56, 0xc5, 0x53, 0xb2, 0xb3, 0x88, 0x71, 0x10, 0x30, 0x42, 0x98, 0xd8, 0xd0, 0x09, 0x2d, 0x9e},
{ // key_area_key_ocean_source
0xfd, 0x43, 0x40, 0x00, 0xc8, 0xff, 0x2b, 0x26, 0xf8, 0xe9, 0xa9, 0xd2, 0xd2, 0xc1, 0x2f, 0x6b,
0xe5, 0x77, 0x3c, 0xbb, 0x9d, 0xc8, 0x63, 0x00, 0xe1, 0xbd, 0x99, 0xf8, 0xea, 0x33, 0xa4, 0x17},
{ // key_area_key_system_source
0x1f, 0x17, 0xb1, 0xfd, 0x51, 0xad, 0x1c, 0x23, 0x79, 0xb5, 0x8f, 0x15, 0x2c, 0xa4, 0x91, 0x2e,
0xc2, 0x10, 0x64, 0x41, 0xe5, 0x17, 0x22, 0xf3, 0x87, 0x00, 0xd5, 0x93, 0x7a, 0x11, 0x62, 0xf7},
{ // save_mac_kek_source
0x3D, 0xCB, 0xA1, 0x00, 0xAD, 0x4D, 0xF1, 0x54, 0x7F, 0xE3, 0xC4, 0x79, 0x5C, 0x4B, 0x22, 0x8A,
0xA9, 0x80, 0x38, 0xF0, 0x7A, 0x36, 0xF1, 0xBC, 0x14, 0x8E, 0xEA, 0xF3, 0xDC, 0xD7, 0x50, 0xF4},
{ // save_mac_key_source
0xB4, 0x7B, 0x60, 0x0B, 0x1A, 0xD3, 0x14, 0xF9, 0x41, 0x14, 0x7D, 0x8B, 0x39, 0x1D, 0x4B, 0x19,
0x87, 0xCC, 0x8C, 0x88, 0x4A, 0xC8, 0x9F, 0xFC, 0x91, 0xCA, 0xE2, 0x21, 0xC5, 0x24, 0x51, 0xF7},
{ // save_mac_sd_card_kek_source
0x60, 0x1a, 0x60, 0xbe, 0x13, 0xf6, 0x3e, 0xda, 0xec, 0xcc, 0x96, 0x7f, 0x27, 0xa3, 0xa3, 0x64,
0x65, 0xcb, 0xe8, 0xf0, 0x29, 0xf0, 0xc4, 0x14, 0xb2, 0x36, 0x6a, 0x8b, 0x8a, 0x0f, 0x13, 0x00},
{ // save_mac_sd_card_key_source
0xc2, 0x22, 0x0a, 0x38, 0xb6, 0x87, 0x2b, 0x63, 0xee, 0x77, 0xac, 0x8c, 0x28, 0x24, 0x7a, 0x44,
0x02, 0xe6, 0xdd, 0x85, 0x24, 0x8b, 0x41, 0x9a, 0x6f, 0x9b, 0x17, 0x93, 0xc0, 0x50, 0x3f, 0x21},
{ // sd_card_custom_storage_key_source
0x6b, 0x8f, 0xd2, 0x6c, 0x76, 0x5b, 0x7c, 0x67, 0x70, 0x0c, 0x68, 0x54, 0x90, 0x8e, 0xbe, 0x88,
0x45, 0xb0, 0x55, 0xa6, 0xbb, 0xbb, 0xea, 0x0c, 0x06, 0x3a, 0x85, 0x04, 0x12, 0xd4, 0xca, 0x53},
{ // sd_card_kek_source
0x6B, 0x2E, 0xD8, 0x77, 0xC2, 0xC5, 0x23, 0x34, 0xAC, 0x51, 0xE5, 0x9A, 0xBF, 0xA7, 0xEC, 0x45,
0x7F, 0x4A, 0x7D, 0x01, 0xE4, 0x62, 0x91, 0xE9, 0xF2, 0xEA, 0xA4, 0x5F, 0x01, 0x1D, 0x24, 0xB7},
{ // sd_card_nca_key_source
0x2E, 0x75, 0x1C, 0xEC, 0xF7, 0xD9, 0x3A, 0x2B, 0x95, 0x7B, 0xD5, 0xFF, 0xCB, 0x08, 0x2F, 0xD0,
0x38, 0xCC, 0x28, 0x53, 0x21, 0x9D, 0xD3, 0x09, 0x2C, 0x6D, 0xAB, 0x98, 0x38, 0xF5, 0xA7, 0xCC},
{ // sd_card_save_key_source
0xD4, 0x82, 0x74, 0x35, 0x63, 0xD3, 0xEA, 0x5D, 0xCD, 0xC3, 0xB7, 0x4E, 0x97, 0xC9, 0xAC, 0x8A,
0x34, 0x21, 0x64, 0xFA, 0x04, 0x1A, 0x1D, 0xC8, 0x0F, 0x17, 0xF6, 0xD3, 0x1E, 0x4B, 0xC0, 0x1C}
};
static const u8 es_hashes_sha256[3][0x20] = {
{ // eticket_rsa_kek
0xB7, 0x1D, 0xB2, 0x71, 0xDC, 0x33, 0x8D, 0xF3, 0x80, 0xAA, 0x2C, 0x43, 0x35, 0xEF, 0x88, 0x73,
0xB1, 0xAF, 0xD4, 0x08, 0xE8, 0x0B, 0x35, 0x82, 0xD8, 0x71, 0x9F, 0xC8, 0x1C, 0x5E, 0x51, 0x1C},
{ // eticket_rsa_kekek
0xE8, 0x96, 0x5A, 0x18, 0x7D, 0x30, 0xE5, 0x78, 0x69, 0xF5, 0x62, 0xD0, 0x43, 0x83, 0xC9, 0x96,
0xDE, 0x48, 0x7B, 0xBA, 0x57, 0x61, 0x36, 0x3D, 0x2D, 0x4D, 0x32, 0x39, 0x18, 0x66, 0xA8, 0x5C},
{ // ssl_rsa_kek_source_x
0x69, 0xA0, 0x8E, 0x62, 0xE0, 0xAE, 0x50, 0x7B, 0xB5, 0xDA, 0x0E, 0x65, 0x17, 0x9A, 0xE3, 0xBE,
0x05, 0x1F, 0xED, 0x3C, 0x49, 0x94, 0x1D, 0xF4, 0xEF, 0x29, 0x56, 0xD3, 0x6D, 0x30, 0x11, 0x0C}
};
static const u8 ssl_hashes_sha256[2][0x20] = {
{ // ssl_rsa_kek_source_x
0x69, 0xA0, 0x8E, 0x62, 0xE0, 0xAE, 0x50, 0x7B, 0xB5, 0xDA, 0x0E, 0x65, 0x17, 0x9A, 0xE3, 0xBE,
0x05, 0x1F, 0xED, 0x3C, 0x49, 0x94, 0x1D, 0xF4, 0xEF, 0x29, 0x56, 0xD3, 0x6D, 0x30, 0x11, 0x0C},
{ // ssl_rsa_kek_source_y
0x1C, 0x86, 0xF3, 0x63, 0x26, 0x54, 0x17, 0xD4, 0x99, 0x22, 0x9E, 0xB1, 0xC4, 0xAD, 0xC7, 0x47,
0x9B, 0x2A, 0x15, 0xF9, 0x31, 0x26, 0x1F, 0x31, 0xEE, 0x67, 0x76, 0xAE, 0xB4, 0xC7, 0x65, 0x42}
};

View File

@ -25,7 +25,7 @@
#include "../hos/pkg2.h"
#include "../hos/sept.h"
#include <libs/fatfs/ff.h>
#include <libs/save/save.h>
#include <libs/nx_savedata/save.h>
#include <mem/heap.h>
#include <mem/mc.h>
#include <mem/minerva.h>
@ -84,14 +84,25 @@ 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 _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed);
static void _get_device_key(u32 ks, void *out_device_key, u32 revision, const void *device_key, const void *master_key);
// nca functions
static void *_nca_process(u32 tweak_ks, u32 crypt_ks, FIL *fp, u32 key_offset, u32 len, const u8 key_area_key[3][KB_FIRMWARE_VERSION_MAX+1][0x10]);
static u32 _nca_fread_ctr(u32 ks, FIL *fp, void *buffer, u32 offset, u32 len, u8 *ctr);
static void _update_ctr(u8 *ctr, u32 ofs);
// titlekey functions
static bool _test_key_pair(const void *E, const void *D, const void *N);
static void _mgf1_xor(void *masked, u32 masked_size, const void *seed, u32 seed_size);
static inline const u8 *_find_tsec_fw(const u8 *pkg1) {
const u32 tsec_fw_align = 0x100;
const u32 tsec_fw_first_instruction = 0xCF42004D;
for (const u32 *pos = (const u32 *)pkg1; (u8 *)pos < pkg1 + PKG1_MAX_SIZE; pos += tsec_fw_align / sizeof(u32))
if (*pos == tsec_fw_first_instruction)
return (const u8 *)pos;
return NULL;
}
static inline u32 _get_tsec_fw_size(tsec_key_data_t *key_data) {
return 0x100 + key_data->blob0_size + key_data->blob1_size + key_data->blob2_size + key_data->blob3_size + key_data->blob4_size;
}
void dump_keys() {
u8 temp_key[0x10],
bis_key[4][0x20] = {0},
@ -99,14 +110,11 @@ void dump_keys() {
device_key_4x[0x10] = {0},
sd_seed[0x10] = {0},
// FS-related keys
fs_keys[13][0x20] = {0},
header_key[0x20] = {0},
save_mac_key[0x10] = {0},
// other sysmodule sources
es_keys[3][0x10] = {0},
// other sysmodule keys
eticket_rsa_kek[0x10] = {0},
eticket_rsa_kek_personalized[0x10] = {0},
ssl_keys[0x10] = {0},
ssl_rsa_kek[0x10] = {0},
// keyblob-derived families
keyblob[KB_FIRMWARE_VERSION_600+1][0x90] = {0},
@ -147,12 +155,12 @@ void dump_keys() {
TPRINTFARGS("%kMMC init... ", colors[(color_idx++) % 6]);
// Read package1.
u8 *pkg1 = (u8 *)malloc(0x40000);
u8 *pkg1 = (u8 *)malloc(PKG1_MAX_SIZE);
if (!emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0)) {
EPRINTF("Unable to set partition.");
goto out_wait;
}
if (!emummc_storage_read(&emmc_storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1)) {
if (!emummc_storage_read(&emmc_storage, PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1)) {
EPRINTF("Unable to read pkg1.");
goto out_wait;
}
@ -162,32 +170,23 @@ void dump_keys() {
goto out_wait;
}
bool pkg1_not_100 = memcmp(pkg1_id->id, "2016", 4);
bool found_tsec_fw = false;
for (const u32 *pos = (const u32 *)pkg1; (u8 *)pos < pkg1 + 0x40000; pos += 0x100 / sizeof(u32)) {
if (*pos == 0xCF42004D) {
tsec_ctxt.fw = (u8 *)pos;
found_tsec_fw = true;
break;
}
}
if (!found_tsec_fw) {
tsec_ctxt.fw = _find_tsec_fw(pkg1);
if (!tsec_ctxt.fw) {
EPRINTF("Unable to locate TSEC firmware.");
goto out_wait;
}
minerva_periodic_training();
tsec_key_data_t *key_data = (tsec_key_data_t *)(tsec_ctxt.fw + TSEC_KEY_DATA_ADDR);
tsec_ctxt.pkg1 = pkg1;
tsec_ctxt.size = 0x100 + key_data->blob0_size + key_data->blob1_size + key_data->blob2_size + key_data->blob3_size + key_data->blob4_size;
u32 MAX_KEY = 6;
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_620) {
MAX_KEY = pkg1_id->kb + 1;
tsec_ctxt.size = _get_tsec_fw_size((tsec_key_data_t *)(tsec_ctxt.fw + TSEC_KEY_DATA_OFFSET));
if (tsec_ctxt.size > PKG1_MAX_SIZE) {
EPRINTF("Unexpected TSEC firmware size.");
goto out_wait;
}
u32 max_derivable_key_index = pkg1_id->kb >= KB_FIRMWARE_VERSION_620 ? pkg1_id->kb + 1 : 6;
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700) {
sd_mount();
if (!f_stat("sd:/sept/payload.bak", NULL)) {
@ -360,12 +359,10 @@ get_tsec: ;
key_set(ks, wrapped_key), block_ecb(ks, 0, key, source) -> final key in key
*/
minerva_periodic_training();
u32 key_generation = 0;
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_500) {
key_generation = fuse_read_odm_keygen_rev();
if (key_generation)
key_generation--;
}
u32 key_generation = fuse_read_odm_keygen_rev();
if (key_generation)
key_generation--;
if (_key_exists(device_key)) {
if (key_generation) {
_get_device_key(8, temp_key, key_generation, device_key_4x, master_key[0]);
@ -384,127 +381,6 @@ get_tsec: ;
memcpy(bis_key[3], bis_key[2], 0x20);
}
// Dump package2.
u8 *pkg2 = NULL;
pkg2_kip1_info_t *ki = NULL;
if (!emummc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP)) {
EPRINTF("Unable to set partition.");
goto out_wait;
}
// Parse eMMC GPT.
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &emmc_storage);
// Find package2 partition.
emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main");
if (!pkg2_part) {
EPRINTF("Unable to locate Package2.");
goto pkg2_done;
}
// Read in package2 header and get package2 real size.
u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
nx_emmc_part_read(&emmc_storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
u32 *hdr_pkg2_raw = (u32 *)(tmp + 0x100);
u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3];
free(tmp);
if (pkg2_size > 0x7FC000) {
EPRINTF("Invalid Package2 header.");
goto pkg2_done;
}
// Read in package2.
u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE);
pkg2 = malloc(pkg2_size_aligned);
nx_emmc_part_read(&emmc_storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, pkg2_size_aligned / NX_EMMC_BLOCKSIZE, pkg2);
// Decrypt package2 and parse KIP1 blobs in INI1 section. Try all available key generations in case of pkg1/pkg2 mismatch.
minerva_periodic_training();
pkg2_hdr_t *pkg2_hdr;
pkg2_hdr_t hdr;
u32 pkg2_kb;
for (pkg2_kb = 0; pkg2_kb < MAX_KEY; pkg2_kb++) {
se_aes_key_set(8, master_key[pkg2_kb], 0x10);
se_aes_unwrap_key(8, 8, package2_key_source);
memcpy(&hdr, pkg2 + 0x100, sizeof(pkg2_hdr_t));
se_aes_crypt_ctr(8, &hdr, sizeof(pkg2_hdr_t), &hdr, sizeof(pkg2_hdr_t), &hdr);
if (hdr.magic == PKG2_MAGIC)
break;
}
if (pkg2_kb == MAX_KEY) {
EPRINTF("Unable to derive Package2 key.");
goto pkg2_done;
} else if (pkg2_kb != pkg1_id->kb)
EPRINTFARGS("Warning! Package1-Package2 mismatch: %d, %d", pkg1_id->kb, pkg2_kb);
pkg2_hdr = pkg2_decrypt(pkg2);
if (!pkg2_hdr) {
EPRINTF("Unable to decrypt Package2.");
goto pkg2_done;
}
TPRINTFARGS("%kDecrypt pkg2... ", colors[(color_idx++) % 6]);
LIST_INIT(kip1_info);
bool new_pkg2;
if (!pkg2_parse_kips(&kip1_info, pkg2_hdr, &new_pkg2)) {
EPRINTF("Unable to locate INI1.");
goto pkg2_done;
}
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki_tmp, &kip1_info, link) {
if(ki_tmp->kip1->tid == 0x0100000000000000ULL) {
ki = malloc(sizeof(pkg2_kip1_info_t));
memcpy(ki, ki_tmp, sizeof(pkg2_kip1_info_t));
break;
}
}
LIST_FOREACH_SAFE(iter, &kip1_info)
free(CONTAINER_OF(iter, pkg2_kip1_info_t, link));
if (!ki) {
EPRINTF("Unable to parse INI1.");
goto pkg2_done;
}
pkg2_decompress_kip(ki, 2 | 4); // we only need .rodata and .data
TPRINTFARGS("%kDecompress FS...", colors[(color_idx++) % 6]);
u8 hash_index = 0;
const u8 key_lengths[13] = {0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x20, 0x20};
if (!pkg1_not_100) {
// 1.0.0 doesn't have SD keys at all and the first key isn't aligned with the rest
memcpy(fs_keys[FS_KEY_AREA_KEY_APPLI_SOURCE], ki->kip1->data + ki->kip1->sections[0].size_comp + 0x1ae0e, 0x10);
hash_index = 1;
}
u8 temp_hash[0x20];
for (u32 i = ki->kip1->sections[0].size_comp + pkg1_id->key_info.start_offset; i < ki->size - 0x20; ) {
minerva_periodic_training();
se_calc_sha256(temp_hash, ki->kip1->data + i, key_lengths[pkg1_id->key_info.hash_order[hash_index]]);
if (!memcmp(temp_hash, fs_hashes_sha256[pkg1_id->key_info.hash_order[hash_index]], 0x20)) {
memcpy(fs_keys[pkg1_id->key_info.hash_order[hash_index]], ki->kip1->data + i, key_lengths[pkg1_id->key_info.hash_order[hash_index]]);
i += key_lengths[pkg1_id->key_info.hash_order[hash_index]];
if (hash_index == pkg1_id->key_info.hash_max - 1) {
if (pkg1_id->key_info.hks_offset_is_from_end)
i = ki->size - pkg1_id->key_info.hks_offset;
else
i = ki->size - (ki->kip1->sections[2].size_decomp - pkg1_id->key_info.hks_offset);
} else if (hash_index == pkg1_id->key_info.hash_max) {
break;
}
hash_index++;
} else {
i += pkg1_id->key_info.alignment;
}
}
pkg2_done:
if (ki) {
free(ki);
}
free(pkg2);
u8 *rights_ids = NULL, *titlekeys = NULL;
TPRINTFARGS("%kFS keys... ", colors[(color_idx++) % 6]);
@ -520,10 +396,10 @@ pkg2_done:
se_aes_crypt_block_ecb(8, 0, save_mac_key, fs_keys[FS_SAVE_MAC_KEY_SOURCE]);
}
if (_key_exists(master_key[MAX_KEY])) {
MAX_KEY = KB_FIRMWARE_VERSION_MAX + 1;
if (_key_exists(master_key[max_derivable_key_index])) {
max_derivable_key_index = KB_FIRMWARE_VERSION_MAX + 1;
}
for (u32 i = 0; i < MAX_KEY; i++) {
for (u32 i = 0; i < max_derivable_key_index; i++) {
if (!_key_exists(master_key[i]))
continue;
if (_key_exists(fs_keys[FS_KEY_AREA_KEY_APPLI_SOURCE]) && _key_exists(fs_keys[FS_KEY_AREA_KEY_OCEAN_SOURCE]) && _key_exists(fs_keys[FS_KEY_AREA_KEY_SYSTE_SOURCE])) {
@ -543,6 +419,25 @@ pkg2_done:
goto key_output;
}
FILINFO fno;
FIL fp;
save_ctx_t *save_ctx = NULL;
bool save_process_success = false;
u32 read_bytes = 0;
// derive eticket_rsa_kek and ssl_rsa_kek
if (_key_exists(master_key[0])) {
for (u32 i = 0; i < 0x10; i++)
temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_03[i];
_generate_kek(7, es_keys[1], master_key[0], temp_key, NULL);
se_aes_crypt_block_ecb(7, 0, eticket_rsa_kek, es_keys[0]);
for (u32 i = 0; i < 0x10; i++)
temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_01[i];
_generate_kek(7, es_keys[2], master_key[0], temp_key, NULL);
se_aes_crypt_block_ecb(7, 0, ssl_rsa_kek, ssl_keys);
}
// Set BIS keys.
// PRODINFO/PRODINFOF
se_aes_key_set(0, bis_key[0] + 0x00, 0x10);
@ -558,6 +453,14 @@ pkg2_done:
se_aes_key_set(8, header_key + 0x00, 0x10);
se_aes_key_set(9, header_key + 0x10, 0x10);
if (!emummc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP)) {
EPRINTF("Unable to set partition.");
goto out_wait;
}
// Parse eMMC GPT.
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &emmc_storage);
emmc_part_t *system_part = nx_emmc_part_find(&gpt, "SYSTEM");
if (!system_part) {
EPRINTF("Unable to locate System partition.");
@ -571,120 +474,6 @@ pkg2_done:
goto key_output;
}
DIR dir;
FILINFO fno;
FIL fp;
save_ctx_t *save_ctx = NULL;
bool save_process_success = false;
// sysmodule NCAs only ever have one section (exefs) so 0x600 is sufficient
u8 *dec_header = (u8*)malloc(0x600);
char path[100] = "bis:/Contents/registered";
u32 titles_found = 0, read_bytes = 0, title_limit = pkg1_not_100 ? 2 : 1;
u8 *temp_file = NULL;
if (f_opendir(&dir, path)) {
EPRINTF("Unable to open System:/Contents/registered.");
goto dismount;
}
gfx_printf("%kSector cache... ", colors[(color_idx++) % 6]);
// prepopulate /Contents/registered in decrypted sector cache
while (!f_readdir(&dir, &fno) && fno.fname[0]) {}
f_closedir(&dir);
TPRINTF();
if (pkg1_not_100) {
gfx_printf("%kES & SSL keys...", colors[(color_idx++) % 6]);
} else {
gfx_printf("%kSSL keys... ", colors[(color_idx++) % 6]);
}
if (f_opendir(&dir, path)) {
EPRINTF("Unable to open System:/Contents/registered.");
goto dismount;
}
path[24] = '/';
while (!f_readdir(&dir, &fno) && fno.fname[0] && titles_found < title_limit) {
minerva_periodic_training();
memcpy(path + 25, fno.fname, 36);
path[61] = 0;
if (fno.fattrib & AM_DIR)
memcpy(path + 61, "/00", 4);
if (f_open(&fp, path, FA_READ | FA_OPEN_EXISTING)) continue;
if (f_lseek(&fp, 0x200) || f_read(&fp, dec_header, 0x20, &read_bytes) || read_bytes != 0x20) {
f_close(&fp);
continue;
}
se_aes_xts_crypt_sec(9, 8, 0, 1, dec_header + 0x200, dec_header, 0x20);
// es doesn't contain es key sources on 1.0.0
if (pkg1_not_100 && _read_le_u32(dec_header, 0x210) == 0x33 && dec_header[0x205] == 0) {
u8 hash_order[3] = {0, 1, 2};
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_500) {
hash_order[0] = 1;
hash_order[1] = 0;
}
hash_index = 0;
// decrypt only what is needed to locate needed keys
temp_file = (u8*)_nca_process(9, 8, &fp, pkg1_id->key_info.es_offset, 0xc0, key_area_key);
for (u32 i = 0; i <= 0xb0; ) {
se_calc_sha256(temp_hash, temp_file + i, 0x10);
if (!memcmp(temp_hash, es_hashes_sha256[hash_order[hash_index]], 0x10)) {
memcpy(es_keys[hash_order[hash_index]], temp_file + i, 0x10);
hash_index++;
if (hash_index == 3)
break;
i += 0x10;
} else {
i++;
}
}
free(temp_file);
temp_file = NULL;
titles_found++;
} else if (_read_le_u32(dec_header, 0x210) == 0x24 && dec_header[0x205] == 0) {
temp_file = (u8*)_nca_process(9, 8, &fp, pkg1_id->key_info.ssl_offset, 0x70, key_area_key);
for (u32 i = 0; i <= 0x60; i++) {
se_calc_sha256(temp_hash, temp_file + i, 0x10);
if (!memcmp(temp_hash, ssl_hashes_sha256[1], 0x10)) {
memcpy(ssl_keys, temp_file + i, 0x10);
// only get ssl_rsa_kek_source_x from SSL on 1.0.0
// we get it from ES on every other firmware
// and it's located oddly distant from ssl_rsa_kek_source_y on >= 6.0.0
if (!pkg1_not_100) {
se_calc_sha256(temp_hash, temp_file + i + 0x10, 0x10);
if (!memcmp(temp_hash, ssl_hashes_sha256[0], 0x10))
memcpy(es_keys[2], temp_file + i + 0x10, 0x10);
}
break;
}
}
free(temp_file);
temp_file = NULL;
titles_found++;
}
f_close(&fp);
}
f_closedir(&dir);
free(dec_header);
// derive eticket_rsa_kek and ssl_rsa_kek
if (_key_exists(es_keys[0]) && _key_exists(es_keys[1]) && _key_exists(master_key[0])) {
for (u32 i = 0; i < 0x10; i++)
temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_03[i];
_generate_kek(7, es_keys[1], master_key[0], temp_key, NULL);
se_aes_crypt_block_ecb(7, 0, eticket_rsa_kek, es_keys[0]);
}
if (_key_exists(ssl_keys) && _key_exists(es_keys[2]) && _key_exists(master_key[0])) {
for (u32 i = 0; i < 0x10; i++)
temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_01[i];
_generate_kek(7, es_keys[2], master_key[0], temp_key, NULL);
se_aes_crypt_block_ecb(7, 0, ssl_rsa_kek, ssl_keys);
}
TPRINTF();
char private_path[200] = "sd:/";
if (emu_cfg.nintendo_path && (emu_cfg.enabled || !h_cfg.emummc_force_disable)) {
strcat(private_path, emu_cfg.nintendo_path);
@ -735,7 +524,7 @@ get_titlekeys:
0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55};
u32 buf_size = 0x40000;
u32 buf_size = 0x4000;
u8 *buffer = (u8 *)MIXD_BUF_ALIGNED;
u8 keypair[0x230] = {0};
@ -824,14 +613,17 @@ get_titlekeys:
goto dismount;
}
while (br == buf_size && offset < ticket_file.size) {
if (!save_data_file_read(&ticket_file, &br, offset, buffer, buf_size) || buffer[0] == 0)
bool terminator_reached = false;
while (offset < ticket_file.size && !terminator_reached) {
if (!save_data_file_read(&ticket_file, &br, offset, buffer, buf_size) || buffer[0] == 0 || br != buf_size)
break;
offset += br;
minerva_periodic_training();
for (u32 j = 0; j < buf_size; j += 0x20) {
if (buffer[j] == 0xff && buffer[j+1] == 0xff && buffer[j+2] == 0xff && buffer[j+3] == 0xff)
if (buffer[j] == 0xff && buffer[j+1] == 0xff && buffer[j+2] == 0xff && buffer[j+3] == 0xff) {
terminator_reached = true;
break;
}
file_tkey_count++;
}
}
@ -843,10 +635,9 @@ get_titlekeys:
}
offset = 0;
br = buf_size;
while (br == buf_size && offset < ticket_file.size) {
if (!save_data_file_read(&ticket_file, &br, offset, buffer, buf_size) || buffer[0] == 0)
terminator_reached = false;
while (offset < ticket_file.size && !terminator_reached) {
if (!save_data_file_read(&ticket_file, &br, offset, buffer, buf_size) || buffer[0] == 0 || br != buf_size)
break;
offset += br;
for (u32 j = 0; j < buf_size; j += 0x400) {
@ -861,6 +652,7 @@ get_titlekeys:
memcpy(titlekeys + 0x10 * _titlekey_count, buffer + j + 0x180, 0x10);
_titlekey_count++;
} else {
terminator_reached = true;
break;
}
}
@ -902,15 +694,17 @@ get_titlekeys:
offset = 0;
file_tkey_count = 0;
br = buf_size;
while (br == buf_size && offset < ticket_file.size) {
if (!save_data_file_read(&ticket_file, &br, offset, buffer, buf_size) || buffer[0] == 0)
terminator_reached = false;
while (offset < ticket_file.size && !terminator_reached) {
if (!save_data_file_read(&ticket_file, &br, offset, buffer, buf_size) || buffer[0] == 0 || br != buf_size)
break;
offset += br;
minerva_periodic_training();
for (u32 j = 0; j < buf_size; j += 0x20) {
if (buffer[j] == 0xff && buffer[j+1] == 0xff && buffer[j+2] == 0xff && buffer[j+3] == 0xff)
if (buffer[j] == 0xff && buffer[j+1] == 0xff && buffer[j+2] == 0xff && buffer[j+3] == 0xff) {
terminator_reached = true;
break;
}
file_tkey_count++;
}
}
@ -924,9 +718,9 @@ get_titlekeys:
offset = 0;
pct = 0;
last_pct = 0;
br = buf_size;
while (br == buf_size && offset < ticket_file.size) {
if (!save_data_file_read(&ticket_file, &br, offset, buffer, buf_size) || buffer[0] == 0)
terminator_reached = false;
while (offset < ticket_file.size && !terminator_reached) {
if (!save_data_file_read(&ticket_file, &br, offset, buffer, buf_size) || buffer[0] == 0 || br != buf_size)
break;
offset += br;
for (u32 j = 0; j < buf_size; j += 0x400) {
@ -950,6 +744,7 @@ get_titlekeys:
memcpy(titlekeys + 0x10 * _titlekey_count, db + 0xcf, 0x10);
_titlekey_count++;
} else {
terminator_reached = true;
break;
}
}
@ -994,23 +789,23 @@ key_output: ;
SAVE_KEY("header_kek_source", fs_keys[FS_HEADER_KEK_SOURCE], 0x10);
SAVE_KEY("header_key", header_key, 0x20);
SAVE_KEY("header_key_source", fs_keys[FS_HEADER_KEY_SOURCE], 0x20);
SAVE_KEY_FAMILY("key_area_key_application", key_area_key[0], 0, MAX_KEY, 0x10);
SAVE_KEY_FAMILY("key_area_key_application", key_area_key[0], 0, max_derivable_key_index, 0x10);
SAVE_KEY("key_area_key_application_source", fs_keys[FS_KEY_AREA_KEY_APPLI_SOURCE], 0x10);
SAVE_KEY_FAMILY("key_area_key_ocean", key_area_key[1], 0, MAX_KEY, 0x10);
SAVE_KEY_FAMILY("key_area_key_ocean", key_area_key[1], 0, max_derivable_key_index, 0x10);
SAVE_KEY("key_area_key_ocean_source", fs_keys[FS_KEY_AREA_KEY_OCEAN_SOURCE], 0x10);
SAVE_KEY_FAMILY("key_area_key_system", key_area_key[2], 0, MAX_KEY, 0x10);
SAVE_KEY_FAMILY("key_area_key_system", key_area_key[2], 0, max_derivable_key_index, 0x10);
SAVE_KEY("key_area_key_system_source", fs_keys[FS_KEY_AREA_KEY_SYSTE_SOURCE], 0x10);
SAVE_KEY_FAMILY("keyblob", keyblob, 0, 6, 0x90);
SAVE_KEY_FAMILY("keyblob_key", keyblob_key, 0, 6, 0x10);
SAVE_KEY_FAMILY("keyblob_key_source", keyblob_key_source, 0, 6, 0x10);
SAVE_KEY_FAMILY("keyblob_mac_key", keyblob_mac_key, 0, 6, 0x10);
SAVE_KEY("keyblob_mac_key_source", keyblob_mac_key_source, 0x10);
SAVE_KEY_FAMILY("master_kek", master_kek, 0, MAX_KEY, 0x10);
SAVE_KEY_FAMILY("master_kek", master_kek, 0, max_derivable_key_index, 0x10);
SAVE_KEY_FAMILY("master_kek_source", master_kek_sources, KB_FIRMWARE_VERSION_620, sizeof(master_kek_sources) / 0x10, 0x10);
SAVE_KEY_FAMILY("master_key", master_key, 0, MAX_KEY, 0x10);
SAVE_KEY_FAMILY("master_key", master_key, 0, max_derivable_key_index, 0x10);
SAVE_KEY("master_key_source", master_key_source, 0x10);
SAVE_KEY_FAMILY("package1_key", package1_key, 0, 6, 0x10);
SAVE_KEY_FAMILY("package2_key", package2_key, 0, MAX_KEY, 0x10);
SAVE_KEY_FAMILY("package2_key", package2_key, 0, max_derivable_key_index, 0x10);
SAVE_KEY("package2_key_source", package2_key_source, 0x10);
SAVE_KEY("per_console_key_source", per_console_key_source, 0x10);
SAVE_KEY("retail_specific_aes_key_source", retail_specific_aes_key_source, 0x10);
@ -1034,7 +829,7 @@ key_output: ;
SAVE_KEY("ssl_rsa_kek", ssl_rsa_kek, 0x10);
SAVE_KEY("ssl_rsa_kek_source_x", es_keys[2], 0x10);
SAVE_KEY("ssl_rsa_kek_source_y", ssl_keys, 0x10);
SAVE_KEY_FAMILY("titlekek", titlekek, 0, MAX_KEY, 0x10);
SAVE_KEY_FAMILY("titlekek", titlekek, 0, max_derivable_key_index, 0x10);
SAVE_KEY("titlekek_source", titlekek_source, 0x10);
SAVE_KEY("tsec_key", tsec_keys, 0x10);
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
@ -1045,7 +840,7 @@ key_output: ;
end_time = get_tmr_us();
gfx_printf("\n%k Found %d keys.\n\n", colors[(color_idx++) % 6], _key_count);
gfx_printf("%kLockpick totally done in %d us\n\n", colors[(color_idx++) % 6], end_time - begin_time);
gfx_printf("%kFound through master_key_%02x.\n\n", colors[(color_idx++) % 6], MAX_KEY - 1);
gfx_printf("%kFound through master_key_%02x.\n\n", colors[(color_idx++) % 6], max_derivable_key_index - 1);
f_mkdir("sd:/switch");
char keyfile_path[30] = "sd:/switch/";
@ -1132,67 +927,6 @@ static void _get_device_key(u32 ks, void *out_device_key, u32 revision, const vo
se_aes_crypt_ecb(ks, 0, out_device_key, 0x10, temp_key, 0x10);
}
static void *_nca_process(u32 tweak_ks, u32 crypt_ks, FIL *fp, u32 key_offset, u32 len, const u8 key_area_key[3][KB_FIRMWARE_VERSION_MAX+1][0x10]) {
u32 read_bytes = 0, crypt_offset, read_size, num_files, string_table_size, rodata_offset;
u8 *temp_file = (u8*)malloc(0x400),
ctr[0x10] = {0};
if (f_lseek(fp, 0x200) || f_read(fp, temp_file, 0x400, &read_bytes) || read_bytes != 0x400) {
free(temp_file);
return NULL;
}
se_aes_xts_crypt(tweak_ks, crypt_ks, 0, 1, temp_file, temp_file, 0x200, 2);
// both 1.x and 2.x use master_key_00
temp_file[0x20] -= temp_file[0x20] ? 1 : 0;
// decrypt key area and load decrypted key area key
se_aes_key_set(7, key_area_key[temp_file[7]][temp_file[0x20]], 0x10);
se_aes_crypt_block_ecb(7, 0, temp_file + 0x120, temp_file + 0x120);
se_aes_key_set(6, temp_file + 0x120, 0x10);
for (u32 i = 0; i < 8; i++)
ctr[i] = temp_file[0x347 - i];
crypt_offset = _read_le_u32(temp_file, 0x40) * 0x200 + _read_le_u32(temp_file, 0x240);
read_size = 0x10;
_nca_fread_ctr(6, fp, temp_file, crypt_offset, read_size, ctr);
num_files = _read_le_u32(temp_file, 4);
string_table_size = _read_le_u32(temp_file, 8);
if (!memcmp(temp_file + 0x10 + num_files * 0x18, "main.npdm", 9))
crypt_offset += _read_le_u32(temp_file, 0x18);
crypt_offset += 0x10 + num_files * 0x18 + string_table_size;
read_size = 0x40;
_nca_fread_ctr(6, fp, temp_file, crypt_offset, read_size, ctr);
rodata_offset = _read_le_u32(temp_file, 0x20);
void *buf = malloc(len);
_nca_fread_ctr(6, fp, buf, crypt_offset + rodata_offset + key_offset, len, ctr);
free(temp_file);
return buf;
}
static u32 _nca_fread_ctr(u32 ks, FIL *fp, void *buffer, u32 offset, u32 len, u8 *ctr) {
u32 br;
if (f_lseek(fp, offset) || f_read(fp, buffer, len, &br) || br != len)
return 0;
_update_ctr(ctr, offset);
if (offset % 0x10) {
u8 *temp = (u8*)malloc(ALIGN(br + offset % 0x10, 0x10));
memcpy(temp + offset % 0x10, buffer, br);
se_aes_crypt_ctr(ks, temp, ALIGN(br + offset % 0x10, 0x10), temp, ALIGN(br + offset % 0x10, 0x10), ctr);
memcpy(buffer, temp + offset % 0x10, br);
free(temp);
return br;
}
se_aes_crypt_ctr(ks, buffer, br, buffer, br, ctr);
return br;
}
static void _update_ctr(u8 *ctr, u32 ofs) {
ofs >>= 4;
for (u32 i = 0; i < 4; i++, ofs >>= 8)
ctr[0x10-i-1] = (u8)(ofs & 0xff);
}
static bool _test_key_pair(const void *E, const void *D, const void *N) {
u8 X[0x100] = {0}, Y[0x100] = {0}, Z[0x100] = {0};