forked from Mirror/GodMode9
Rewritten support file handling
Support files are now also accepted from CTRNAND.
This commit is contained in:
parent
d8521dfdb9
commit
1a63575caa
@ -33,11 +33,8 @@
|
||||
|
||||
#define STATIC_ASSERT(...) \
|
||||
_Static_assert((__VA_ARGS__), #__VA_ARGS__)
|
||||
|
||||
// input / output paths
|
||||
#define SUPPORT_PATH "0:/gm9/support"
|
||||
#define SCRIPT_PATH "0:/gm9/scripts"
|
||||
#define PAYLOAD_PATH "0:/gm9/payloads"
|
||||
|
||||
// standard output path (support file paths are in support.h)
|
||||
#define OUTPUT_PATH "0:/gm9/out"
|
||||
|
||||
// buffer area defines (in use by godmode.c)
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "aes.h"
|
||||
#include "sha.h"
|
||||
#include "ff.h"
|
||||
#include "vram0.h"
|
||||
#include "support.h"
|
||||
|
||||
typedef struct {
|
||||
u8 slot; // keyslot, 0x00...0x39
|
||||
@ -120,19 +120,7 @@ u32 LoadKeyDb(const char* path_db, AesKeyInfo* keydb, u32 bsize) {
|
||||
fsize = 0;
|
||||
f_close(&fp);
|
||||
}
|
||||
} else {
|
||||
// check for hardcoded key database
|
||||
u64 aeskeydb_bin_size = 0;
|
||||
void* aeskeydb_bin = FindVTarFileInfo(KEYDB_NAME, &aeskeydb_bin_size);
|
||||
fsize = (aeskeydb_bin_size <= bsize) ? aeskeydb_bin_size : 0;
|
||||
if (fsize) memcpy(keydb, aeskeydb_bin, aeskeydb_bin_size);
|
||||
|
||||
// try to load aeskeydb.bin file
|
||||
if (f_open(&fp, SUPPORT_PATH "/" KEYDB_NAME, FA_READ | FA_OPEN_EXISTING) == FR_OK) {
|
||||
if ((f_read(&fp, keydb, bsize, &fsize) != FR_OK) || (fsize >= bsize)) fsize = 0;
|
||||
f_close(&fp);
|
||||
}
|
||||
}
|
||||
} else fsize = LoadSupportFile(KEYDB_NAME, keydb, bsize); // load key database support file
|
||||
|
||||
u32 nkeys = 0;
|
||||
if (fsize && !(fsize % sizeof(AesKeyInfo)))
|
||||
@ -173,15 +161,10 @@ u32 LoadKeyFromFile(void* key, u32 keyslot, char type, char* id)
|
||||
|
||||
// load legacy slot0x??Key?.bin file instead
|
||||
if (!found && (type != 'I')) {
|
||||
char path[64];
|
||||
FIL fp;
|
||||
UINT btr;
|
||||
snprintf(path, 64, "%s/slot0x%02lXKey%s%s.bin", SUPPORT_PATH, keyslot,
|
||||
char fname[64];
|
||||
snprintf(fname, 64, "slot0x%02lXKey%s%s.bin", keyslot,
|
||||
(type == 'X') ? "X" : (type == 'Y') ? "Y" : (type == 'I') ? "IV" : "", (id) ? id : "");
|
||||
if (f_open(&fp, path, FA_READ | FA_OPEN_EXISTING) == FR_OK) {
|
||||
found = ((f_read(&fp, key, 16, &btr) == FR_OK) && (btr == 16));
|
||||
f_close(&fp);
|
||||
}
|
||||
found = (LoadSupportFile(fname, key, 16) == 16);
|
||||
}
|
||||
|
||||
// key still not found (duh)
|
||||
@ -254,7 +237,7 @@ u32 InitKeyDb(const char* path)
|
||||
|
||||
u32 CheckRecommendedKeyDb(const char* path)
|
||||
{
|
||||
// SHA-256 of the reommended aeskeydb.bin file
|
||||
// SHA-256 of the recommended aeskeydb.bin file
|
||||
// equals MD5 A5B28945A7C051D7A0CD18AF0E580D1B
|
||||
const u8 recommended_sha[0x20] = {
|
||||
0x40, 0x76, 0x54, 0x3D, 0xA3, 0xFF, 0x91, 0x1C, 0xE1, 0xCC, 0x4E, 0xC7, 0x2F, 0x92, 0xE4, 0xB7,
|
||||
|
75
arm9/source/filesys/support.c
Normal file
75
arm9/source/filesys/support.c
Normal file
@ -0,0 +1,75 @@
|
||||
#include "support.h"
|
||||
#include "fsutil.h" // only for file selector
|
||||
#include "vram0.h"
|
||||
#include "vff.h"
|
||||
|
||||
#define SUPPORT_FILE_PATHS "0:/gm9/support", "1:/gm9/support" // we also check the VRAM TAR first
|
||||
#define SUPPORT_DIR_PATHS "V:", "0:/gm9", "1:/gm9"
|
||||
|
||||
|
||||
bool CheckSupportFile(const char* fname)
|
||||
{
|
||||
// try VRAM0 first
|
||||
if (FindVTarFileInfo(fname, NULL))
|
||||
return true;
|
||||
|
||||
// try support file paths
|
||||
const char* base_paths[] = { SUPPORT_FILE_PATHS };
|
||||
for (u32 i = 0; i < countof(base_paths); i++) {
|
||||
char path[256];
|
||||
snprintf(path, 256, "%s/%s", base_paths[i], fname);
|
||||
if (fvx_stat(path, NULL) == FR_OK)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t LoadSupportFile(const char* fname, void* buffer, size_t max_len)
|
||||
{
|
||||
// try VRAM0 first
|
||||
u64 len64 = 0;
|
||||
void* data = FindVTarFileInfo(fname, &len64);
|
||||
if (data && len64 && (len64 < max_len)) {
|
||||
memcpy(buffer, data, len64);
|
||||
return (size_t) len64;
|
||||
}
|
||||
|
||||
// try support file paths
|
||||
const char* base_paths[] = { SUPPORT_FILE_PATHS };
|
||||
for (u32 i = 0; i < countof(base_paths); i++) {
|
||||
UINT len32;
|
||||
char path[256];
|
||||
snprintf(path, 256, "%s/%s", base_paths[i], fname);
|
||||
if (fvx_qread(path, buffer, 0, max_len, &len32) == FR_OK)
|
||||
return len32;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool GetSupportDir(char* path, const char* dname)
|
||||
{
|
||||
const char* base_paths[] = { SUPPORT_DIR_PATHS };
|
||||
for (u32 i = 0; i < countof(base_paths); i++) {
|
||||
FILINFO fno;
|
||||
snprintf(path, 256, "%s/%s", base_paths[i], dname);
|
||||
if ((fvx_stat(path, &fno) == FR_OK) && (fno.fattrib & AM_DIR))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckSupportDir(const char* dname)
|
||||
{
|
||||
char path[256];
|
||||
return GetSupportDir(path, dname);
|
||||
}
|
||||
|
||||
bool FileSelectorSupport(char* result, const char* text, const char* dname, const char* pattern, bool hide_ext, bool no_dirs)
|
||||
{
|
||||
char path[256];
|
||||
if (!GetSupportDir(path, dname)) return false;
|
||||
return FileSelector(result, text, path, pattern, hide_ext, no_dirs);
|
||||
}
|
13
arm9/source/filesys/support.h
Normal file
13
arm9/source/filesys/support.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
// scripts / payloads dir names
|
||||
#define SCRIPTS_DIR "scripts"
|
||||
#define PAYLOADS_DIR "payloads"
|
||||
|
||||
bool CheckSupportFile(const char* fname);
|
||||
size_t LoadSupportFile(const char* fname, void* buffer, size_t max_len);
|
||||
|
||||
bool CheckSupportDir(const char* fpath);
|
||||
bool FileSelectorSupport(char* result, const char* text, const char* dname, const char* pattern, bool hide_ext, bool no_dirs);
|
@ -1,4 +1,5 @@
|
||||
#include "ncch.h"
|
||||
#include "support.h"
|
||||
#include "keydb.h"
|
||||
#include "aes.h"
|
||||
#include "sha.h"
|
||||
@ -53,10 +54,6 @@ u32 GetNcchSeed(u8* seed, NcchHeader* ncch) {
|
||||
static u8 lseed[16+8] = { 0 }; // seed plus title ID for easy validation
|
||||
u64 titleId = ncch->programId;
|
||||
u32 hash_seed = ncch->hash_seed;
|
||||
|
||||
UINT btr = 0;
|
||||
FIL file;
|
||||
char path[128];
|
||||
u32 sha256sum[8];
|
||||
|
||||
memcpy(lseed+16, &(ncch->programId), 8);
|
||||
@ -69,7 +66,11 @@ u32 GetNcchSeed(u8* seed, NcchHeader* ncch) {
|
||||
// try to grab the seed from NAND database
|
||||
const u32 seed_offset[2] = {SEEDSAVE_AREA_OFFSETS};
|
||||
const char* nand_drv[] = {"1:", "4:"}; // SysNAND and EmuNAND
|
||||
for (u32 i = 0; i < (sizeof(nand_drv)/sizeof(char*)); i++) {
|
||||
for (u32 i = 0; i < countof(nand_drv); i++) {
|
||||
UINT btr = 0;
|
||||
FIL file;
|
||||
char path[128];
|
||||
|
||||
// grab the key Y from movable.sed
|
||||
u8 movable_keyy[16];
|
||||
snprintf(path, 128, "%s/private/movable.sed", nand_drv[i]);
|
||||
@ -118,20 +119,17 @@ u32 GetNcchSeed(u8* seed, NcchHeader* ncch) {
|
||||
}
|
||||
|
||||
// not found -> try seeddb.bin
|
||||
if (f_open(&file, SUPPORT_PATH "/" SEEDDB_NAME, FA_READ | FA_OPEN_EXISTING) == FR_OK) {
|
||||
SeedInfo* seeddb = (SeedInfo*) (TEMP_BUFFER + (TEMP_BUFFER_SIZE/2));
|
||||
f_read(&file, seeddb, TEMP_BUFFER_SIZE / 2, &btr);
|
||||
f_close(&file);
|
||||
if (seeddb->n_entries <= (btr - 16) / 32) { // check filesize / seeddb size
|
||||
for (u32 s = 0; s < seeddb->n_entries; s++) {
|
||||
if (titleId != seeddb->entries[s].titleId)
|
||||
continue;
|
||||
memcpy(lseed, seeddb->entries[s].seed, 16);
|
||||
sha_quick(sha256sum, lseed, 16 + 8, SHA256_MODE);
|
||||
if (hash_seed == sha256sum[0]) {
|
||||
memcpy(seed, lseed, 16);
|
||||
return 0; // found!
|
||||
}
|
||||
SeedInfo* seeddb = (SeedInfo*) (TEMP_BUFFER + (TEMP_BUFFER_SIZE/2));
|
||||
size_t len = LoadSupportFile(SEEDDB_NAME, seeddb, (TEMP_BUFFER_SIZE/2));
|
||||
if (len && (seeddb->n_entries <= (len - 16) / 32)) { // check filesize / seeddb size
|
||||
for (u32 s = 0; s < seeddb->n_entries; s++) {
|
||||
if (titleId != seeddb->entries[s].titleId)
|
||||
continue;
|
||||
memcpy(lseed, seeddb->entries[s].seed, 16);
|
||||
sha_quick(sha256sum, lseed, 16 + 8, SHA256_MODE);
|
||||
if (hash_seed == sha256sum[0]) {
|
||||
memcpy(seed, lseed, 16);
|
||||
return 0; // found!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "ticket.h"
|
||||
#include "support.h"
|
||||
#include "unittype.h"
|
||||
#include "aes.h"
|
||||
#include "sha.h"
|
||||
@ -106,15 +107,10 @@ u32 FindTitleKey(Ticket* ticket, u8* title_id) {
|
||||
// when found, add it to the ticket
|
||||
for (u32 enc = 0; (enc <= 1) && !found; enc++) {
|
||||
TitleKeysInfo* tikdb = (TitleKeysInfo*) (TEMP_BUFFER + (TEMP_BUFFER_SIZE/2));
|
||||
const char* path = (enc) ? SUPPORT_PATH "/" TIKDB_NAME_ENC : SUPPORT_PATH "/" TIKDB_NAME_DEC;
|
||||
FIL file;
|
||||
UINT btr;
|
||||
u32 len = LoadSupportFile((enc) ? TIKDB_NAME_ENC : TIKDB_NAME_DEC, tikdb, (TEMP_BUFFER_SIZE/2));
|
||||
|
||||
if (f_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK)
|
||||
continue;
|
||||
f_read(&file, tikdb, TEMP_BUFFER_SIZE / 2, &btr);
|
||||
f_close(&file);
|
||||
if (tikdb->n_entries > (btr - 16) / 32)
|
||||
if (len == 0) continue; // file not found
|
||||
if (tikdb->n_entries > (len - 16) / 32)
|
||||
continue; // filesize / titlekey db size mismatch
|
||||
for (u32 t = 0; t < tikdb->n_entries; t++) {
|
||||
TitleKeyEntry* tik = tikdb->entries + t;
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "godmode.h"
|
||||
#include "support.h"
|
||||
#include "ui.h"
|
||||
#include "hid.h"
|
||||
#include "fs.h"
|
||||
@ -1843,9 +1844,9 @@ u32 GodMode(int entrypoint) {
|
||||
bootloader = true;
|
||||
} else if (user_select == 2) {
|
||||
godmode9 = true;
|
||||
} else if ((user_select == 3) && (FileSelector(loadpath, "Bootloader payloads menu.\nSelect payload:", PAYLOAD_PATH, "*.firm", true, false))) {
|
||||
} else if ((user_select == 3) && (FileSelectorSupport(loadpath, "Bootloader payloads menu.\nSelect payload:", PAYLOADS_DIR, "*.firm", true, false))) {
|
||||
BootFirmHandler(loadpath, false, false);
|
||||
} else if ((user_select == 4) && (FileSelector(loadpath, "Bootloader scripts menu.\nSelect script:", SCRIPT_PATH, "*.gm9", true, false))) {
|
||||
} else if ((user_select == 4) && (FileSelectorSupport(loadpath, "Bootloader scripts menu.\nSelect script:", SCRIPTS_DIR, "*.gm9", true, false))) {
|
||||
ExecuteGM9Script(loadpath);
|
||||
} else if (user_select == 5) {
|
||||
exit_mode = GODMODE_EXIT_POWEROFF;
|
||||
@ -2228,8 +2229,8 @@ u32 GodMode(int entrypoint) {
|
||||
u32 n_opt = 0;
|
||||
int poweroff = ++n_opt;
|
||||
int reboot = ++n_opt;
|
||||
int scripts = (PathExist(SCRIPT_PATH)) ? (int) ++n_opt : -1;
|
||||
int payloads = (PathExist(PAYLOAD_PATH)) ? (int) ++n_opt : -1;
|
||||
int scripts = (CheckSupportDir(SCRIPTS_DIR)) ? (int) ++n_opt : -1;
|
||||
int payloads = (CheckSupportDir(PAYLOADS_DIR)) ? (int) ++n_opt : -1;
|
||||
int more = ++n_opt;
|
||||
if (poweroff > 0) optionstr[poweroff - 1] = "Poweroff system";
|
||||
if (reboot > 0) optionstr[reboot - 1] = "Reboot system";
|
||||
@ -2242,12 +2243,12 @@ u32 GodMode(int entrypoint) {
|
||||
(user_select != poweroff) && (user_select != reboot)) {
|
||||
char loadpath[256];
|
||||
if ((user_select == more) && (HomeMoreMenu(current_path) == 0)) break; // more... menu
|
||||
else if ((user_select == scripts) && (FileSelector(loadpath, "HOME scripts... menu.\nSelect script:", SCRIPT_PATH, "*.gm9", true, false))) {
|
||||
else if ((user_select == scripts) && (FileSelectorSupport(loadpath, "HOME scripts... menu.\nSelect script:", SCRIPTS_DIR, "*.gm9", true, false))) {
|
||||
ExecuteGM9Script(loadpath);
|
||||
GetDirContents(current_dir, current_path);
|
||||
ClearScreenF(true, true, COLOR_STD_BG);
|
||||
break;
|
||||
} else if ((user_select == payloads) && (FileSelector(loadpath, "HOME payloads... menu.\nSelect payload:", PAYLOAD_PATH, "*.firm", true, false))) {
|
||||
} else if ((user_select == payloads) && (FileSelectorSupport(loadpath, "HOME payloads... menu.\nSelect payload:", PAYLOADS_DIR, "*.firm", true, false))) {
|
||||
BootFirmHandler(loadpath, false, false);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user