add user-facing sha1 support

This commit is contained in:
BuildTools 2021-09-30 13:12:54 -04:00 committed by d0k3
parent ddf577b88c
commit e042886db4
5 changed files with 79 additions and 53 deletions

View File

@ -161,7 +161,7 @@ size_t FileGetSize(const char* path) {
return fno.fsize; return fno.fsize;
} }
bool FileGetSha256(const char* path, u8* sha256, u64 offset, u64 size) { bool FileGetSha(const char* path, u8* hash, u64 offset, u64 size, bool sha1) {
bool ret = true; bool ret = true;
FIL file; FIL file;
u64 fsize; u64 fsize;
@ -179,7 +179,7 @@ bool FileGetSha256(const char* path, u8* sha256, u64 offset, u64 size) {
if (!buffer) return false; if (!buffer) return false;
ShowProgress(0, 0, path); ShowProgress(0, 0, path);
sha_init(SHA256_MODE); sha_init(sha1 ? SHA1_MODE : SHA256_MODE);
for (u64 pos = 0; (pos < size) && ret; pos += bufsiz) { for (u64 pos = 0; (pos < size) && ret; pos += bufsiz) {
UINT read_bytes = min(bufsiz, size - pos); UINT read_bytes = min(bufsiz, size - pos);
UINT bytes_read = 0; UINT bytes_read = 0;
@ -190,7 +190,7 @@ bool FileGetSha256(const char* path, u8* sha256, u64 offset, u64 size) {
sha_update(buffer, bytes_read); sha_update(buffer, bytes_read);
} }
sha_get(sha256); sha_get(hash);
fvx_close(&file); fvx_close(&file);
free(buffer); free(buffer);
@ -448,6 +448,7 @@ bool PathMoveCopyRec(char* dest, char* orig, u32* flags, bool move, u8* buffer,
bool silent = (flags && (*flags & SILENT)); bool silent = (flags && (*flags & SILENT));
bool append = (flags && (*flags & APPEND_ALL)); bool append = (flags && (*flags & APPEND_ALL));
bool calcsha = (flags && (*flags & CALC_SHA) && !append); bool calcsha = (flags && (*flags & CALC_SHA) && !append);
bool sha1 = (flags && (*flags & USE_SHA1));
bool ret = false; bool ret = false;
// check destination write permission (special paths only) // check destination write permission (special paths only)
@ -552,7 +553,7 @@ bool PathMoveCopyRec(char* dest, char* orig, u32* flags, bool move, u8* buffer,
fvx_lseek(&ofile, 0); fvx_lseek(&ofile, 0);
fvx_sync(&ofile); fvx_sync(&ofile);
if (calcsha) sha_init(SHA256_MODE); if (calcsha) sha_init(sha1 ? SHA1_MODE : SHA256_MODE);
for (u64 pos = 0; (pos < osize) && ret; pos += bufsiz) { for (u64 pos = 0; (pos < osize) && ret; pos += bufsiz) {
UINT bytes_read = 0; UINT bytes_read = 0;
UINT bytes_written = 0; UINT bytes_written = 0;
@ -580,11 +581,11 @@ bool PathMoveCopyRec(char* dest, char* orig, u32* flags, bool move, u8* buffer,
if (!ret && ((dsize == 0) || (fvx_lseek(&dfile, dsize) != FR_OK) || (f_truncate(&dfile) != FR_OK))) { if (!ret && ((dsize == 0) || (fvx_lseek(&dfile, dsize) != FR_OK) || (f_truncate(&dfile) != FR_OK))) {
fvx_unlink(dest); fvx_unlink(dest);
} else if (!to_virtual && calcsha) { } else if (!to_virtual && calcsha) {
u8 sha256[0x20]; u8 hash[0x20];
char* ext_sha = dest + strnlen(dest, 256); char* ext_sha = dest + strnlen(dest, 256);
strncpy(ext_sha, ".sha", 256 - (ext_sha - dest)); snprintf(ext_sha, 256 - (ext_sha - dest), ".sha%c", sha1 ? '1' : '\0');
sha_get(sha256); sha_get(hash);
FileSetData(dest, sha256, 0x20, 0, true); FileSetData(dest, hash, sha1 ? 20 : 32, 0, true);
} }
} }

View File

@ -7,12 +7,13 @@
#define NO_CANCEL (1UL<<1) #define NO_CANCEL (1UL<<1)
#define SILENT (1UL<<2) #define SILENT (1UL<<2)
#define CALC_SHA (1UL<<3) #define CALC_SHA (1UL<<3)
#define BUILD_PATH (1UL<<4) #define USE_SHA1 (1UL<<4)
#define ALLOW_EXPAND (1UL<<5) #define BUILD_PATH (1UL<<5)
#define ASK_ALL (1UL<<6) #define ALLOW_EXPAND (1UL<<6)
#define SKIP_ALL (1UL<<7) #define ASK_ALL (1UL<<7)
#define OVERWRITE_ALL (1UL<<8) #define SKIP_ALL (1UL<<8)
#define APPEND_ALL (1UL<<9) #define OVERWRITE_ALL (1UL<<9)
#define APPEND_ALL (1UL<<10)
// file selector flags // file selector flags
#define NO_DIRS (1UL<<0) #define NO_DIRS (1UL<<0)
@ -43,7 +44,7 @@ size_t FileGetData(const char* path, void* data, size_t size, size_t foffset);
size_t FileGetSize(const char* path); size_t FileGetSize(const char* path);
/** Get SHA-256 of file **/ /** Get SHA-256 of file **/
bool FileGetSha256(const char* path, u8* sha256, u64 offset, u64 size); bool FileGetSha(const char* path, u8* hash, u64 offset, u64 size, bool sha1);
/** Find data in file **/ /** Find data in file **/
u32 FileFindData(const char* path, u8* data, u32 size_data, u32 offset_file); u32 FileFindData(const char* path, u8* data, u32 size_data, u32 offset_file);

View File

@ -842,37 +842,46 @@ u32 FileHexViewer(const char* path) {
return 0; return 0;
} }
u32 Sha256Calculator(const char* path) { u32 ShaCalculator(const char* path, bool sha1) {
const u8 hashlen = sha1 ? 20 : 32;
u32 drvtype = DriveType(path); u32 drvtype = DriveType(path);
char pathstr[32 + 1]; char pathstr[32 + 1];
u8 sha256[32]; u8 hash[32];
TruncateString(pathstr, path, 32, 8); TruncateString(pathstr, path, 32, 8);
if (!FileGetSha256(path, sha256, 0, 0)) { if (!FileGetSha(path, hash, 0, 0, sha1)) {
ShowPrompt(false, "Calculating SHA-256: failed!"); ShowPrompt(false, "Calculating SHA-%s: failed!", sha1 ? "1" : "256");
return 1; return 1;
} else { } else {
static char pathstr_prev[32 + 1] = { 0 }; static char pathstr_prev[32 + 1] = { 0 };
static u8 sha256_prev[32] = { 0 }; static u8 hash_prev[32] = { 0 };
char sha_path[256]; char sha_path[256];
u8 sha256_file[32]; u8 sha_file[32];
snprintf(sha_path, 256, "%s.sha", path); snprintf(sha_path, 256, "%s.sha%c", path, sha1 ? '1' : '\0');
bool have_sha = (FileGetData(sha_path, sha256_file, 32, 0) == 32); bool have_sha = (FileGetData(sha_path, sha_file, hashlen, 0) == hashlen);
bool match_sha = have_sha && (memcmp(sha256, sha256_file, 32) == 0); bool match_sha = have_sha && (memcmp(hash, sha_file, hashlen) == 0);
bool match_prev = (memcmp(sha256, sha256_prev, 32) == 0); bool match_prev = (memcmp(hash, hash_prev, hashlen) == 0);
bool write_sha = (!have_sha || !match_sha) && (drvtype & DRV_SDCARD); // writing only on SD bool write_sha = (!have_sha || !match_sha) && (drvtype & DRV_SDCARD); // writing only on SD
if (ShowPrompt(write_sha, "%s\n%016llX%016llX\n%016llX%016llX%s%s%s%s%s", char hash_str[32+1+32+1];
pathstr, getbe64(sha256 + 0), getbe64(sha256 + 8), getbe64(sha256 + 16), getbe64(sha256 + 24), if (sha1)
snprintf(hash_str, 40+1, "%016llX%016llX%08lX", getbe64(hash + 0), getbe64(hash + 8),
getbe32(hash + 16));
else
snprintf(hash_str, 32+1+32+1, "%016llX%016llX\n%016llX%016llX", getbe64(hash + 0), getbe64(hash + 8),
getbe64(hash + 16), getbe64(hash + 24));
if (ShowPrompt(write_sha, "%s\n%s%s%s%s%s%c \nWrite .SHA%s file?",
pathstr, hash_str,
(have_sha) ? "\nSHA verification: " : "", (have_sha) ? "\nSHA verification: " : "",
(have_sha) ? ((match_sha) ? "passed!" : "failed!") : "", (have_sha) ? ((match_sha) ? "passed!" : "failed!") : "",
(match_prev) ? "\n \nIdentical with previous file:\n" : "", (match_prev) ? "\n \nIdentical with previous file:\n" : "",
(match_prev) ? pathstr_prev : "", (match_prev) ? pathstr_prev : "",
(write_sha) ? "\n \nWrite .SHA file?" : "") && write_sha) { (write_sha) ? '\n' : '\0',
FileSetData(sha_path, sha256, 32, 0, true); (sha1) ? "1" : "") && write_sha) {
FileSetData(sha_path, hash, hashlen, 0, true);
} }
strncpy(pathstr_prev, pathstr, 32 + 1); strncpy(pathstr_prev, pathstr, 32 + 1);
memcpy(sha256_prev, sha256, 32); memcpy(hash_prev, hash, hashlen);
} }
return 0; return 0;
@ -1158,7 +1167,8 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
int special = (special_opt) ? ++n_opt : -1; int special = (special_opt) ? ++n_opt : -1;
int hexviewer = ++n_opt; int hexviewer = ++n_opt;
int textviewer = (filetype & TXT_GENERIC) ? ++n_opt : -1; int textviewer = (filetype & TXT_GENERIC) ? ++n_opt : -1;
int calcsha = ++n_opt; int calcsha256 = ++n_opt;
int calcsha1 = ++n_opt;
int calccmac = (CheckCmacPath(file_path) == 0) ? ++n_opt : -1; int calccmac = (CheckCmacPath(file_path) == 0) ? ++n_opt : -1;
int fileinfo = ++n_opt; int fileinfo = ++n_opt;
int copystd = (!in_output_path) ? ++n_opt : -1; int copystd = (!in_output_path) ? ++n_opt : -1;
@ -1170,7 +1180,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
int titleman = -1; int titleman = -1;
if (DriveType(current_path) & DRV_TITLEMAN) { if (DriveType(current_path) & DRV_TITLEMAN) {
// special case: title manager (disable almost everything) // special case: title manager (disable almost everything)
hexviewer = textviewer = calcsha = calccmac = fileinfo = copystd = inject = searchdrv = -1; hexviewer = textviewer = calcsha256 = calcsha1 = calccmac = fileinfo = copystd = inject = searchdrv = -1;
special = 1; special = 1;
titleman = 2; titleman = 2;
n_opt = 2; n_opt = 2;
@ -1210,7 +1220,8 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
(filetype & HDR_NAND) ? "Rebuild NCSD header" : (filetype & HDR_NAND) ? "Rebuild NCSD header" :
(filetype & NOIMG_NAND) ? "Rebuild NCSD header" : "???"; (filetype & NOIMG_NAND) ? "Rebuild NCSD header" : "???";
optionstr[hexviewer-1] = "Show in Hexeditor"; optionstr[hexviewer-1] = "Show in Hexeditor";
optionstr[calcsha-1] = "Calculate SHA-256"; optionstr[calcsha256-1] = "Calculate SHA-256";
optionstr[calcsha1-1] = "Calculate SHA-1";
optionstr[fileinfo-1] = "Show file info"; optionstr[fileinfo-1] = "Show file info";
if (textviewer > 0) optionstr[textviewer-1] = "Show in Textviewer"; if (textviewer > 0) optionstr[textviewer-1] = "Show in Textviewer";
if (calccmac > 0) optionstr[calccmac-1] = "Calculate CMAC"; if (calccmac > 0) optionstr[calccmac-1] = "Calculate CMAC";
@ -1230,8 +1241,13 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
FileTextViewer(file_path, scriptable); FileTextViewer(file_path, scriptable);
return 0; return 0;
} }
else if (user_select == calcsha) { // -> calculate SHA-256 else if (user_select == calcsha256) { // -> calculate SHA-256
Sha256Calculator(file_path); ShaCalculator(file_path, false);
GetDirContents(current_dir, current_path);
return 0;
}
else if (user_select == calcsha1) { // -> calculate SHA-1
ShaCalculator(file_path, true);
GetDirContents(current_dir, current_path); GetDirContents(current_dir, current_path);
return 0; return 0;
} }

View File

@ -895,7 +895,7 @@ u32 VerifyTadFile(const char* path) {
u8 hash[32]; u8 hash[32];
u32 len = align(hdr->content_size[i], 0x10); u32 len = align(hdr->content_size[i], 0x10);
if (!len) continue; // non-existant section if (!len) continue; // non-existant section
if (!FileGetSha256(path, hash, content_start, len) || if (!FileGetSha(path, hash, content_start, len, false) ||
(memcmp(hash, ftr->content_sha256[i], 32) != 0)) (memcmp(hash, ftr->content_sha256[i], 32) != 0))
return 1; return 1;
content_start += len + sizeof(TadBlockMetaData); content_start += len + sizeof(TadBlockMetaData);

View File

@ -59,7 +59,7 @@
// some useful macros // some useful macros
#define IS_WHITESPACE(c) ((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n')) #define IS_WHITESPACE(c) ((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n'))
#define MATCH_STR(s,l,c) ((l == strlen(c)) && (strncmp(s, c, l) == 0)) #define MATCH_STR(s,l,c) ((l == strlen(c)) && (strncmp(s, c, l) == 0))
#define _FLG(c) ((c >= 'a') ? (1 << (c - 'a')) : 0) #define _FLG(c) ((c >= 'a') ? (1 << (c - 'a')) : ((c >= '0') ? (1 << (26 + c - '0')) : 0))
#define IS_CTRLFLOW_CMD(id) ((id == CMD_ID_IF) || (id == CMD_ID_ELIF) || (id == CMD_ID_ELSE) || (id == CMD_ID_END) || \ #define IS_CTRLFLOW_CMD(id) ((id == CMD_ID_IF) || (id == CMD_ID_ELIF) || (id == CMD_ID_ELSE) || (id == CMD_ID_END) || \
(id == CMD_ID_GOTO) || (id == CMD_ID_LABELSEL) || \ (id == CMD_ID_GOTO) || (id == CMD_ID_LABELSEL) || \
@ -163,7 +163,7 @@ static const Gm9ScriptCmd cmd_list[] = {
{ CMD_ID_STRREP , "strrep" , 3, 0 }, { CMD_ID_STRREP , "strrep" , 3, 0 },
{ CMD_ID_CHK , "chk" , 2, _FLG('u') }, { CMD_ID_CHK , "chk" , 2, _FLG('u') },
{ CMD_ID_ALLOW , "allow" , 1, _FLG('a') }, { CMD_ID_ALLOW , "allow" , 1, _FLG('a') },
{ CMD_ID_CP , "cp" , 2, _FLG('h') | _FLG('w') | _FLG('k') | _FLG('s') | _FLG('n') | _FLG('p')}, { CMD_ID_CP , "cp" , 2, _FLG('h') | _FLG('1') | _FLG('w') | _FLG('k') | _FLG('s') | _FLG('n') | _FLG('p')},
{ CMD_ID_MV , "mv" , 2, _FLG('w') | _FLG('k') | _FLG('s') | _FLG('n') }, { CMD_ID_MV , "mv" , 2, _FLG('w') | _FLG('k') | _FLG('s') | _FLG('n') },
{ CMD_ID_INJECT , "inject" , 2, _FLG('n') }, { CMD_ID_INJECT , "inject" , 2, _FLG('n') },
{ CMD_ID_FILL , "fill" , 2, _FLG('n') }, { CMD_ID_FILL , "fill" , 2, _FLG('n') },
@ -176,8 +176,8 @@ static const Gm9ScriptCmd cmd_list[] = {
{ CMD_ID_FINDNOT , "findnot" , 2, 0 }, { CMD_ID_FINDNOT , "findnot" , 2, 0 },
{ CMD_ID_FGET , "fget" , 2, _FLG('e') }, { CMD_ID_FGET , "fget" , 2, _FLG('e') },
{ CMD_ID_FSET , "fset" , 2, _FLG('e') }, { CMD_ID_FSET , "fset" , 2, _FLG('e') },
{ CMD_ID_SHA , "sha" , 2, 0 }, { CMD_ID_SHA , "sha" , 2, _FLG('1') },
{ CMD_ID_SHAGET , "shaget" , 2, 0 }, { CMD_ID_SHAGET , "shaget" , 2, _FLG('1') },
{ CMD_ID_DUMPTXT , "dumptxt" , 2, _FLG('p') }, { CMD_ID_DUMPTXT , "dumptxt" , 2, _FLG('p') },
{ CMD_ID_FIXCMAC , "fixcmac" , 1, 0 }, { CMD_ID_FIXCMAC , "fixcmac" , 1, 0 },
{ CMD_ID_VERIFY , "verify" , 1, 0 }, { CMD_ID_VERIFY , "verify" , 1, 0 },
@ -584,6 +584,7 @@ u32 get_flag(char* str, u32 len, char* err_str) {
if ((len < 2) || (*str != '-')) flag_char = '\0'; if ((len < 2) || (*str != '-')) flag_char = '\0';
else if (len == 2) flag_char = str[1]; else if (len == 2) flag_char = str[1];
else if (strncmp(str, "--sha1", len) == 0) flag_char = '1';
else if (strncmp(str, "--all", len) == 0) flag_char = 'a'; else if (strncmp(str, "--all", len) == 0) flag_char = 'a';
else if (strncmp(str, "--before", len) == 0) flag_char = 'b'; else if (strncmp(str, "--before", len) == 0) flag_char = 'b';
else if (strncmp(str, "--include_dirs", len) == 0) flag_char = 'd'; else if (strncmp(str, "--include_dirs", len) == 0) flag_char = 'd';
@ -603,7 +604,7 @@ u32 get_flag(char* str, u32 len, char* err_str) {
else if (strncmp(str, "--overwrite", len) == 0) flag_char = 'w'; else if (strncmp(str, "--overwrite", len) == 0) flag_char = 'w';
else if (strncmp(str, "--explorer", len) == 0) flag_char = 'x'; else if (strncmp(str, "--explorer", len) == 0) flag_char = 'x';
if ((flag_char < 'a') && (flag_char > 'z')) { if (((flag_char < 'a') || (flag_char > 'z')) && ((flag_char < '0') || (flag_char > '5'))) {
if (err_str) snprintf(err_str, _ERR_STR_LEN, "illegal flag"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "illegal flag");
return 0; return 0;
} }
@ -1150,6 +1151,7 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
else if (id == CMD_ID_CP) { else if (id == CMD_ID_CP) {
u32 flags_ext = BUILD_PATH; u32 flags_ext = BUILD_PATH;
if (flags & _FLG('h')) flags_ext |= CALC_SHA; if (flags & _FLG('h')) flags_ext |= CALC_SHA;
if (flags & _FLG('1')) flags_ext |= USE_SHA1;
if (flags & _FLG('n')) flags_ext |= NO_CANCEL; if (flags & _FLG('n')) flags_ext |= NO_CANCEL;
if (flags & _FLG('s')) flags_ext |= SILENT; if (flags & _FLG('s')) flags_ext |= SILENT;
if (flags & _FLG('w')) flags_ext |= OVERWRITE_ALL; if (flags & _FLG('w')) flags_ext |= OVERWRITE_ALL;
@ -1291,30 +1293,36 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
} }
} }
else if (id == CMD_ID_SHA) { else if (id == CMD_ID_SHA) {
u8 sha256_fil[0x20]; const u8 hashlen = (flags & _FLG('1')) ? 20 : 32;
u8 sha256_cmp[0x20]; u8 hash_fil[0x20];
if (!FileGetSha256(argv[0], sha256_fil, at_org, sz_org)) { u8 hash_cmp[0x20];
if (!FileGetSha(argv[0], hash_fil, at_org, sz_org, flags & _FLG('1'))) {
ret = false; ret = false;
if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha arg0 fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha arg0 fail");
} else if ((FileGetData(argv[1], sha256_cmp, 0x20, 0) != 0x20) && !strntohex(argv[1], sha256_cmp, 0x20)) { } else if ((FileGetData(argv[1], hash_cmp, hashlen, 0) != hashlen) && !strntohex(argv[1], hash_cmp, hashlen)) {
ret = false; ret = false;
if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha arg1 fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha arg1 fail");
} else { } else {
ret = (memcmp(sha256_fil, sha256_cmp, 0x20) == 0); ret = (memcmp(hash_fil, hash_cmp, hashlen) == 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_SHAGET) { else if (id == CMD_ID_SHAGET) {
u8 sha256_fil[0x20]; const u8 hashlen = (flags & _FLG('1')) ? 20 : 32;
if (!(ret = FileGetSha256(argv[0], sha256_fil, at_org, sz_org))) { u8 hash_fil[0x20];
if (!(ret = FileGetSha(argv[0], hash_fil, at_org, sz_org, flags & _FLG('1')))) {
if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha arg0 fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha arg0 fail");
} else if (!strchr(argv[1], ':')) { } else if (!strchr(argv[1], ':')) {
char sha256_str[64+1]; char hash_str[64+1];
snprintf(sha256_str, 64+1, "%016llX%016llX%016llX%016llX", getbe64(sha256_fil + 0), getbe64(sha256_fil + 8), if (flags & _FLG('1'))
getbe64(sha256_fil + 16), getbe64(sha256_fil + 24)); snprintf(hash_str, 64+1, "%016llX%016llX%08lX", getbe64(hash_fil + 0), getbe64(hash_fil + 8),
ret = set_var(argv[1], sha256_str); getbe32(hash_fil + 16));
else
snprintf(hash_str, 64+1, "%016llX%016llX%016llX%016llX", getbe64(hash_fil + 0), getbe64(hash_fil + 8),
getbe64(hash_fil + 16), getbe64(hash_fil + 24));
ret = set_var(argv[1], hash_str);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "var fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "var fail");
} else if (!(ret = FileSetData(argv[1], sha256_fil, 0x20, 0, true))) { } else if (!(ret = FileSetData(argv[1], hash_fil, hashlen, 0, true))) {
if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha write fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha write fail");
} }
} }