2019-03-04 18:05:42 -05:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2019 shchmue
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms and conditions of the GNU General Public License,
|
|
|
|
* version 2, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "keys.h"
|
2019-09-16 22:18:41 -06:00
|
|
|
|
|
|
|
#include "../config/config.h"
|
2019-03-04 18:05:42 -05:00
|
|
|
#include "../gfx/di.h"
|
|
|
|
#include "../gfx/gfx.h"
|
2019-09-17 09:51:30 -06:00
|
|
|
#include "../gfx/tui.h"
|
2019-03-04 18:05:42 -05:00
|
|
|
#include "../hos/pkg1.h"
|
|
|
|
#include "../hos/pkg2.h"
|
|
|
|
#include "../hos/sept.h"
|
2019-09-25 00:49:22 +02:00
|
|
|
#include "../libs/fatfs/ff.h"
|
2019-03-04 18:05:42 -05:00
|
|
|
#include "../mem/heap.h"
|
2019-04-19 13:00:10 -04:00
|
|
|
#include "../mem/mc.h"
|
2019-04-18 11:02:15 -04:00
|
|
|
#include "../mem/sdram.h"
|
2019-03-04 18:05:42 -05:00
|
|
|
#include "../sec/se.h"
|
|
|
|
#include "../sec/se_t210.h"
|
|
|
|
#include "../sec/tsec.h"
|
|
|
|
#include "../soc/fuse.h"
|
|
|
|
#include "../soc/smmu.h"
|
|
|
|
#include "../soc/t210.h"
|
2019-09-17 09:51:30 -06:00
|
|
|
#include "../storage/emummc.h"
|
2019-03-04 18:05:42 -05:00
|
|
|
#include "../storage/nx_emmc.h"
|
|
|
|
#include "../storage/sdmmc.h"
|
|
|
|
#include "../utils/btn.h"
|
|
|
|
#include "../utils/list.h"
|
2019-05-12 13:15:23 -04:00
|
|
|
#include "../utils/sprintf.h"
|
2019-03-04 18:05:42 -05:00
|
|
|
#include "../utils/util.h"
|
|
|
|
|
2019-05-12 13:15:23 -04:00
|
|
|
#include "key_sources.inl"
|
2019-09-24 15:18:28 +02:00
|
|
|
|
2019-09-23 16:12:04 +02:00
|
|
|
#include "../libs/fatfs/diskio.h"
|
2019-03-04 18:05:42 -05:00
|
|
|
#include <string.h>
|
2019-09-24 09:41:22 +02:00
|
|
|
#include "sha256.h"
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-25 17:48:19 +02:00
|
|
|
#include "aes_xts.h"
|
|
|
|
|
2019-03-04 18:05:42 -05:00
|
|
|
extern bool sd_mount();
|
|
|
|
extern void sd_unmount();
|
2019-09-29 00:18:17 +02:00
|
|
|
extern int sd_save_to_file(void *buf, u32 size, const char *filename);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-16 22:18:41 -06:00
|
|
|
extern hekate_config h_cfg;
|
|
|
|
|
2019-03-04 18:05:42 -05:00
|
|
|
u32 _key_count = 0;
|
|
|
|
sdmmc_storage_t storage;
|
|
|
|
emmc_part_t *system_part;
|
2019-09-23 21:40:31 +02:00
|
|
|
emmc_part_t *prodinfo_part;
|
2019-09-16 22:18:41 -06:00
|
|
|
u32 start_time, end_time;
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
#define TPRINTF(text) \
|
|
|
|
end_time = get_tmr_us(); \
|
|
|
|
gfx_printf(text " done in %d us\n", end_time - start_time); \
|
2019-09-16 22:18:41 -06:00
|
|
|
start_time = get_tmr_us()
|
2019-09-29 00:18:17 +02:00
|
|
|
#define TPRINTFARGS(text, args...) \
|
|
|
|
end_time = get_tmr_us(); \
|
|
|
|
gfx_printf(text " done in %d us\n", args, end_time - start_time); \
|
2019-09-16 22:18:41 -06:00
|
|
|
start_time = get_tmr_us()
|
2019-05-12 14:05:58 -04:00
|
|
|
#define SAVE_KEY(name, src, len) _save_key(name, src, len, text_buffer)
|
|
|
|
#define SAVE_KEY_FAMILY(name, src, count, len) _save_key_family(name, src, count, len, text_buffer)
|
2019-03-04 18:05:42 -05:00
|
|
|
|
|
|
|
static u8 temp_key[0x10],
|
2019-09-29 00:18:17 +02:00
|
|
|
bis_key[4][0x20] = {0},
|
|
|
|
device_key[0x10] = {0},
|
|
|
|
new_device_key[0x10] = {0},
|
|
|
|
keyblob[KB_FIRMWARE_VERSION_600 + 1][0x90] = {0},
|
|
|
|
keyblob_key[KB_FIRMWARE_VERSION_600 + 1][0x10] = {0},
|
|
|
|
keyblob_mac_key[KB_FIRMWARE_VERSION_600 + 1][0x10] = {0},
|
|
|
|
package1_key[KB_FIRMWARE_VERSION_600 + 1][0x10] = {0},
|
|
|
|
// master key-derived families
|
|
|
|
master_kek[KB_FIRMWARE_VERSION_MAX + 1][0x10] = {0},
|
|
|
|
master_key[KB_FIRMWARE_VERSION_MAX + 1][0x10] = {0};
|
2019-03-04 18:05:42 -05:00
|
|
|
|
|
|
|
// key functions
|
2019-09-29 00:18:17 +02:00
|
|
|
static bool _key_exists(const void *data) { return memcmp(data, zeros, 0x10); };
|
|
|
|
static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed);
|
|
|
|
|
|
|
|
bool dump_keys()
|
|
|
|
{
|
2019-03-04 18:05:42 -05:00
|
|
|
display_backlight_brightness(100, 1000);
|
2019-09-17 09:51:30 -06:00
|
|
|
gfx_clear_partial_grey(0x1B, 0, 1256);
|
2019-04-18 12:47:34 -04:00
|
|
|
gfx_con_setpos(0, 0);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
gfx_print_header();
|
|
|
|
|
|
|
|
// gfx_printf("[%kLo%kck%kpi%kck%k_R%kCM%k v%d.%d.%d%k]\n\n",
|
|
|
|
// colors[0], colors[1], colors[2], colors[3], colors[4], colors[5], 0xFFFF00FF, LP_VER_MJ, LP_VER_MN, LP_VER_BF, 0xFFCCCCCC);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-16 22:18:41 -06:00
|
|
|
start_time = get_tmr_us();
|
2019-09-29 00:18:17 +02:00
|
|
|
//u32 begin_time = get_tmr_us();
|
2019-09-16 22:18:41 -06:00
|
|
|
u32 retries = 0;
|
|
|
|
u32 color_idx = 0;
|
2019-03-04 18:05:42 -05:00
|
|
|
|
|
|
|
tsec_ctxt_t tsec_ctxt;
|
|
|
|
sdmmc_t sdmmc;
|
|
|
|
|
2019-09-17 09:51:30 -06:00
|
|
|
emummc_storage_init_mmc(&storage, &sdmmc);
|
2019-09-16 22:18:41 -06:00
|
|
|
TPRINTFARGS("%kMMC init... ", colors[(color_idx++) % 6]);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
|
|
|
// Read package1.
|
|
|
|
u8 *pkg1 = (u8 *)malloc(0x40000);
|
2019-09-17 09:51:30 -06:00
|
|
|
emummc_storage_set_mmc_partition(&storage, 1);
|
|
|
|
emummc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
2019-03-04 18:05:42 -05:00
|
|
|
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
2019-09-29 00:18:17 +02:00
|
|
|
if (!pkg1_id)
|
|
|
|
{
|
2019-03-04 18:05:42 -05:00
|
|
|
EPRINTF("Unknown pkg1 version.");
|
2019-09-29 00:18:17 +02:00
|
|
|
return false;
|
2019-03-04 18:05:42 -05:00
|
|
|
}
|
|
|
|
|
2019-05-11 21:03:24 -04:00
|
|
|
bool found_tsec_fw = false;
|
2019-09-29 00:18:17 +02:00
|
|
|
for (const u32 *pos = (const u32 *)pkg1; (u8 *)pos < pkg1 + 0x40000; pos += 0x100 / sizeof(u32))
|
|
|
|
{
|
|
|
|
if (*pos == 0xCF42004D)
|
|
|
|
{
|
2019-05-11 21:03:24 -04:00
|
|
|
tsec_ctxt.fw = (u8 *)pos;
|
|
|
|
found_tsec_fw = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-09-29 00:18:17 +02:00
|
|
|
if (!found_tsec_fw)
|
|
|
|
{
|
2019-05-11 21:03:24 -04:00
|
|
|
EPRINTF("Failed to locate TSEC firmware.");
|
2019-09-29 00:18:17 +02:00
|
|
|
return false;
|
2019-05-11 21:03:24 -04:00
|
|
|
}
|
|
|
|
|
2019-06-19 18:16:02 -04:00
|
|
|
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;
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// u32 MAX_KEY = 6;
|
|
|
|
// if (pkg1_id->kb >= KB_FIRMWARE_VERSION_620)
|
|
|
|
// {
|
|
|
|
// MAX_KEY = pkg1_id->kb + 1;
|
|
|
|
// }
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700)
|
|
|
|
{
|
|
|
|
se_aes_key_read(12, master_key[KB_FIRMWARE_VERSION_MAX], 0x10);
|
2019-03-04 18:05:42 -05:00
|
|
|
}
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
//get_tsec: ;
|
2019-03-04 18:05:42 -05:00
|
|
|
u8 tsec_keys[0x10 * 2] = {0};
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
|
|
|
|
{
|
2019-03-04 18:05:42 -05:00
|
|
|
u8 *tsec_paged = (u8 *)page_alloc(3);
|
|
|
|
memcpy(tsec_paged, (void *)tsec_ctxt.fw, tsec_ctxt.size);
|
|
|
|
tsec_ctxt.fw = tsec_paged;
|
|
|
|
}
|
|
|
|
|
|
|
|
int res = 0;
|
|
|
|
|
2019-04-19 13:00:10 -04:00
|
|
|
mc_disable_ahb_redirect();
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
while (tsec_query(tsec_keys, pkg1_id->kb, &tsec_ctxt) < 0)
|
|
|
|
{
|
2019-03-04 18:05:42 -05:00
|
|
|
memset(tsec_keys, 0x00, 0x20);
|
|
|
|
retries++;
|
2019-09-29 00:18:17 +02:00
|
|
|
if (retries > 15)
|
|
|
|
{
|
2019-03-04 18:05:42 -05:00
|
|
|
res = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(pkg1);
|
|
|
|
|
2019-04-19 13:00:10 -04:00
|
|
|
mc_enable_ahb_redirect();
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
if (res < 0)
|
|
|
|
{
|
2019-03-04 18:05:42 -05:00
|
|
|
EPRINTFARGS("ERROR %x dumping TSEC.\n", res);
|
2019-09-29 00:18:17 +02:00
|
|
|
return false;
|
2019-03-04 18:05:42 -05:00
|
|
|
}
|
|
|
|
|
2019-09-16 22:18:41 -06:00
|
|
|
TPRINTFARGS("%kTSEC key(s)... ", colors[(color_idx++) % 6]);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
|
|
|
// Master key derivation
|
2019-09-29 00:18:17 +02:00
|
|
|
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620 && _key_exists(tsec_keys + 0x10))
|
|
|
|
{
|
2019-03-04 18:05:42 -05:00
|
|
|
se_aes_key_set(8, tsec_keys + 0x10, 0x10); // mkek6 = unwrap(mkeks6, tsecroot)
|
|
|
|
se_aes_crypt_block_ecb(8, 0, master_kek[6], master_kek_sources[0]);
|
|
|
|
se_aes_key_set(8, master_kek[6], 0x10); // mkey = unwrap(mkek, mks)
|
|
|
|
se_aes_crypt_block_ecb(8, 0, master_key[6], master_key_source);
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 *keyblob_block = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
|
|
|
u8 keyblob_mac[0x10] = {0};
|
|
|
|
u32 sbk[4] = {FUSE(FUSE_PRIVATE_KEY0), FUSE(FUSE_PRIVATE_KEY1),
|
|
|
|
FUSE(FUSE_PRIVATE_KEY2), FUSE(FUSE_PRIVATE_KEY3)};
|
|
|
|
se_aes_key_set(8, tsec_keys, 0x10);
|
|
|
|
se_aes_key_set(9, sbk, 0x10);
|
2019-09-29 00:18:17 +02:00
|
|
|
for (u32 i = 0; i <= KB_FIRMWARE_VERSION_600; i++)
|
|
|
|
{
|
2019-03-04 18:05:42 -05:00
|
|
|
se_aes_crypt_block_ecb(8, 0, keyblob_key[i], keyblob_key_source[i]); // temp = unwrap(kbks, tsec)
|
2019-09-29 00:18:17 +02:00
|
|
|
se_aes_crypt_block_ecb(9, 0, keyblob_key[i], keyblob_key[i]); // kbk = unwrap(temp, sbk)
|
2019-03-04 18:05:42 -05:00
|
|
|
se_aes_key_set(7, keyblob_key[i], 0x10);
|
|
|
|
se_aes_crypt_block_ecb(7, 0, keyblob_mac_key[i], keyblob_mac_key_source); // kbm = unwrap(kbms, kbk)
|
2019-09-29 00:18:17 +02:00
|
|
|
if (i == 0)
|
|
|
|
{
|
2019-03-04 18:05:42 -05:00
|
|
|
se_aes_crypt_block_ecb(7, 0, device_key, per_console_key_source); // devkey = unwrap(pcks, kbk0)
|
2019-09-15 19:30:42 -06:00
|
|
|
se_aes_crypt_block_ecb(7, 0, new_device_key, per_console_key_source_4x);
|
|
|
|
}
|
2019-03-04 18:05:42 -05:00
|
|
|
|
|
|
|
// verify keyblob is not corrupt
|
2019-09-17 09:51:30 -06:00
|
|
|
emummc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + i, 1, keyblob_block);
|
2019-03-04 18:05:42 -05:00
|
|
|
se_aes_key_set(3, keyblob_mac_key[i], 0x10);
|
|
|
|
se_aes_cmac(3, keyblob_mac, 0x10, keyblob_block + 0x10, 0xa0);
|
2019-09-29 00:18:17 +02:00
|
|
|
if (memcmp(keyblob_block, keyblob_mac, 0x10))
|
|
|
|
{
|
2019-03-04 18:05:42 -05:00
|
|
|
EPRINTFARGS("Keyblob %x corrupt.", i);
|
2019-04-18 12:47:34 -04:00
|
|
|
gfx_hexdump(i, keyblob_block, 0x10);
|
|
|
|
gfx_hexdump(i, keyblob_mac, 0x10);
|
2019-03-04 18:05:42 -05:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// decrypt keyblobs
|
|
|
|
se_aes_key_set(2, keyblob_key[i], 0x10);
|
|
|
|
se_aes_crypt_ctr(2, keyblob[i], 0x90, keyblob_block + 0x20, 0x90, keyblob_block + 0x10);
|
|
|
|
|
|
|
|
memcpy(package1_key[i], keyblob[i] + 0x80, 0x10);
|
|
|
|
memcpy(master_kek[i], keyblob[i], 0x10);
|
|
|
|
se_aes_key_set(7, master_kek[i], 0x10);
|
|
|
|
se_aes_crypt_block_ecb(7, 0, master_key[i], master_key_source);
|
|
|
|
}
|
|
|
|
free(keyblob_block);
|
|
|
|
|
2019-09-16 22:18:41 -06:00
|
|
|
TPRINTFARGS("%kMaster keys... ", colors[(color_idx++) % 6]);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-15 19:30:42 -06:00
|
|
|
u32 key_generation = 0;
|
2019-09-29 00:18:17 +02:00
|
|
|
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_500)
|
|
|
|
{
|
|
|
|
if ((fuse_read_odm(4) & 0x800) && fuse_read_odm(0) == 0x8E61ECAE && fuse_read_odm(1) == 0xF2BA3BB2)
|
|
|
|
{
|
2019-09-15 19:30:42 -06:00
|
|
|
key_generation = fuse_read_odm(2) & 0x1F;
|
|
|
|
}
|
|
|
|
}
|
2019-09-29 00:18:17 +02:00
|
|
|
if (_key_exists(device_key))
|
|
|
|
{
|
|
|
|
if (key_generation)
|
|
|
|
{
|
2019-09-15 19:30:42 -06:00
|
|
|
se_aes_key_set(8, new_device_key, 0x10);
|
|
|
|
se_aes_crypt_block_ecb(8, 0, temp_key, new_device_key_sources[pkg1_id->kb - KB_FIRMWARE_VERSION_400]);
|
|
|
|
se_aes_key_set(8, master_key[0], 0x10);
|
|
|
|
se_aes_unwrap_key(8, 8, new_device_keygen_sources[pkg1_id->kb - KB_FIRMWARE_VERSION_400]);
|
|
|
|
se_aes_crypt_block_ecb(8, 0, temp_key, temp_key);
|
2019-09-29 00:18:17 +02:00
|
|
|
}
|
|
|
|
else
|
2019-09-15 19:30:42 -06:00
|
|
|
memcpy(temp_key, device_key, 0x10);
|
|
|
|
se_aes_key_set(8, temp_key, 0x10);
|
2019-09-29 00:18:17 +02:00
|
|
|
se_aes_unwrap_key(8, 8, retail_specific_aes_key_source); // kek = unwrap(rsaks, devkey)
|
2019-03-04 18:05:42 -05:00
|
|
|
se_aes_crypt_block_ecb(8, 0, bis_key[0] + 0x00, bis_key_source[0] + 0x00); // bkey = unwrap(bkeys, kek)
|
|
|
|
se_aes_crypt_block_ecb(8, 0, bis_key[0] + 0x10, bis_key_source[0] + 0x10);
|
|
|
|
// kek = generate_kek(bkeks, devkey, aeskek, aeskey)
|
2019-09-15 19:30:42 -06:00
|
|
|
_generate_kek(8, bis_kek_source, temp_key, aes_kek_generation_source, aes_key_generation_source);
|
2019-03-04 18:05:42 -05:00
|
|
|
se_aes_crypt_block_ecb(8, 0, bis_key[1] + 0x00, bis_key_source[1] + 0x00); // bkey = unwrap(bkeys, kek)
|
|
|
|
se_aes_crypt_block_ecb(8, 0, bis_key[1] + 0x10, bis_key_source[1] + 0x10);
|
|
|
|
se_aes_crypt_block_ecb(8, 0, bis_key[2] + 0x00, bis_key_source[2] + 0x00);
|
|
|
|
se_aes_crypt_block_ecb(8, 0, bis_key[2] + 0x10, bis_key_source[2] + 0x10);
|
|
|
|
memcpy(bis_key[3], bis_key[2], 0x20);
|
|
|
|
}
|
|
|
|
|
2019-09-17 09:51:30 -06:00
|
|
|
emummc_storage_set_mmc_partition(&storage, 0);
|
2019-03-04 18:05:42 -05:00
|
|
|
// Parse eMMC GPT.
|
|
|
|
LIST_INIT(gpt);
|
|
|
|
nx_emmc_gpt_parse(&gpt, &storage);
|
2019-09-17 10:03:41 -06:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// Find PRODINFO partition.
|
2019-09-23 21:40:31 +02:00
|
|
|
prodinfo_part = nx_emmc_part_find(&gpt, "PRODINFO");
|
2019-09-29 00:18:17 +02:00
|
|
|
if (!prodinfo_part)
|
|
|
|
{
|
2019-09-23 15:25:37 +02:00
|
|
|
EPRINTF("Failed to locate PRODINFO.");
|
2019-09-29 00:18:17 +02:00
|
|
|
return false;
|
2019-03-04 18:05:42 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Read in package2 header and get package2 real size.
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// u8 *tmp_copy = (u8 *)malloc(NX_EMMC_BLOCKSIZE*2);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-23 21:40:31 +02:00
|
|
|
// nx_emmc_part_read(&storage, prodinfo_part, 0, 2, tmp);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-23 21:40:31 +02:00
|
|
|
// memcpy(tmp_copy, tmp, NX_EMMC_BLOCKSIZE*2);
|
|
|
|
// gfx_hexdump(0, tmp + 0x250, 0x18);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// aes_xtsn_decrypt(tmp_copy, NX_EMMC_BLOCKSIZE*2, bis_key[0], bis_key[0] + 0x10, pkg2_part->lba_end, pkg2_part->lba_start, NX_EMMC_BLOCKSIZE);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// gfx_hexdump(0, tmp_copy + 0x250, 0x18);
|
|
|
|
// memcpy(tmp_copy, tmp, NX_EMMC_BLOCKSIZE*2);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-23 21:40:31 +02:00
|
|
|
se_aes_key_set(8, bis_key[0] + 0x00, 0x10);
|
|
|
|
se_aes_key_set(9, bis_key[0] + 0x10, 0x10);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-25 00:49:22 +02:00
|
|
|
//u32 length = 0x18;
|
2019-09-26 08:56:27 +02:00
|
|
|
// u8* buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
|
|
|
// readData(buffer, 0, NX_EMMC_BLOCKSIZE);
|
|
|
|
// gfx_hexdump(0, buffer, 0x08);
|
|
|
|
|
|
|
|
// readData(buffer, NX_EMMC_BLOCKSIZE, NX_EMMC_BLOCKSIZE);
|
|
|
|
// gfx_hexdump(0, buffer, 100);
|
|
|
|
|
|
|
|
// free(buffer);
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
//verify();
|
2019-09-25 17:48:19 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// const char junkSerial[] = "XAJ40030771137";
|
|
|
|
// // gfx_hexdump(0, (u8 *)junkSerial, strlen(junkSerial));
|
|
|
|
// writeData((u8 *)junkSerial, 0x250, strlen(junkSerial));
|
2019-09-26 08:56:27 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// writeClientCertHash();
|
|
|
|
// writeCal0Hash();
|
2019-09-25 17:48:19 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // gfx_hexdump(0, buffer, sizeof(buffer));
|
|
|
|
// //free(buffer);
|
2019-09-25 17:48:19 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // restore();
|
2019-09-25 17:48:19 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // verify();
|
2019-09-25 17:48:19 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
|
|
|
// u8 *tmp_dec = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
|
|
|
// // nx_emmc_part_read(&storage, prodinfo_part, 1, 1, tmp);
|
2019-09-25 17:48:19 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // gfx_hexdump(0, tmp, 0x100);
|
|
|
|
// // aes_xts_ctxt_t context;
|
|
|
|
// // aes_xts_init(&context, AES_DECRYPT, bis_key[0], bis_key[0] + 0x10, 128);
|
|
|
|
// // // aes_xts_crypt(&context, 0, NX_EMMC_BLOCKSIZE, tmp, tmp_dec);
|
2019-09-25 18:04:13 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // // gfx_hexdump(0, tmp_dec, 0x100);
|
2019-09-25 18:04:13 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // aes_xts_crypt(&context, 1, NX_EMMC_BLOCKSIZE, tmp, tmp_dec);
|
2019-09-25 18:04:13 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // gfx_hexdump(0, tmp_dec, 0x100);
|
2019-09-25 18:05:38 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// disk_read_prod(tmp_dec, 1, 1);
|
|
|
|
// //readData(tmp_dec, NX_EMMC_BLOCKSIZE, NX_EMMC_BLOCKSIZE);
|
2019-09-25 18:04:13 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// gfx_hexdump(0, tmp_dec, 0x100);
|
2019-09-26 08:56:27 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // disk_write_prod(tmp_dec, 1, 1);
|
|
|
|
// // gfx_hexdump(0, tmp_dec, 0x100);
|
2019-09-26 08:56:27 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// //se_aes_xts_crypt_sec(9, 8, 1, 1, tmp, tmp_dec, NX_EMMC_BLOCKSIZE);
|
2019-09-26 08:56:27 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// //gfx_hexdump(0, tmp, 0x100);
|
2019-09-26 08:56:27 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // se_aes_xts_crypt_sec(9, 8, 1, 0, tmp, tmp_dec, NX_EMMC_BLOCKSIZE);
|
2019-09-26 08:56:27 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // se_aes_xts_crypt_sec(9, 8, 0, 0, tmp_dec, tmp, NX_EMMC_BLOCKSIZE);
|
2019-09-26 08:56:27 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // gfx_hexdump(0, tmp_dec, 0x10);
|
2019-09-25 18:04:13 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // free(tmp);
|
|
|
|
// free(tmp_dec);
|
2019-09-24 09:41:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // writeClientCertHash();
|
|
|
|
// // writeCal0Hash();
|
2019-09-25 10:12:15 +02:00
|
|
|
|
|
|
|
// verify();
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // verify();
|
|
|
|
// // free(tmp_copy);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // pkg2_done:
|
|
|
|
// // // free(pkg2);
|
|
|
|
// // // free(ki);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // TPRINTFARGS("%kFS keys... ", colors[(color_idx++) % 6]);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // // DIR dir;
|
|
|
|
// // // FILINFO fno;
|
|
|
|
// // // FIL fp;
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // // f_closedir(&dir);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // // f_close(&fp);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // TPRINTFARGS("%kSD Seed... ", colors[(color_idx++) % 6]);
|
2019-09-16 22:18:41 -06:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// dismount:
|
|
|
|
// nx_emmc_gpt_free(&gpt);
|
|
|
|
// emummc_storage_end(&storage);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// end_time = get_tmr_us();
|
|
|
|
// gfx_printf("\n%kFound %d keys.", colors[(color_idx++) % 6], _key_count);
|
|
|
|
// _key_count = 0;
|
|
|
|
// gfx_printf("\n%kLockpick totally done in %d us", colors[(color_idx++) % 6], end_time - begin_time);
|
|
|
|
// gfx_printf("\n%kFound through master_key_%02x\n", colors[(color_idx++) % 6], MAX_KEY - 1);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// // f_mkdir("sd:/switch");
|
|
|
|
// // char keyfile_path[30] = "sd:/switch/";
|
|
|
|
// // if (!(fuse_read_odm(4) & 3))
|
|
|
|
// // sprintf(&keyfile_path[11], "prod.keys");
|
|
|
|
// // else
|
|
|
|
// // sprintf(&keyfile_path[11], "dev.keys");
|
|
|
|
// // if (sd_mount() && !sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) {
|
|
|
|
// // gfx_printf("%kWrote %d bytes to %s\n", colors[(color_idx++) % 6], (u32)fno.fsize, keyfile_path);
|
|
|
|
// // } else
|
|
|
|
// // EPRINTF("Failed to save keys to SD.");
|
|
|
|
h_cfg.emummc_force_disable = emummc_load_cfg();
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// out_wait:
|
|
|
|
// // sd_unmount();
|
|
|
|
// gfx_printf("\n%kPress any key to return to the main menu.", colors[(color_idx) % 6], colors[(color_idx + 1) % 6], colors[(color_idx + 2) % 6]);
|
2019-09-16 22:18:41 -06:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// btn_wait();
|
|
|
|
// nx_emmc_gpt_free(&gpt);
|
|
|
|
gfx_printf("\n%kFound keys.\n\n", colors[(color_idx++) % 6]);
|
|
|
|
return true;
|
|
|
|
}
|
2019-04-18 11:02:15 -04:00
|
|
|
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
void cleanUp(){
|
|
|
|
|
|
|
|
emummc_storage_end(&storage);
|
2019-03-04 18:05:42 -05:00
|
|
|
}
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed)
|
|
|
|
{
|
2019-03-04 18:05:42 -05:00
|
|
|
if (!_key_exists(key_source) || !_key_exists(master_key) || !_key_exists(kek_seed))
|
|
|
|
return;
|
|
|
|
|
|
|
|
se_aes_key_set(ks, master_key, 0x10);
|
|
|
|
se_aes_unwrap_key(ks, ks, kek_seed);
|
|
|
|
se_aes_unwrap_key(ks, ks, key_source);
|
|
|
|
if (key_seed && _key_exists(key_seed))
|
|
|
|
se_aes_unwrap_key(ks, ks, key_seed);
|
|
|
|
}
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
static inline u32 _read_le_u32(const void *buffer, u32 offset)
|
|
|
|
{
|
|
|
|
return (*(u8 *)(buffer + offset + 0)) |
|
|
|
|
(*(u8 *)(buffer + offset + 1) << 0x08) |
|
|
|
|
(*(u8 *)(buffer + offset + 2) << 0x10) |
|
|
|
|
(*(u8 *)(buffer + offset + 3) << 0x18);
|
2019-03-04 18:05:42 -05:00
|
|
|
}
|
|
|
|
|
2019-09-24 15:15:18 +02:00
|
|
|
bool readData(u8 *buffer, u32 offset, u32 length)
|
2019-09-23 21:40:31 +02:00
|
|
|
{
|
2019-09-24 15:15:18 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
|
|
|
// u32 sector = (offset / NX_EMMC_BLOCKSIZE);
|
|
|
|
// u32 newOffset = offset % NX_EMMC_BLOCKSIZE;
|
|
|
|
// u32 read = 0;
|
2019-09-23 21:40:31 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// if (newOffset > 0 && length >= NX_EMMC_BLOCKSIZE)
|
|
|
|
// {
|
|
|
|
// u32 toRead = NX_EMMC_BLOCKSIZE - newOffset;
|
|
|
|
// disk_read_prod(tmp, sector, 1);
|
|
|
|
// memcpy(buffer, tmp + newOffset, toRead);
|
2019-09-23 21:40:31 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// length -= toRead;
|
|
|
|
// read += toRead;
|
|
|
|
// sector++;
|
2019-09-24 09:41:22 +02:00
|
|
|
// }
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// while (length > NX_EMMC_BLOCKSIZE)
|
|
|
|
// {
|
2019-09-24 09:41:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// disk_read_prod(tmp, sector, 1);
|
|
|
|
// memcpy(buffer + read, tmp, NX_EMMC_BLOCKSIZE);
|
|
|
|
|
|
|
|
// length -= NX_EMMC_BLOCKSIZE;
|
|
|
|
// read += NX_EMMC_BLOCKSIZE;
|
|
|
|
// sector++;
|
|
|
|
// }
|
2019-09-26 08:56:27 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// if (length > 0)
|
|
|
|
// {
|
|
|
|
// disk_read_prod(tmp, sector, 1);
|
|
|
|
// memcpy(buffer + read, tmp, length);
|
|
|
|
// }
|
2019-09-26 08:56:27 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// free(tmp);
|
2019-09-26 08:56:27 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
u32 sector = (offset / NX_EMMC_BLOCKSIZE);
|
|
|
|
u32 newOffset = (offset % NX_EMMC_BLOCKSIZE);
|
2019-09-26 08:56:27 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
u32 sectorCount = ((newOffset + length - 1) / (NX_EMMC_BLOCKSIZE)) + 1;
|
2019-09-26 08:56:27 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
u8 *tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE);
|
2019-09-26 08:56:27 +02:00
|
|
|
|
2019-09-25 00:49:22 +02:00
|
|
|
disk_read_prod(tmp, sector, sectorCount);
|
2019-09-24 09:41:22 +02:00
|
|
|
|
2019-09-24 15:15:18 +02:00
|
|
|
memcpy(buffer, tmp + newOffset, length);
|
2019-03-04 18:05:42 -05:00
|
|
|
|
2019-09-23 21:40:31 +02:00
|
|
|
free(tmp);
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
return true;
|
2019-09-24 09:41:22 +02:00
|
|
|
}
|
|
|
|
|
2019-09-25 00:49:22 +02:00
|
|
|
bool writeData(u8 *buffer, u32 offset, u32 length)
|
2019-09-24 15:15:18 +02:00
|
|
|
{
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
|
|
|
// u32 sector = (offset / NX_EMMC_BLOCKSIZE);
|
|
|
|
// u32 newOffset = offset % NX_EMMC_BLOCKSIZE;
|
|
|
|
// u32 read = 0;
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// if (newOffset > 0 && length >= NX_EMMC_BLOCKSIZE)
|
|
|
|
// {
|
|
|
|
// u32 toRead = NX_EMMC_BLOCKSIZE - newOffset;
|
|
|
|
// disk_read_prod(tmp, sector, 1);
|
|
|
|
// memcpy(tmp + newOffset, buffer, toRead);
|
|
|
|
// disk_write_prod(tmp, sector, 1);
|
|
|
|
// length -= toRead;
|
|
|
|
// read += toRead;
|
|
|
|
// sector++;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// while (length > NX_EMMC_BLOCKSIZE)
|
|
|
|
// {
|
|
|
|
|
|
|
|
// disk_write_prod(buffer + read, sector, 1);
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// length -= NX_EMMC_BLOCKSIZE;
|
|
|
|
// read += NX_EMMC_BLOCKSIZE;
|
|
|
|
// sector++;
|
2019-09-25 00:49:22 +02:00
|
|
|
// }
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// if (length > 0)
|
|
|
|
// {
|
|
|
|
// disk_read_prod(tmp, sector, 1);
|
|
|
|
// memcpy(tmp, buffer + read, length);
|
|
|
|
// disk_write_prod(buffer + read, sector, 1);
|
|
|
|
// }
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// free(tmp);
|
2019-09-26 08:56:27 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
u32 sector = (offset / NX_EMMC_BLOCKSIZE);
|
|
|
|
u32 newOffset = (offset % NX_EMMC_BLOCKSIZE);
|
|
|
|
|
|
|
|
u8 sectorCount = ((newOffset + length - 1) / (NX_EMMC_BLOCKSIZE)) + 1;
|
|
|
|
|
|
|
|
u8 *tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE);
|
|
|
|
|
2019-09-25 00:49:22 +02:00
|
|
|
disk_read_prod(tmp, sector, sectorCount);
|
|
|
|
|
|
|
|
memcpy(tmp + newOffset, buffer, length);
|
|
|
|
|
|
|
|
disk_write_prod(tmp, sector, sectorCount);
|
|
|
|
|
|
|
|
free(tmp);
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
return true;
|
2019-09-25 00:49:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool writeHash(u32 hashOffset, u32 offset, u32 sz)
|
2019-09-29 00:18:17 +02:00
|
|
|
{
|
2019-09-24 15:15:18 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
u8 *buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
2019-09-24 15:15:18 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
SHA256_CTX ctx;
|
|
|
|
sha256_init(&ctx);
|
2019-09-24 15:15:18 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
u32 newOffset = offset % NX_EMMC_BLOCKSIZE;
|
2019-09-24 15:15:18 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
if (newOffset > 0 && newOffset + sz >= NX_EMMC_BLOCKSIZE)
|
|
|
|
{
|
|
|
|
u32 toRead = NX_EMMC_BLOCKSIZE - newOffset;
|
|
|
|
readData(buffer, offset, toRead);
|
|
|
|
sha256_update(&ctx, buffer, toRead);
|
2019-09-24 15:15:18 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
sz -= toRead;
|
|
|
|
offset += toRead;
|
|
|
|
}
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
while (sz > NX_EMMC_BLOCKSIZE)
|
|
|
|
{
|
2019-09-25 10:12:15 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
readData(buffer, offset, NX_EMMC_BLOCKSIZE);
|
|
|
|
sha256_update(&ctx, buffer, NX_EMMC_BLOCKSIZE);
|
2019-09-25 10:12:15 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
sz -= NX_EMMC_BLOCKSIZE;
|
|
|
|
offset += NX_EMMC_BLOCKSIZE;
|
|
|
|
}
|
2019-09-25 10:12:15 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
if (sz > 0)
|
|
|
|
{
|
2019-09-25 10:12:15 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
readData(buffer, offset, sz);
|
|
|
|
sha256_update(&ctx, buffer, sz);
|
|
|
|
}
|
|
|
|
u8 hash[0x20];
|
|
|
|
sha256_final(&ctx, hash);
|
2019-09-24 15:15:18 +02:00
|
|
|
|
2019-09-25 00:49:22 +02:00
|
|
|
writeData(hash, hashOffset, 0x20);
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
free(buffer);
|
|
|
|
return true;
|
|
|
|
}
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
bool verifyHash(u32 hashOffset, u32 offset, u32 sz)
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
u8 *buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
SHA256_CTX ctx;
|
|
|
|
sha256_init(&ctx);
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
u32 newOffset = offset % NX_EMMC_BLOCKSIZE;
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
if (newOffset > 0 && sz >= NX_EMMC_BLOCKSIZE)
|
|
|
|
{
|
|
|
|
u32 toRead = NX_EMMC_BLOCKSIZE - newOffset;
|
|
|
|
readData(buffer, offset, toRead);
|
|
|
|
sha256_update(&ctx, buffer, toRead);
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
sz -= toRead;
|
|
|
|
offset += toRead;
|
|
|
|
}
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
while (sz > NX_EMMC_BLOCKSIZE)
|
|
|
|
{
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
readData(buffer, offset, NX_EMMC_BLOCKSIZE);
|
|
|
|
sha256_update(&ctx, buffer, NX_EMMC_BLOCKSIZE);
|
2019-09-24 15:15:18 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
sz -= NX_EMMC_BLOCKSIZE;
|
|
|
|
offset += NX_EMMC_BLOCKSIZE;
|
|
|
|
}
|
2019-09-24 15:15:18 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
if (sz > 0)
|
|
|
|
{
|
2019-09-24 15:15:18 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
readData(buffer, offset, sz);
|
|
|
|
sha256_update(&ctx, buffer, sz);
|
|
|
|
}
|
|
|
|
u8 hash1[0x20];
|
|
|
|
sha256_final(&ctx, hash1);
|
2019-09-24 15:15:18 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
u8 hash2[0x20];
|
2019-09-24 15:15:18 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
readData(hash2, hashOffset, 0x20);
|
2019-09-24 15:15:18 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
if (memcmp(hash1, hash2, 0x20))
|
|
|
|
{
|
|
|
|
EPRINTF("error: hash verification failed\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = true;
|
|
|
|
}
|
2019-09-25 10:12:15 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
gfx_hexdump(0, hash1, 0x20);
|
|
|
|
gfx_hexdump(0, hash2, 0x20);
|
2019-09-25 10:12:15 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
free(buffer);
|
|
|
|
return result;
|
|
|
|
}
|
2019-09-25 10:12:15 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
u32 certSize()
|
|
|
|
{
|
|
|
|
u32 buffer;
|
|
|
|
readData((u8 *)&buffer, 0x0AD0, sizeof(buffer));
|
|
|
|
return buffer;
|
2019-09-24 15:15:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
u32 calibrationDataSize()
|
|
|
|
{
|
|
|
|
u32 buffer;
|
|
|
|
readData((u8 *)&buffer, 0x08, sizeof(buffer));
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
2019-09-25 00:49:22 +02:00
|
|
|
bool writeCal0Hash()
|
|
|
|
{
|
2019-09-29 00:18:17 +02:00
|
|
|
return writeHash(0x20, 0x40, calibrationDataSize());
|
2019-09-25 00:49:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool writeClientCertHash()
|
|
|
|
{
|
2019-09-29 00:18:17 +02:00
|
|
|
return writeHash(0x12E0, 0xAE0, certSize());
|
2019-09-25 00:49:22 +02:00
|
|
|
}
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
bool verifyCal0Hash()
|
|
|
|
{
|
2019-09-25 00:49:22 +02:00
|
|
|
return verifyHash(0x20, 0x40, calibrationDataSize());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool verifyClientCertHash()
|
|
|
|
{
|
|
|
|
|
|
|
|
return verifyHash(0x12E0, 0xAE0, certSize());
|
|
|
|
}
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
bool verifyProdinfo()
|
2019-09-24 15:15:18 +02:00
|
|
|
{
|
2019-09-29 00:18:17 +02:00
|
|
|
return verifyClientCertHash() && verifyCal0Hash();
|
2019-09-25 00:49:22 +02:00
|
|
|
// bool r = verifyHash(0x12E0, 0xAE0, certSize()); // client cert hash
|
|
|
|
// r &= verifyHash(0x20, 0x40, calibrationDataSize()); // calibration hash
|
2019-09-24 09:41:22 +02:00
|
|
|
|
2019-09-25 00:49:22 +02:00
|
|
|
// return r;
|
2019-09-24 15:15:18 +02:00
|
|
|
}
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
bool backupProdinfo()
|
|
|
|
{
|
|
|
|
sd_mount();
|
|
|
|
char* name;
|
|
|
|
if (!emu_cfg.enabled || h_cfg.emummc_force_disable){
|
|
|
|
name = "sd:/prodinfo_sysnand.bin";
|
|
|
|
} else {
|
|
|
|
|
|
|
|
name = "sd:/prodinfo_emunand.bin";
|
|
|
|
}
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
if (f_stat(name, NULL))
|
|
|
|
{
|
|
|
|
f_unlink(name);
|
2019-09-25 00:49:22 +02:00
|
|
|
}
|
2019-09-29 00:18:17 +02:00
|
|
|
FIL fp;
|
|
|
|
f_open(&fp, name, FA_CREATE_ALWAYS | FA_WRITE);
|
|
|
|
u8 bufferNX[NX_EMMC_BLOCKSIZE];
|
|
|
|
u32 size = 0x3FBC00;
|
|
|
|
u32 offset = 0;
|
|
|
|
while (size > NX_EMMC_BLOCKSIZE)
|
|
|
|
{
|
|
|
|
readData(bufferNX, offset, NX_EMMC_BLOCKSIZE);
|
|
|
|
f_write(&fp, bufferNX, NX_EMMC_BLOCKSIZE, NULL);
|
|
|
|
f_sync(&fp);
|
|
|
|
offset += NX_EMMC_BLOCKSIZE;
|
|
|
|
size -= NX_EMMC_BLOCKSIZE;
|
2019-09-25 00:49:22 +02:00
|
|
|
}
|
2019-09-29 00:18:17 +02:00
|
|
|
if (size > 0)
|
|
|
|
{
|
|
|
|
readData(bufferNX, offset, size);
|
|
|
|
f_write(&fp, bufferNX, size, NULL);
|
|
|
|
f_sync(&fp);
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
f_close(&fp);
|
|
|
|
|
|
|
|
gfx_printf("%kBackup %s done!\n\n", COLOR_GREEN, name);
|
|
|
|
|
|
|
|
// if (f_stat("sd:/prodinfoENC.bin", NULL))
|
|
|
|
// {
|
|
|
|
// f_unlink("sd:/prodinfoENC.bin");
|
|
|
|
// }
|
|
|
|
|
|
|
|
// f_open(&fp, "sd:/prodinfoENC.bin", FA_CREATE_NEW | FA_WRITE);
|
|
|
|
// size = 0x3FBC00;
|
|
|
|
// offset = 0;
|
|
|
|
// while (size > 0)
|
|
|
|
// {
|
|
|
|
// nx_emmc_part_read(&storage, prodinfo_part, offset, 1, bufferNX);
|
|
|
|
// f_write(&fp, bufferNX, NX_EMMC_BLOCKSIZE, NULL);
|
|
|
|
// offset++;
|
|
|
|
// size -= NX_EMMC_BLOCKSIZE;
|
|
|
|
// }
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// f_close(&fp);
|
2019-09-25 10:12:15 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
// gfx_printf("\n%kBackup encrypted done!", colors[4]);
|
|
|
|
return true;
|
2019-09-25 10:12:15 +02:00
|
|
|
}
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
bool restoreProdinfo()
|
|
|
|
{
|
|
|
|
sd_mount();
|
|
|
|
|
|
|
|
char* name;
|
|
|
|
if (!emu_cfg.enabled || h_cfg.emummc_force_disable){
|
|
|
|
name = "sd:/prodinfo_sysnand.bin";
|
|
|
|
} else {
|
|
|
|
|
|
|
|
name = "sd:/prodinfo_emunand.bin";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FIL fp;
|
|
|
|
if (f_open(&fp, name, FA_READ) != FR_OK)
|
|
|
|
{
|
|
|
|
gfx_printf("\nCannot open%s!\n", name);
|
|
|
|
return false;
|
|
|
|
}
|
2019-09-25 10:12:15 +02:00
|
|
|
u8 bufferNX[NX_EMMC_BLOCKSIZE];
|
2019-09-25 00:49:22 +02:00
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
u32 size = 0x3FBC00;
|
|
|
|
u32 offset = 0;
|
|
|
|
while (size > 0)
|
|
|
|
{
|
|
|
|
f_read(&fp, bufferNX, NX_EMMC_BLOCKSIZE, NULL);
|
|
|
|
writeData(bufferNX,offset,NX_EMMC_BLOCKSIZE);
|
|
|
|
//nx_emmc_part_write(&storage, prodinfo_part, offset, 1, bufferNX);
|
|
|
|
offset+= NX_EMMC_BLOCKSIZE;
|
|
|
|
size -= NX_EMMC_BLOCKSIZE;
|
|
|
|
}
|
2019-09-25 10:12:15 +02:00
|
|
|
// if(size > 0){
|
|
|
|
// f_read(&fp, bufferNX, size, NULL);
|
|
|
|
// nx_emmc_part_write(&storage, prodinfo_part, offset, 1, bufferNX);
|
|
|
|
// f_write(&fp, bufferNX, size, NULL);
|
|
|
|
// }
|
|
|
|
|
2019-09-29 00:18:17 +02:00
|
|
|
f_close(&fp);
|
|
|
|
|
|
|
|
gfx_printf("%kRestore %s done!\n\n", COLOR_GREEN, name);
|
2019-09-25 10:12:15 +02:00
|
|
|
return true;
|
2019-09-25 00:49:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// bool erase(u32 offset, u32 sz)
|
|
|
|
// {
|
|
|
|
// u8 zero = 0;
|
|
|
|
|
|
|
|
// for (u64 i = 0; i < sz; i++)
|
|
|
|
// {
|
|
|
|
// fsStorageWrite(&m_sh, offset + i, &zero, 1);
|
|
|
|
// }
|
|
|
|
|
|
|
|
// return true;
|
|
|
|
// }
|