forked from Mirror/GodMode9
Scripting: add fixcmac command
fixes #175 check HelloScript.gm9 for how it's done
This commit is contained in:
parent
26690f4a90
commit
551a48149f
@ -128,6 +128,12 @@ set ERRORMSG "SHA check failed (this was expected)"
|
|||||||
sha -o $[RENPATH] $[TESTPATH].sha
|
sha -o $[RENPATH] $[TESTPATH].sha
|
||||||
set ERRORMSG ""
|
set ERRORMSG ""
|
||||||
|
|
||||||
|
# 'fixcmac' COMMAND
|
||||||
|
# Use this to fix the CMACs for a file or a whole folder (recursively)
|
||||||
|
# This will count as success if a file does not contain a CMAC
|
||||||
|
# More info on CMACs: http://3dbrew.org/wiki/Savegames#AES_CMAC_header
|
||||||
|
# fixcmac 1:/data
|
||||||
|
|
||||||
# 'verify' COMMAND
|
# 'verify' COMMAND
|
||||||
# Certain file formats (NAND, NCCH, NCSD, CIA, FIRM, ...) can also be verified. Use 'verify' to do so.
|
# Certain file formats (NAND, NCCH, NCSD, CIA, FIRM, ...) can also be verified. Use 'verify' to do so.
|
||||||
# verify -o s:/firm0.bin # As drive letters are case sensitive, this would fail
|
# verify -o s:/firm0.bin # As drive letters are case sensitive, this would fail
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "fsutil.h"
|
#include "fsutil.h"
|
||||||
#include "fsinit.h"
|
#include "fsinit.h"
|
||||||
#include "fsperm.h"
|
#include "fsperm.h"
|
||||||
|
#include "nandcmac.h"
|
||||||
#include "nandutil.h"
|
#include "nandutil.h"
|
||||||
#include "gameutil.h"
|
#include "gameutil.h"
|
||||||
#include "keydbutil.h"
|
#include "keydbutil.h"
|
||||||
@ -46,6 +47,7 @@ typedef enum {
|
|||||||
CMD_ID_DECRYPT,
|
CMD_ID_DECRYPT,
|
||||||
CMD_ID_ENCRYPT,
|
CMD_ID_ENCRYPT,
|
||||||
CMD_ID_BUILDCIA,
|
CMD_ID_BUILDCIA,
|
||||||
|
CMD_ID_BOOT,
|
||||||
CMD_ID_REBOOT,
|
CMD_ID_REBOOT,
|
||||||
CMD_ID_POWEROFF
|
CMD_ID_POWEROFF
|
||||||
} cmd_id;
|
} cmd_id;
|
||||||
@ -78,11 +80,12 @@ Gm9ScriptCmd cmd_list[] = {
|
|||||||
{ CMD_ID_FIND , "find" , 2, 0 },
|
{ CMD_ID_FIND , "find" , 2, 0 },
|
||||||
{ CMD_ID_FINDNOT , "findnot" , 2, 0 },
|
{ CMD_ID_FINDNOT , "findnot" , 2, 0 },
|
||||||
{ CMD_ID_SHA , "sha" , 2, 0 },
|
{ CMD_ID_SHA , "sha" , 2, 0 },
|
||||||
// { CMD_ID_FIXCMAC , "fixcmac" , 1, 0 }, // not supported yet
|
{ CMD_ID_FIXCMAC , "fixcmac" , 1, 0 },
|
||||||
{ CMD_ID_VERIFY , "verify" , 1, 0 },
|
{ CMD_ID_VERIFY , "verify" , 1, 0 },
|
||||||
{ CMD_ID_DECRYPT , "decrypt" , 1, 0 },
|
{ CMD_ID_DECRYPT , "decrypt" , 1, 0 },
|
||||||
{ CMD_ID_ENCRYPT , "encrypt" , 1, 0 },
|
{ CMD_ID_ENCRYPT , "encrypt" , 1, 0 },
|
||||||
{ CMD_ID_BUILDCIA, "buildcia", 1, _FLG('l') },
|
{ CMD_ID_BUILDCIA, "buildcia", 1, _FLG('l') },
|
||||||
|
// { CMD_ID_BOOT , "boot" , 1, 0 }, // not supported yet
|
||||||
{ CMD_ID_REBOOT , "reboot" , 0, 0 },
|
{ CMD_ID_REBOOT , "reboot" , 0, 0 },
|
||||||
{ CMD_ID_POWEROFF, "poweroff", 0, 0 }
|
{ CMD_ID_POWEROFF, "poweroff", 0, 0 }
|
||||||
};
|
};
|
||||||
@ -445,6 +448,10 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
|
|||||||
ret = (memcmp(sha256_fil, sha256_cmp, 0x20) == 0);
|
ret = (memcmp(sha256_fil, sha256_cmp, 0x20) == 0);
|
||||||
if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha does not match");
|
if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha does not match");
|
||||||
}
|
}
|
||||||
|
} else if (id == CMD_ID_FIXCMAC) {
|
||||||
|
ShowString("Fixing CMACs...");
|
||||||
|
ret = (RecursiveFixFileCmac(argv[0]) == 0);
|
||||||
|
if (err_str) snprintf(err_str, _ERR_STR_LEN, "fixcmac failed");
|
||||||
} else if (id == CMD_ID_VERIFY) {
|
} else if (id == CMD_ID_VERIFY) {
|
||||||
u32 filetype = IdentifyFileType(argv[0]);
|
u32 filetype = IdentifyFileType(argv[0]);
|
||||||
if (filetype & IMG_NAND) ret = (ValidateNandDump(argv[0]) == 0);
|
if (filetype & IMG_NAND) ret = (ValidateNandDump(argv[0]) == 0);
|
||||||
|
@ -6,14 +6,14 @@
|
|||||||
#include "vff.h"
|
#include "vff.h"
|
||||||
|
|
||||||
// CMAC types, see:
|
// CMAC types, see:
|
||||||
// https://www.3dbrew.org/wiki/Savegames#AES_CMAC_header
|
// https://3dbrew.org/wiki/Savegames#AES_CMAC_header
|
||||||
// https://3dbrew.org/wiki/Nand/private/movable.sed
|
// https://3dbrew.org/wiki/Nand/private/movable.sed
|
||||||
// https://3dbrew.org/wiki/3DS_Virtual_Console#NAND_Savegame
|
// https://3dbrew.org/wiki/3DS_Virtual_Console#NAND_Savegame
|
||||||
#define CMAC_EXTDATA_SD 1
|
#define CMAC_EXTDATA_SD 1
|
||||||
#define CMAC_EXTDATA_SYS 2
|
#define CMAC_EXTDATA_SYS 2
|
||||||
#define CMAC_SAVEDATA_SYS 3
|
#define CMAC_SAVEDATA_SYS 3
|
||||||
#define CMAC_SAVE_GAMECARD 4
|
#define CMAC_SAVE_GAMECARD 4
|
||||||
#define CMAC_SAVEGAME 5 // this is not calclated into a CMAC
|
#define CMAC_SAVEGAME 5 // this is not calculated into a CMAC
|
||||||
#define CMAC_SAVEDATA_SD 6
|
#define CMAC_SAVEDATA_SD 6
|
||||||
#define CMAC_TITLEDB_SYS 7
|
#define CMAC_TITLEDB_SYS 7
|
||||||
#define CMAC_TITLEDB_SD 8
|
#define CMAC_TITLEDB_SD 8
|
||||||
@ -233,3 +233,39 @@ u32 FixFileCmac(const char* path) {
|
|||||||
u8 ccmac[16];
|
u8 ccmac[16];
|
||||||
return ((CalculateFileCmac(path, ccmac) == 0) && (WriteFileCmac(path, ccmac) == 0)) ? 0 : 1;
|
return ((CalculateFileCmac(path, ccmac) == 0) && (WriteFileCmac(path, ccmac) == 0)) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 RecursiveFixFileCmacWorker(char* path) {
|
||||||
|
FILINFO fno;
|
||||||
|
|
||||||
|
if (fvx_stat(path, &fno) != FR_OK) return 1; // path does not exist
|
||||||
|
if (fno.fattrib & AM_DIR) { // process folder contents
|
||||||
|
DIR pdir;
|
||||||
|
char* fname = path + strnlen(path, 255);
|
||||||
|
if (fvx_opendir(&pdir, path) != FR_OK) return 1;
|
||||||
|
*(fname++) = '/';
|
||||||
|
|
||||||
|
while (f_readdir(&pdir, &fno) == FR_OK) {
|
||||||
|
if ((strncmp(fno.fname, ".", 2) == 0) || (strncmp(fno.fname, "..", 3) == 0))
|
||||||
|
continue; // filter out virtual entries
|
||||||
|
strncpy(fname, fno.fname, path + 255 - fname);
|
||||||
|
if (fno.fname[0] == 0) {
|
||||||
|
break;
|
||||||
|
} else if (fno.fattrib & AM_DIR) { // directory, recurse through it
|
||||||
|
if (RecursiveFixFileCmacWorker(path) != 0) return 1;
|
||||||
|
} else if (CheckCmacPath(path) == 0) { // file, try to fix the CMAC
|
||||||
|
if (FixFileCmac(path) != 0) return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f_closedir(&pdir);
|
||||||
|
*(--fname) = '\0';
|
||||||
|
} else if (CheckCmacPath(path) == 0)
|
||||||
|
return FixFileCmac(path);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 RecursiveFixFileCmac(const char* path) {
|
||||||
|
char lpath[256] = { 0 };
|
||||||
|
strncpy(lpath, path, 255);
|
||||||
|
return RecursiveFixFileCmacWorker(lpath);
|
||||||
|
}
|
||||||
|
@ -8,3 +8,4 @@ u32 WriteFileCmac(const char* path, u8* cmac);
|
|||||||
u32 CalculateFileCmac(const char* path, u8* cmac);
|
u32 CalculateFileCmac(const char* path, u8* cmac);
|
||||||
u32 CheckFileCmac(const char* path);
|
u32 CheckFileCmac(const char* path);
|
||||||
u32 FixFileCmac(const char* path);
|
u32 FixFileCmac(const char* path);
|
||||||
|
u32 RecursiveFixFileCmac(const char* path);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user