diff --git a/source/tegraexplorer/common/common.h b/source/tegraexplorer/common/common.h index 266e70b..8b58222 100644 --- a/source/tegraexplorer/common/common.h +++ b/source/tegraexplorer/common/common.h @@ -116,3 +116,5 @@ extern gpt_entry_rule gpt_fs_rules[]; extern menu_entry mmcmenu_start[]; extern menu_entry mmcmenu_filemenu[]; + +extern menu_entry fwDump_typeMenu[]; \ No newline at end of file diff --git a/source/tegraexplorer/common/structs.c b/source/tegraexplorer/common/structs.c index 4acd674..98173f8 100644 --- a/source/tegraexplorer/common/structs.c +++ b/source/tegraexplorer/common/structs.c @@ -92,4 +92,11 @@ menu_entry mmcmenu_filemenu[] = { {NULL, COLOR_VIOLET, {ISSKIP | ISMENU}}, {"\nBack", COLOR_WHITE, {ISMENU}}, {"Dump to SD", COLOR_YELLOW, {ISMENU}} +}; + +menu_entry fwDump_typeMenu[] = { + {"Back\n", COLOR_WHITE, {ISMENU}}, + {"Firmware format type:", COLOR_WHITE, {ISMENU | ISSKIP}}, + {"Daybreak (prod.keys required!)", COLOR_BLUE, {ISMENU}}, + {"ChoiNX", COLOR_VIOLET, {ISMENU}} }; \ No newline at end of file diff --git a/source/tegraexplorer/emmc/emmc.c b/source/tegraexplorer/emmc/emmc.c index afea163..50c2a7b 100644 --- a/source/tegraexplorer/emmc/emmc.c +++ b/source/tegraexplorer/emmc/emmc.c @@ -218,9 +218,6 @@ int dump_biskeys(){ //sdmmc_storage_set_mmc_partition(&storage, 0); //nx_emmc_gpt_parse(&sys_gpt, &storage); - - se_aes_key_set(8, bis_key[2] + 0x00, 0x10); - se_aes_key_set(9, bis_key[2] + 0x10, 0x10); pkg1inf.ver = pkg1_id->kb; strcpy(pkg1inf.id, pkg1_id->id); diff --git a/source/tegraexplorer/fs/keys.c b/source/tegraexplorer/fs/keys.c new file mode 100644 index 0000000..403ac56 --- /dev/null +++ b/source/tegraexplorer/fs/keys.c @@ -0,0 +1,62 @@ +#include "keys.h" +#include "../../utils/types.h" +#include "../../libs/fatfs/ff.h" +#include "../../sec/se.h" +#include "../../mem/heap.h" +#include "../gfx/gfxutils.h" +#include "../../config/ini.h" +#include "../common/common.h" +#include + +char *getKey(const char *search, link_t *inilist){ + LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, inilist, link){ + if (ini_sec->type == INI_CHOICE){ + LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link) + { + if (!strcmp(search, kv->key)) + return kv->val; + } + } + } + return NULL; +} + +u8 getHexSingle(const char c) { + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; +} + +u8 *getHex(const char *in){ + u32 len = strlen(in), count = 0; + u8 *out = calloc(len / 2, sizeof(u8)); + + for (u32 i = 0; i < len; i += 2){ + out[count++] = (u8)(getHexSingle(in[i]) << 4) | (getHexSingle(in[i + 1])); + } + + return out; +} + +u8 *GetKey(const char *keypath, const char *keyName){ + LIST_INIT(inilist); + char *key; + u8 *hex = NULL; + + if (!ini_parse(&inilist, keypath, false)){ + gfx_errDisplay("GetKey", ERR_INI_PARSE_FAIL, 1); + goto out_free; + } + + if ((key = getKey(keyName, &inilist)) == NULL){ + gfx_errDisplay("GetKey", ERR_INI_PARSE_FAIL, 2); + goto out_free; + } + + hex = getHex(key); + +out_free:; + list_empty(&inilist); + return hex; +} \ No newline at end of file diff --git a/source/tegraexplorer/fs/keys.h b/source/tegraexplorer/fs/keys.h new file mode 100644 index 0000000..53dc0a8 --- /dev/null +++ b/source/tegraexplorer/fs/keys.h @@ -0,0 +1,4 @@ +#pragma once +#include "../../utils/types.h" + +u8 *GetKey(const char *keypath, const char *keyName); \ No newline at end of file diff --git a/source/tegraexplorer/fs/nca.c b/source/tegraexplorer/fs/nca.c new file mode 100644 index 0000000..685614e --- /dev/null +++ b/source/tegraexplorer/fs/nca.c @@ -0,0 +1,46 @@ +#include "nca.h" +#include "keys.h" +#include "../../utils/types.h" +#include "../../libs/fatfs/ff.h" +#include "../../sec/se.h" +#include "../../mem/heap.h" +#include "../gfx/gfxutils.h" +#include "../../config/ini.h" +#include "../common/common.h" +#include + +int SetHeaderKey(){ + u8 *header_key = GetKey("sd:/switch/prod.keys", "header_key"); + + if (header_key == NULL) + return -1; + + se_aes_key_set(4, header_key + 0x00, 0x10); + se_aes_key_set(5, header_key + 0x10, 0x10); + + return 0; +} + +int GetNcaType(char *ncaPath){ + FIL fp; + u32 read_bytes = 0; + + if (f_open(&fp, ncaPath, FA_READ | FA_OPEN_EXISTING)) + return -1; + + u8 *dec_header = (u8*)malloc(0x600); + + if (f_lseek(&fp, 0x200) || f_read(&fp, dec_header, 32, &read_bytes) || read_bytes != 32){ + f_close(&fp); + free(dec_header); + return -1; + } + + se_aes_xts_crypt(5,4,0,1,dec_header + 0x200, dec_header, 32, 1); + + u8 ContentType = dec_header[0x205]; + + f_close(&fp); + free(dec_header); + return ContentType; +} \ No newline at end of file diff --git a/source/tegraexplorer/fs/nca.h b/source/tegraexplorer/fs/nca.h new file mode 100644 index 0000000..c63f586 --- /dev/null +++ b/source/tegraexplorer/fs/nca.h @@ -0,0 +1,4 @@ +#pragma once + +int GetNcaType(char *ncaPath); +int SetHeaderKey(); \ No newline at end of file diff --git a/source/tegraexplorer/fs/savesign.c b/source/tegraexplorer/fs/savesign.c index af8167f..3594a6c 100644 --- a/source/tegraexplorer/fs/savesign.c +++ b/source/tegraexplorer/fs/savesign.c @@ -1,4 +1,5 @@ #include "savesign.h" +#include "keys.h" #include "../../utils/types.h" #include "../../libs/fatfs/ff.h" #include "../../sec/se.h" @@ -62,62 +63,15 @@ out_free:; return success; } - -char *getKey(const char *search, link_t *inilist){ - LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, inilist, link){ - if (ini_sec->type == INI_CHOICE){ - LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link) - { - if (!strcmp(search, kv->key)) - return kv->val; - } - } - } - return NULL; -} - -u8 getHexSingle(const char c) { - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; -} - -u8 *getHex(const char *in){ - u32 len = strlen(in), count = 0; - u8 *out = calloc(len / 2, sizeof(u8)); - - for (u32 i = 0; i < len; i += 2){ - out[count++] = (u8)(getHexSingle(in[i]) << 4) | (getHexSingle(in[i + 1])); - } - - return out; -} - bool save_sign(const char *keypath, const char *savepath){ - LIST_INIT(inilist); - char *key; - u8 *hex; - bool success = false; + u8 *key = GetKey(keypath, "save_mac_key"); - if (!ini_parse(&inilist, keypath, false)){ - gfx_errDisplay("save_sign", ERR_INI_PARSE_FAIL, 1); - goto out_free; + if (key == NULL){ + return false; } - if ((key = getKey("save_mac_key", &inilist)) == NULL){ - gfx_errDisplay("save_sign", ERR_INI_PARSE_FAIL, 2); - goto out_free; - } + if (!save_commit(savepath, key)) + return false; - hex = getHex(key); - - if (!save_commit(savepath, hex)) - goto out_free; - - success = true; - -out_free:; - list_empty(&inilist); - return success; + return true; } \ No newline at end of file diff --git a/source/tegraexplorer/mainmenu.c b/source/tegraexplorer/mainmenu.c index 90baad2..498ab4b 100644 --- a/source/tegraexplorer/mainmenu.c +++ b/source/tegraexplorer/mainmenu.c @@ -60,7 +60,10 @@ void MainMenu_Tools(){ displaygpio(); break; case TOOLS_DUMPFIRMWARE: - dumpfirmware(SYSMMC); + res = menu_make(fwDump_typeMenu, 4, "-- Fw Type --"); + if (res >= 2) + dumpfirmware(SYSMMC, (res == 2)); + break; } } diff --git a/source/tegraexplorer/utils/tools.c b/source/tegraexplorer/utils/tools.c index 6cbafb5..4a2203f 100644 --- a/source/tegraexplorer/utils/tools.c +++ b/source/tegraexplorer/utils/tools.c @@ -17,6 +17,7 @@ #include "../fs/fsutils.h" #include "../../mem/heap.h" #include "../utils/utils.h" +#include "../fs/nca.h" extern bool sd_mount(); extern void sd_unmount(); @@ -93,7 +94,9 @@ void displaygpio(){ } } -int dumpfirmware(int mmc){ + +// bad code ahead aaaa +int dumpfirmware(int mmc, bool daybreak){ DIR dir; FILINFO fno; bool fail = false; @@ -107,6 +110,22 @@ int dumpfirmware(int mmc){ connect_mmc(mmc); mount_mmc("SYSTEM", 2); + if (daybreak){ + if (!fsutil_checkfile("sd:/switch/prod.keys")){ + SWAPCOLOR(COLOR_RED); + gfx_printf("prod.keys not found.\nPress any button to exit"); + hidWait(); + return true; + } + + if (SetHeaderKey()){ + SWAPCOLOR(COLOR_RED); + gfx_printf("Failed to find header key.\nPress any button to exit"); + hidWait(); + return true; + } + } + gfx_printf("PKG1 version: %d\n", pkg1.ver); gfx_printf("Creating folders...\n"); @@ -115,7 +134,24 @@ int dumpfirmware(int mmc){ sdbase = calloc(32 + strlen(pkg1.id), sizeof(char)); sprintf(sdbase, "sd:/tegraexplorer/Firmware/%d (%s)", pkg1.ver, pkg1.id); - gfx_printf("Out: %s\n", sdbase); + + if (fsutil_checkfile(sdbase)){ + SWAPCOLOR(COLOR_RED); + gfx_printf("Destination folder already exists.\nPress X to delete this folder, any other button to cancel\nPath: %s", sdbase); + + Inputs *input = hidWait(); + if (!input->x){ + free(sdbase); + return true; + } + else { + SWAPCOLOR(COLOR_WHITE); + gfx_printf("\nDeleting folder..\n"); + fsact_del_recursive(sdbase); + } + } + + gfx_printf("\rOut: %s\n", sdbase); f_mkdir(sdbase); if ((ret = f_opendir(&dir, sysbase))) @@ -127,16 +163,39 @@ int dumpfirmware(int mmc){ printerrors = 0; while(!f_readdir(&dir, &fno) && fno.fname[0] && !fail){ - utils_copystring(fsutil_getnextloc(sdbase, fno.fname), &sdpath); utils_copystring(fsutil_getnextloc(sysbase, fno.fname), &syspathtemp); if (fno.fattrib & AM_DIR){ utils_copystring(fsutil_getnextloc(syspathtemp, "00"), &syspath); - free(syspathtemp); } else syspath = syspathtemp; + if (daybreak){ + u8 ContentType = GetNcaType(syspath); + + if (ContentType < 0){ + fail = true; + continue; + } + + char *temp; + utils_copystring(fsutil_getnextloc(sdbase, fno.fname), &temp); + + if (ContentType == 0x01){ + sdpath = calloc(strlen(temp) + 6, 1); + strcpy(sdpath, temp); + memcpy(sdpath + strlen(temp) - 4, ".cnmt.nca", 10); + free(temp); + } + else { + sdpath = temp; + } + } + else + utils_copystring(fsutil_getnextloc(sdbase, fno.fname), &sdpath); + + ret = fsact_copy(syspath, sdpath, 0); gfx_printf("%d %s\r", ++amount, fno.fname); @@ -145,7 +204,9 @@ int dumpfirmware(int mmc){ fail = true; free(sdpath); - free(syspath); + free(syspathtemp); + if (syspath != syspathtemp) + free(syspath); } printerrors = 1; diff --git a/source/tegraexplorer/utils/tools.h b/source/tegraexplorer/utils/tools.h index eb62908..b7408c6 100644 --- a/source/tegraexplorer/utils/tools.h +++ b/source/tegraexplorer/utils/tools.h @@ -1,6 +1,7 @@ #pragma once +#include "../../utils/types.h" void displayinfo(); void displaygpio(); int format(int mode); -int dumpfirmware(int mmc); \ No newline at end of file +int dumpfirmware(int mmc, bool daybreak); \ No newline at end of file