diff --git a/Makefile b/Makefile index 0f47b06..7495f24 100644 --- a/Makefile +++ b/Makefile @@ -10,12 +10,12 @@ include $(DEVKITARM)/base_rules IPL_LOAD_ADDR := 0x40003000 LPVERSION_MAJOR := 1 -LPVERSION_MINOR := 5 +LPVERSION_MINOR := 0 LPVERSION_BUGFX := 0 ################################################################################ -TARGET := Lockpick_RCM +TARGET := Incognito_RCM BUILDDIR := build OUTPUTDIR := output SOURCEDIR = source diff --git a/README.md b/README.md index 48e7667..8369cf0 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,33 @@ -Lockpick_RCM +Incognito_RCM = -Lockpick_RCM is a bare metal Nintendo Switch payload that derives encryption keys for use in Switch file handling software like hactool, hactoolnet/LibHac, ChoiDujour, etc. without booting Horizon OS. +Incognito_RCM is a bare metal Nintendo Switch payload that derives encryption keys for de- and encrypting PRODINFO partition (sysnand and emummc) and wiping personal information from your Nintendo Switch as to go online while worrying slightly less about a ban. + +It is heavily based on [Lockpick_RCM](https://github.com/shchmue/Lockpick_RCM) and takes inspiration from [incognito](https://github.com/blawar/incognito). -Due to changes imposed by firmware 7.0.0, Lockpick homebrew can no longer derive the latest keys. In the boot-time environment however, there is no such limitation. Usage = -* Launch Lockpick_RCM.bin using your favorite payload injector -* Upon completion, keys will be saved to `/switch/prod.keys` on SD -* If the console has Firmware 7.x or higher, the `/sept/` folder from [Atmosphère](https://github.com/Atmosphere-NX/Atmosphere/releases) or [Kosmos](https://github.com/AtlasNX/Kosmos/releases) release zip must be present on SD or else only keyblob master key derivation is possible (ie. up to `master_key_05` only) +* Launch Incoginito_RCM.bin using your favorite payload injector +* Use menu to make a backup! (Will be written to `sd:/prodinfo_sysnand.bin` and `sd:/prodinfo_emunand.bin` respectively) +* Choose either Incognito (sysNAND) or Incognito (emuMMC) to wipe personal information +* If you ever want to revert, choose restore menu points + +Keep in mind that backups will be overwritten, so don't backup after applying Incognito! Building = Install [devkitARM](https://devkitpro.org/) and run `make`. -Massive Thanks to CTCaer! -= -This software is heavily based on [Hekate](https://github.com/CTCaer/hekate). Beyond that, CTCaer was exceptionally helpful in the development of this project, lending loads of advice, expertise, and humor. +Massive Thanks to CTCaer, shchmue and blawar! Known Issues = -* Chainloading from SX will hang immediately due to quirks in their hwinit code, please launch payload directly \ No newline at end of file +* Chainloading from SX will hang immediately due to quirks in their hwinit code, please launch payload directly + +Disclaimers += +* This application does not remove all personal information from your Switch, and should not be treated as a true preventative measure against getting banned. + +* ALWAYS have a NAND backup. I am not responsible for any bricks or bans. Use at your own risk, as this is an experimental program. + +* This application backs up your PRODINFO to the SD card. You should keep this backup in a more secure location, and not leave it on the SD card where it could be subject to corruption or be read by malicious applications. \ No newline at end of file diff --git a/source/gfx/gfx.c b/source/gfx/gfx.c index d23a30a..59ee792 100644 --- a/source/gfx/gfx.c +++ b/source/gfx/gfx.c @@ -400,14 +400,15 @@ void gfx_printf(const char *fmt, ...) void gfx_print_header() { u8 prevFontSize = gfx_con.fntsz; - gfx_con.fntsz = 14; + gfx_con.fntsz = 15; gfx_printf("%k ____ _ __ ____ ________ ___\n", colors[4]); gfx_printf("%k / _/___ _________ ____ _____ (_) /_____ / __ \\/ ____/ |/ /\n", COLOR_GREEN); gfx_printf("%k / // __ \\/ ___/ __ \\/ __ `/ __ \\/ / __/ __ \\ / /_/ / / / /|_/ / \n", COLOR_GREEN); gfx_printf("%k _/ // / / / /__/ /_/ / /_/ / / / / / /_/ /_/ / / _, _/ /___/ / / / \n", COLOR_GREEN); gfx_printf("%k/___/_/ /_/\\___/\\____/\\__, /_/ /_/_/\\__/\\____/____/_/ |_|\\____/_/ /_/ \n", colors[4]); gfx_printf("%k /____/ /_____/ \n", colors[4]); - gfx_printf("%kv%d.%d.%d%k\n\n\n\n", + gfx_con.fntsz = 14; + gfx_printf("%kv%d.%d.%d - by jimzrt%k\n\n\n\n", colors[4], LP_VER_MJ, LP_VER_MN, LP_VER_BF, 0xFFCCCCCC); gfx_con.fntsz = prevFontSize; } diff --git a/source/keys/keys.c b/source/keys/keys.c index 7685f69..3ed359a 100644 --- a/source/keys/keys.c +++ b/source/keys/keys.c @@ -47,8 +47,6 @@ #include #include "sha256.h" -#include "aes_xts.h" - extern bool sd_mount(); extern void sd_unmount(); extern int sd_save_to_file(void *buf, u32 size, const char *filename); @@ -57,10 +55,14 @@ extern hekate_config h_cfg; u32 _key_count = 0; sdmmc_storage_t storage; +sdmmc_t sdmmc; emmc_part_t *system_part; emmc_part_t *prodinfo_part; u32 start_time, end_time; +#define ENCRYPTED 1 +#define DECRYPTED 0 + #define TPRINTF(text) \ end_time = get_tmr_us(); \ gfx_printf(text " done in %d us\n", end_time - start_time); \ @@ -84,6 +86,8 @@ static u8 temp_key[0x10], master_kek[KB_FIRMWARE_VERSION_MAX + 1][0x10] = {0}, master_key[KB_FIRMWARE_VERSION_MAX + 1][0x10] = {0}; +LIST_INIT(gpt); + // key functions 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); @@ -99,16 +103,17 @@ bool dump_keys() // 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); + gfx_printf("%kGetting bis_keys...\n", COLOR_YELLOW); + start_time = get_tmr_us(); //u32 begin_time = get_tmr_us(); u32 retries = 0; - u32 color_idx = 0; + // u32 color_idx = 0; tsec_ctxt_t tsec_ctxt; - sdmmc_t sdmmc; emummc_storage_init_mmc(&storage, &sdmmc); - TPRINTFARGS("%kMMC init... ", colors[(color_idx++) % 6]); + // TPRINTFARGS("%kMMC init... ", colors[(color_idx++) % 6]); // Read package1. u8 *pkg1 = (u8 *)malloc(0x40000); @@ -183,10 +188,10 @@ bool dump_keys() if (res < 0) { EPRINTFARGS("ERROR %x dumping TSEC.\n", res); - return false; + return false; } - TPRINTFARGS("%kTSEC key(s)... ", colors[(color_idx++) % 6]); + //TPRINTFARGS("%kTSEC key(s)... ", colors[(color_idx++) % 6]); // Master key derivation if (pkg1_id->kb == KB_FIRMWARE_VERSION_620 && _key_exists(tsec_keys + 0x10)) @@ -238,7 +243,7 @@ bool dump_keys() } free(keyblob_block); - TPRINTFARGS("%kMaster keys... ", colors[(color_idx++) % 6]); + //TPRINTFARGS("%kMaster keys... ", colors[(color_idx++) % 6]); u32 key_generation = 0; if (pkg1_id->kb >= KB_FIRMWARE_VERSION_500) @@ -275,7 +280,7 @@ bool dump_keys() emummc_storage_set_mmc_partition(&storage, 0); // Parse eMMC GPT. - LIST_INIT(gpt); + nx_emmc_gpt_parse(&gpt, &storage); // Find PRODINFO partition. @@ -283,148 +288,82 @@ bool dump_keys() if (!prodinfo_part) { EPRINTF("Failed to locate PRODINFO."); - return false; + return false; } - // Read in package2 header and get package2 real size. - - // u8 *tmp_copy = (u8 *)malloc(NX_EMMC_BLOCKSIZE*2); - - // nx_emmc_part_read(&storage, prodinfo_part, 0, 2, tmp); - - // memcpy(tmp_copy, tmp, NX_EMMC_BLOCKSIZE*2); - // gfx_hexdump(0, tmp + 0x250, 0x18); - - // 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); - - // gfx_hexdump(0, tmp_copy + 0x250, 0x18); - // memcpy(tmp_copy, tmp, NX_EMMC_BLOCKSIZE*2); - se_aes_key_set(8, bis_key[0] + 0x00, 0x10); se_aes_key_set(9, bis_key[0] + 0x10, 0x10); - //u32 length = 0x18; - // u8* buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE); - // readData(buffer, 0, NX_EMMC_BLOCKSIZE); - // gfx_hexdump(0, buffer, 0x08); + gfx_printf("%kGot keys!\n", COLOR_GREEN); + char serial[15]; + readData((u8 *)serial, 0x250, 15, ENCRYPTED); - // readData(buffer, NX_EMMC_BLOCKSIZE, NX_EMMC_BLOCKSIZE); - // gfx_hexdump(0, buffer, 100); + gfx_printf("%kCurrent serial:%s\n\n", COLOR_BLUE, serial); - // free(buffer); - - //verify(); - - // const char junkSerial[] = "XAJ40030771137"; - // // gfx_hexdump(0, (u8 *)junkSerial, strlen(junkSerial)); - // writeData((u8 *)junkSerial, 0x250, strlen(junkSerial)); - - // writeClientCertHash(); - // writeCal0Hash(); - - // // gfx_hexdump(0, buffer, sizeof(buffer)); - // //free(buffer); - - // // restore(); - - // // verify(); - - // // 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); - - // // 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); - - // // // gfx_hexdump(0, tmp_dec, 0x100); - - // // aes_xts_crypt(&context, 1, NX_EMMC_BLOCKSIZE, tmp, tmp_dec); - - // // gfx_hexdump(0, tmp_dec, 0x100); - - // disk_read_prod(tmp_dec, 1, 1); - // //readData(tmp_dec, NX_EMMC_BLOCKSIZE, NX_EMMC_BLOCKSIZE); - - // gfx_hexdump(0, tmp_dec, 0x100); - - // // disk_write_prod(tmp_dec, 1, 1); - // // gfx_hexdump(0, tmp_dec, 0x100); - - // //se_aes_xts_crypt_sec(9, 8, 1, 1, tmp, tmp_dec, NX_EMMC_BLOCKSIZE); - - // //gfx_hexdump(0, tmp, 0x100); - - // // se_aes_xts_crypt_sec(9, 8, 1, 0, tmp, tmp_dec, NX_EMMC_BLOCKSIZE); - - // // se_aes_xts_crypt_sec(9, 8, 0, 0, tmp_dec, tmp, NX_EMMC_BLOCKSIZE); - - // // gfx_hexdump(0, tmp_dec, 0x10); - - // // free(tmp); - // free(tmp_dec); - - // // writeClientCertHash(); - // // writeCal0Hash(); - - // verify(); - - // // verify(); - // // free(tmp_copy); - - // // pkg2_done: - // // // free(pkg2); - // // // free(ki); - - // // TPRINTFARGS("%kFS keys... ", colors[(color_idx++) % 6]); - - // // // DIR dir; - // // // FILINFO fno; - // // // FIL fp; - - // // // f_closedir(&dir); - - // // // f_close(&fp); - - // // TPRINTFARGS("%kSD Seed... ", colors[(color_idx++) % 6]); - -// dismount: -// nx_emmc_gpt_free(&gpt); -// emummc_storage_end(&storage); - -// 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); - -// // 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(); - -// 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]); - -// btn_wait(); - // nx_emmc_gpt_free(&gpt); - gfx_printf("\n%kFound keys.\n\n", colors[(color_idx++) % 6]); return true; } +void erase(u32 offset, u32 length) +{ -void cleanUp(){ - - emummc_storage_end(&storage); + u8 *tmp = (u8 *)calloc(length, sizeof(u8)); + writeData(tmp, offset, length, ENCRYPTED); + free(tmp); +} + +void writeSerial() +{ + const char *junkSerial; + if (!emu_cfg.enabled || h_cfg.emummc_force_disable) + { + junkSerial = "XAW00000000000"; + } + else + { + junkSerial = "XAW00000000001"; + } + + writeData((u8 *)junkSerial, 0x250, 14, ENCRYPTED); +} + +void incognito() +{ + + gfx_printf("%kWriting junk serial...\n", COLOR_YELLOW); + + writeSerial(); + gfx_printf("%kErasing client cert...\n", COLOR_YELLOW); + erase(0x0AE0, 0x800); // client cert + gfx_printf("%kErasing private key...\n", COLOR_YELLOW); + erase(0x3AE0, 0x130); // private key + gfx_printf("%kErasing deviceId 1/2...\n", COLOR_YELLOW); + erase(0x35E1, 0x006); // deviceId + gfx_printf("%kErasing deviceId 2/2...\n", COLOR_YELLOW); + erase(0x36E1, 0x006); // deviceId + gfx_printf("%kErasing device cert 1/2...\n", COLOR_YELLOW); + erase(0x02B0, 0x180); // device cert + gfx_printf("%kErasing device cert 2/2...\n", COLOR_YELLOW); + erase(0x3D70, 0x240); // device cert + gfx_printf("%kErasing device key...\n", COLOR_YELLOW); + + erase(0x3FC0, 0x240); // device key + + gfx_printf("%kWriting client cert hash...\n", COLOR_YELLOW); + + writeClientCertHash(); + gfx_printf("%kWriting CAL0 hash...\n", COLOR_YELLOW); + + writeCal0Hash(); + + gfx_printf("\n%kIncognito done!\n\n", COLOR_GREEN); +} + +void cleanUp() +{ + + h_cfg.emummc_force_disable = emummc_load_cfg(); + //nx_emmc_gpt_free(&gpt); + // emummc_storage_end(&storage); } static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed) @@ -447,7 +386,7 @@ static inline u32 _read_le_u32(const void *buffer, u32 offset) (*(u8 *)(buffer + offset + 3) << 0x18); } -bool readData(u8 *buffer, u32 offset, u32 length) +bool readData(u8 *buffer, u32 offset, u32 length, u8 enc) { // u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE); @@ -492,16 +431,16 @@ bool readData(u8 *buffer, u32 offset, u32 length) u8 *tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE); - disk_read_prod(tmp, sector, sectorCount); + disk_read_prod(tmp, sector, sectorCount, enc); memcpy(buffer, tmp + newOffset, length); free(tmp); - return true; + return true; } -bool writeData(u8 *buffer, u32 offset, u32 length) +bool writeData(u8 *buffer, u32 offset, u32 length, u8 enc) { // u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE); @@ -539,9 +478,6 @@ bool writeData(u8 *buffer, u32 offset, u32 length) // free(tmp); - - - u32 sector = (offset / NX_EMMC_BLOCKSIZE); u32 newOffset = (offset % NX_EMMC_BLOCKSIZE); @@ -549,15 +485,15 @@ bool writeData(u8 *buffer, u32 offset, u32 length) u8 *tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE); - disk_read_prod(tmp, sector, sectorCount); + disk_read_prod(tmp, sector, sectorCount, 1); memcpy(tmp + newOffset, buffer, length); - disk_write_prod(tmp, sector, sectorCount); + disk_write_prod(tmp, sector, sectorCount, enc); free(tmp); - return true; + return true; } bool writeHash(u32 hashOffset, u32 offset, u32 sz) @@ -573,7 +509,7 @@ bool writeHash(u32 hashOffset, u32 offset, u32 sz) if (newOffset > 0 && newOffset + sz >= NX_EMMC_BLOCKSIZE) { u32 toRead = NX_EMMC_BLOCKSIZE - newOffset; - readData(buffer, offset, toRead); + readData(buffer, offset, toRead, ENCRYPTED); sha256_update(&ctx, buffer, toRead); sz -= toRead; @@ -583,7 +519,7 @@ bool writeHash(u32 hashOffset, u32 offset, u32 sz) while (sz > NX_EMMC_BLOCKSIZE) { - readData(buffer, offset, NX_EMMC_BLOCKSIZE); + readData(buffer, offset, NX_EMMC_BLOCKSIZE, ENCRYPTED); sha256_update(&ctx, buffer, NX_EMMC_BLOCKSIZE); sz -= NX_EMMC_BLOCKSIZE; @@ -593,13 +529,13 @@ bool writeHash(u32 hashOffset, u32 offset, u32 sz) if (sz > 0) { - readData(buffer, offset, sz); + readData(buffer, offset, sz, ENCRYPTED); sha256_update(&ctx, buffer, sz); } u8 hash[0x20]; sha256_final(&ctx, hash); - writeData(hash, hashOffset, 0x20); + writeData(hash, hashOffset, 0x20, ENCRYPTED); free(buffer); return true; @@ -618,7 +554,7 @@ bool verifyHash(u32 hashOffset, u32 offset, u32 sz) if (newOffset > 0 && sz >= NX_EMMC_BLOCKSIZE) { u32 toRead = NX_EMMC_BLOCKSIZE - newOffset; - readData(buffer, offset, toRead); + readData(buffer, offset, toRead, ENCRYPTED); sha256_update(&ctx, buffer, toRead); sz -= toRead; @@ -628,7 +564,7 @@ bool verifyHash(u32 hashOffset, u32 offset, u32 sz) while (sz > NX_EMMC_BLOCKSIZE) { - readData(buffer, offset, NX_EMMC_BLOCKSIZE); + readData(buffer, offset, NX_EMMC_BLOCKSIZE, ENCRYPTED); sha256_update(&ctx, buffer, NX_EMMC_BLOCKSIZE); sz -= NX_EMMC_BLOCKSIZE; @@ -638,7 +574,7 @@ bool verifyHash(u32 hashOffset, u32 offset, u32 sz) if (sz > 0) { - readData(buffer, offset, sz); + readData(buffer, offset, sz, ENCRYPTED); sha256_update(&ctx, buffer, sz); } u8 hash1[0x20]; @@ -646,20 +582,19 @@ bool verifyHash(u32 hashOffset, u32 offset, u32 sz) u8 hash2[0x20]; - readData(hash2, hashOffset, 0x20); + readData(hash2, hashOffset, 0x20, ENCRYPTED); if (memcmp(hash1, hash2, 0x20)) { EPRINTF("error: hash verification failed\n"); + gfx_hexdump(0, hash1, 0x20); + gfx_hexdump(0, hash2, 0x20); } else { result = true; } - gfx_hexdump(0, hash1, 0x20); - gfx_hexdump(0, hash2, 0x20); - free(buffer); return result; } @@ -667,14 +602,14 @@ bool verifyHash(u32 hashOffset, u32 offset, u32 sz) u32 certSize() { u32 buffer; - readData((u8 *)&buffer, 0x0AD0, sizeof(buffer)); + readData((u8 *)&buffer, 0x0AD0, sizeof(buffer), ENCRYPTED); return buffer; } u32 calibrationDataSize() { u32 buffer; - readData((u8 *)&buffer, 0x08, sizeof(buffer)); + readData((u8 *)&buffer, 0x08, sizeof(buffer), ENCRYPTED); return buffer; } @@ -701,23 +636,54 @@ bool verifyClientCertHash() bool verifyProdinfo() { - return verifyClientCertHash() && verifyCal0Hash(); - // bool r = verifyHash(0x12E0, 0xAE0, certSize()); // client cert hash - // r &= verifyHash(0x20, 0x40, calibrationDataSize()); // calibration hash - // return r; + gfx_printf("%kVerifying client cert hash and CAL0 hash...\n", COLOR_YELLOW); + + if (verifyClientCertHash() && verifyCal0Hash()) + { + char serial[15]; + readData((u8 *)serial, 0x250, 15, ENCRYPTED); + gfx_printf("%kVerification successful!\n%kNew Serial:%s\n", COLOR_GREEN, COLOR_BLUE, serial); + return true; + } + gfx_printf("%kVerification not successful!\nPlease restore backup!\n", COLOR_RED); + return false; +} + +void print_progress(size_t count, size_t max) +{ + const char prefix[] = "Progress: ["; + const char suffix[] = "]"; + const size_t prefix_length = sizeof(prefix) - 1; + const size_t suffix_length = sizeof(suffix) - 1; + char *buffer = calloc(max + prefix_length + suffix_length + 1, 1); // +1 for \0 + size_t i = 0; + + strcpy(buffer, prefix); + for (; i < max; ++i) + { + buffer[prefix_length + i] = i < count ? '#' : ' '; + } + + strcpy(&buffer[prefix_length + i], suffix); + gfx_printf("%k%s %d%%\n", COLOR_BLUE, buffer, (100 / max) * count); + free(buffer); } bool backupProdinfo() { - sd_mount(); - char* name; - if (!emu_cfg.enabled || h_cfg.emummc_force_disable){ + char *name; + if (!emu_cfg.enabled || h_cfg.emummc_force_disable) + { name = "sd:/prodinfo_sysnand.bin"; - } else { - - name = "sd:/prodinfo_emunand.bin"; } + else + { + + name = "sd:/prodinfo_emunand.bin"; + } + + gfx_printf("%kBacking up %s...\n", COLOR_YELLOW, name); if (f_stat(name, NULL)) { @@ -725,48 +691,49 @@ bool backupProdinfo() } FIL fp; f_open(&fp, name, FA_CREATE_ALWAYS | FA_WRITE); - u8 bufferNX[NX_EMMC_BLOCKSIZE]; + u8 *bufferNX = (u8 *)malloc(NX_EMMC_BLOCKSIZE); u32 size = 0x3FBC00; + + u8 percentDone = 0; u32 offset = 0; + const u8 step = 5; + + u32 iterations = size / NX_EMMC_BLOCKSIZE; + u32 printCount = iterations / (100 / step); + + u32 x = gfx_con.x; + u32 y = gfx_con.y; + while (size > NX_EMMC_BLOCKSIZE) { - readData(bufferNX, offset, NX_EMMC_BLOCKSIZE); + readData(bufferNX, offset, NX_EMMC_BLOCKSIZE, ENCRYPTED); f_write(&fp, bufferNX, NX_EMMC_BLOCKSIZE, NULL); f_sync(&fp); + offset += NX_EMMC_BLOCKSIZE; size -= NX_EMMC_BLOCKSIZE; + if (iterations % printCount == 0) + { + print_progress(percentDone / step, 100 / step); + gfx_con.x = x; + gfx_con.y = y; + percentDone += step; + } + iterations--; } if (size > 0) { - readData(bufferNX, offset, size); + readData(bufferNX, offset, size, ENCRYPTED); f_write(&fp, bufferNX, size, NULL); f_sync(&fp); - } + print_progress(100 / step, 100 / step); + f_close(&fp); + free(bufferNX); + gfx_printf("%k\nBackup %s done!\n\n", COLOR_GREEN, name); - 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; - // } - - // f_close(&fp); - - // gfx_printf("\n%kBackup encrypted done!", colors[4]); return true; } @@ -774,14 +741,18 @@ bool restoreProdinfo() { sd_mount(); - char* name; - if (!emu_cfg.enabled || h_cfg.emummc_force_disable){ + char *name; + if (!emu_cfg.enabled || h_cfg.emummc_force_disable) + { name = "sd:/prodinfo_sysnand.bin"; - } else { - - name = "sd:/prodinfo_emunand.bin"; + } + else + { + + name = "sd:/prodinfo_emunand.bin"; } + gfx_printf("%kRestoring %s...\n", COLOR_YELLOW, name); FIL fp; if (f_open(&fp, name, FA_READ) != FR_OK) @@ -792,35 +763,41 @@ bool restoreProdinfo() u8 bufferNX[NX_EMMC_BLOCKSIZE]; u32 size = 0x3FBC00; + + u8 percentDone = 0; u32 offset = 0; - while (size > 0) + const u8 step = 5; + + u32 iterations = size / NX_EMMC_BLOCKSIZE; + u32 printCount = iterations / (100 / step); + + u32 x = gfx_con.x; + u32 y = gfx_con.y; + + while (size > NX_EMMC_BLOCKSIZE) { 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; + writeData(bufferNX, offset, NX_EMMC_BLOCKSIZE, ENCRYPTED); + offset += NX_EMMC_BLOCKSIZE; size -= NX_EMMC_BLOCKSIZE; + if (iterations % printCount == 0) + { + print_progress(percentDone / step, 100 / step); + gfx_con.x = x; + gfx_con.y = y; + percentDone += step; + } + iterations--; } - // 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); - // } + if (size > 0) + { + f_read(&fp, bufferNX, size, NULL); + writeData(bufferNX, offset, size, ENCRYPTED); + } + print_progress(100 / step, 100 / step); f_close(&fp); - gfx_printf("%kRestore %s done!\n\n", COLOR_GREEN, name); + gfx_printf("%kRestore %s done!\n\n", COLOR_GREEN, name); return true; } - -// 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; -// } diff --git a/source/keys/keys.h b/source/keys/keys.h index defbda6..6367f54 100644 --- a/source/keys/keys.h +++ b/source/keys/keys.h @@ -20,9 +20,10 @@ #include "../utils/types.h" bool dump_keys(); +void incognito(); void cleanUp(); -bool readData(u8 *buffer, u32 offset, u32 length); -bool writeData(u8 *buffer, u32 offset, u32 length); +bool readData(u8 *buffer, u32 offset, u32 length, u8 enc); +bool writeData(u8 *buffer, u32 offset, u32 length, u8 enc); bool writeClientCertHash(); bool writeCal0Hash(); bool verifyProdinfo(); diff --git a/source/libs/fatfs/diskio.c b/source/libs/fatfs/diskio.c index 5abff87..f902b3d 100644 --- a/source/libs/fatfs/diskio.c +++ b/source/libs/fatfs/diskio.c @@ -133,10 +133,17 @@ DRESULT disk_read_prod ( BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Start sector in LBA */ - UINT count /* Number of sectors to read */ + UINT count, /* Number of sectors to read */ + BYTE enc ) { + if(enc == 0 ){ + if (nx_emmc_part_read(&storage, prodinfo_part, sector, count, buff)) { + return RES_OK; + } + return RES_ERROR; + } __attribute__ ((aligned (16))) static u8 tweak[0x10]; __attribute__ ((aligned (16))) static u64 prev_cluster = -1; @@ -171,10 +178,15 @@ DRESULT disk_write_prod ( BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Start sector in LBA */ - UINT count /* Number of sectors to read */ + UINT count, /* Number of sectors to read */ + BYTE enc ) { + if(enc == 0){ + nx_emmc_part_write(&storage, prodinfo_part, sector, count, buff); + return RES_OK; + } __attribute__ ((aligned (16))) static u8 tweak[0x10]; __attribute__ ((aligned (16))) static u64 prev_cluster = -1; diff --git a/source/libs/fatfs/diskio.h b/source/libs/fatfs/diskio.h index 7791f45..7f13da4 100644 --- a/source/libs/fatfs/diskio.h +++ b/source/libs/fatfs/diskio.h @@ -33,8 +33,8 @@ typedef enum { DSTATUS disk_initialize (BYTE pdrv); DSTATUS disk_status (BYTE pdrv); DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); -DRESULT disk_read_prod (BYTE *buff, DWORD sector, UINT count); -DRESULT disk_write_prod (BYTE *buff, DWORD sector, UINT count); +DRESULT disk_read_prod (BYTE *buff, DWORD sector, UINT count, BYTE enc); +DRESULT disk_write_prod (BYTE *buff, DWORD sector, UINT count, BYTE enc); DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); diff --git a/source/main.c b/source/main.c index ed56c8c..d18c2e1 100644 --- a/source/main.c +++ b/source/main.c @@ -38,11 +38,11 @@ sdmmc_t sd_sdmmc; sdmmc_storage_t sd_storage; -__attribute__ ((aligned (16))) FATFS sd_fs; +__attribute__((aligned(16))) FATFS sd_fs; static bool sd_mounted; hekate_config h_cfg; -boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg; +boot_cfg_t __attribute__((section("._boot_cfg"))) b_cfg; bool sd_mount() { @@ -124,12 +124,12 @@ int sd_save_to_file(void *buf, u32 size, const char *filename) } // This is a safe and unused DRAM region for our payloads. -#define RELOC_META_OFF 0x7C -#define PATCHED_RELOC_SZ 0x94 +#define RELOC_META_OFF 0x7C +#define PATCHED_RELOC_SZ 0x94 #define PATCHED_RELOC_STACK 0x40007000 -#define COREBOOT_ADDR (0xD0000000 - 0x100000) -#define CBFS_DRAM_EN_ADDR 0x4003e000 -#define CBFS_DRAM_MAGIC 0x4452414D // "DRAM" +#define COREBOOT_ADDR (0xD0000000 - 0x100000) +#define CBFS_DRAM_EN_ADDR 0x4003e000 +#define CBFS_DRAM_MAGIC 0x4452414D // "DRAM" void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size) { @@ -139,8 +139,8 @@ void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size) relocator->start = payload_dst - ALIGN(PATCHED_RELOC_SZ, 0x10); relocator->stack = PATCHED_RELOC_STACK; - relocator->end = payload_dst + payload_size; - relocator->ep = payload_dst; + relocator->end = payload_dst + payload_size; + relocator->ep = payload_dst; if (payload_size == 0x7000) { @@ -149,89 +149,114 @@ void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size) } } -void dump_sysnand() +void incognito_sysnand() { + h_cfg.emummc_force_disable = true; b_cfg.extra_cfg &= ~EXTRA_CFG_DUMP_EMUMMC; - dump_keys(); + if (!dump_keys()) + { + cleanUp(); + return; + } + incognito(); verifyProdinfo(); cleanUp(); - // verifyProdinfo(); - - gfx_printf("\n%kPress any key to return to the main menu.", COLOR_GREEN); - // cleanUp(); + gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE); btn_wait(); } -void dump_emunand() +void incognito_emunand() { if (h_cfg.emummc_force_disable) return; emu_cfg.enabled = 1; b_cfg.extra_cfg |= EXTRA_CFG_DUMP_EMUMMC; - dump_keys(); + if (!dump_keys()) + { + cleanUp(); + return; + } + incognito(); verifyProdinfo(); cleanUp(); - gfx_printf("\n%kPress any key to return to the main menu.", COLOR_GREEN); - btn_wait(); + gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE); + btn_wait(); } -void backup_sysnand(){ - h_cfg.emummc_force_disable = true; +void backup_sysnand() +{ + h_cfg.emummc_force_disable = true; b_cfg.extra_cfg &= ~EXTRA_CFG_DUMP_EMUMMC; - dump_keys(); - + if (!dump_keys()) + { + cleanUp(); + return; + } backupProdinfo(); - verifyProdinfo(); cleanUp(); - gfx_printf("\n%kPress any key to return to the main menu.", COLOR_GREEN); - btn_wait(); + gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE); + btn_wait(); } -void backup_emunand(){ -if (h_cfg.emummc_force_disable) +void backup_emunand() +{ + if (h_cfg.emummc_force_disable) return; emu_cfg.enabled = 1; b_cfg.extra_cfg |= EXTRA_CFG_DUMP_EMUMMC; - dump_keys(); + if (!dump_keys()) + { + cleanUp(); + return; + } backupProdinfo(); - verifyProdinfo(); cleanUp(); - gfx_printf("\n%kPress any key to return to the main menu.", COLOR_GREEN); - btn_wait(); + gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE); + btn_wait(); } -void restore_sysnand(){ - h_cfg.emummc_force_disable = true; +void restore_sysnand() +{ + h_cfg.emummc_force_disable = true; b_cfg.extra_cfg &= ~EXTRA_CFG_DUMP_EMUMMC; - dump_keys(); + if (!dump_keys()) + { + cleanUp(); + return; + } restoreProdinfo(); - verifyProdinfo(); + verifyProdinfo(); cleanUp(); - gfx_printf("\n%kPress any key to return to the main menu.", COLOR_GREEN); - btn_wait(); + gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE); + btn_wait(); } -void restore_emunand(){ -if (h_cfg.emummc_force_disable) +void restore_emunand() +{ + if (h_cfg.emummc_force_disable) return; emu_cfg.enabled = 1; b_cfg.extra_cfg |= EXTRA_CFG_DUMP_EMUMMC; - dump_keys(); + if (!dump_keys()) + { + cleanUp(); + return; + } restoreProdinfo(); - verifyProdinfo(); + verifyProdinfo(); cleanUp(); - gfx_printf("\n%kPress any key to return to the main menu.", COLOR_GREEN); - btn_wait(); + gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE); + btn_wait(); } ment_t ment_top[] = { - MDEF_HANDLER("Incognito (SysNAND)", dump_sysnand, COLOR_ORANGE), - MDEF_HANDLER("Incognito (emuMMC)", dump_emunand, COLOR_ORANGE), + MDEF_HANDLER("Incognito (SysNAND)", incognito_sysnand, COLOR_ORANGE), + MDEF_HANDLER("Incognito (emuMMC)", incognito_emunand, COLOR_ORANGE), MDEF_CAPTION("", COLOR_YELLOW), MDEF_HANDLER("Backup (SysNAND)", backup_sysnand, COLOR_ORANGE), MDEF_HANDLER("Backup (emuMMC)", backup_emunand, COLOR_ORANGE), @@ -239,16 +264,15 @@ ment_t ment_top[] = { MDEF_HANDLER("Restore (SysNAND)", restore_sysnand, COLOR_ORANGE), MDEF_HANDLER("Restore (emuMMC)", restore_emunand, COLOR_ORANGE), MDEF_CAPTION("", COLOR_YELLOW), - MDEF_CAPTION("---------------", COLOR_YELLOW), - MDEF_HANDLER("Reboot (Normal)", reboot_normal, COLOR_GREEN), - MDEF_HANDLER("Reboot (RCM)", reboot_rcm, COLOR_BLUE), - MDEF_HANDLER("Power off", power_off, COLOR_VIOLET), - MDEF_END() -}; + MDEF_CAPTION("---------------", COLOR_YELLOW), + MDEF_HANDLER("Reboot (Normal)", reboot_normal, COLOR_GREEN), + MDEF_HANDLER("Reboot (RCM)", reboot_rcm, COLOR_BLUE), + MDEF_HANDLER("Power off", power_off, COLOR_VIOLET), + MDEF_END()}; -menu_t menu_top = { ment_top, NULL, 0, 0 }; +menu_t menu_top = {ment_top, NULL, 0, 0}; -#define IPL_STACK_TOP 0x4003F000 +#define IPL_STACK_TOP 0x4003F000 #define IPL_HEAP_START 0x90020000 extern void pivot_stack(u32 stack_top); diff --git a/source/storage/emummc.c b/source/storage/emummc.c index a07d9ed..0c6acaa 100644 --- a/source/storage/emummc.c +++ b/source/storage/emummc.c @@ -47,6 +47,7 @@ bool emummc_load_cfg() emu_cfg.file_based_part_size = 0; emu_cfg.active_part = 0; emu_cfg.fs_ver = 0; + free(emu_cfg.emummc_file_based_path); emu_cfg.emummc_file_based_path = (char *)malloc(0x80); LIST_INIT(ini_sections);