From 4d91a86d128463a9dc3e552a8acd696d19133c01 Mon Sep 17 00:00:00 2001 From: d0k3 Date: Tue, 30 May 2017 01:58:18 +0200 Subject: [PATCH] Remove the size limitation on BOSS files --- source/common/common.h | 2 +- source/game/boss.c | 1 - source/game/boss.h | 1 - source/game/gameutil.c | 35 +++++++++++++++++++++++++---------- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/source/common/common.h b/source/common/common.h index 0680600..c54c484 100644 --- a/source/common/common.h +++ b/source/common/common.h @@ -49,7 +49,7 @@ #endif // GodMode9 version -#define VERSION "1.1.9" +#define VERSION "1.2.0" // Maximum payload size (arbitrary value!) #define SELF_MAX_SIZE (320 * 1024) // 320kB diff --git a/source/game/boss.c b/source/game/boss.c index 5ab83bd..c9ffe13 100644 --- a/source/game/boss.c +++ b/source/game/boss.c @@ -26,7 +26,6 @@ u32 ValidateBossHeader(BossHeader* header, u32 fsize) { // base checks if ((memcmp(header->magic, boss_magic, sizeof(boss_magic)) != 0) || (fsize && (fsize != getbe32(header->filesize))) || - (getbe32(header->filesize) > BOSS_MAX_SIZE) || (getbe32(header->filesize) < sizeof(BossHeader)) || (getbe16(header->unknown0) != 0x0001) || (getbe16(header->cnthdr_hash_type) != 0x0002) || diff --git a/source/game/boss.h b/source/game/boss.h index 74ef9c7..ce6fa3c 100644 --- a/source/game/boss.h +++ b/source/game/boss.h @@ -3,7 +3,6 @@ #include "common.h" #define BOSS_MAGIC 0x62, 0x6F, 0x73, 0x73, 0x00, 0x01, 0x00, 0x01 -#define BOSS_MAX_SIZE 0xF0000 // 960 kB, should be more than enough #define BOSS_OFFSET_PAYLOAD sizeof(BossHeader) #define BOSS_SIZE_PAYLOAD_HEADER (0x1C + 2) diff --git a/source/game/gameutil.c b/source/game/gameutil.c index 994a4a7..a4844a0 100644 --- a/source/game/gameutil.c +++ b/source/game/gameutil.c @@ -549,26 +549,32 @@ u32 VerifyFirmFile(const char* path) { u32 VerifyBossFile(const char* path) { BossHeader* boss = (BossHeader*) TEMP_BUFFER; - u8* payload_hdr = MAIN_BUFFER; - u8* payload = MAIN_BUFFER + BOSS_SIZE_PAYLOAD_HEADER; u32 payload_size; bool encrypted = false; + FIL file; + UINT btr; char pathstr[32 + 1]; TruncateString(pathstr, path, 32, 8); // read file header - UINT btr; - if ((fvx_qread(path, boss, 0, sizeof(BossHeader), &btr) != FR_OK) || + + if (fvx_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) + return 1; + fvx_lseek(&file, 0); + if ((fvx_read(&file, boss, sizeof(BossHeader), &btr) != FR_OK) || (btr != sizeof(BossHeader)) || (ValidateBossHeader(boss, 0) != 0)) { ShowPrompt(false, "%s\nError: Not a BOSS file", pathstr); + fvx_close(&file); return 1; } // get / check size payload_size = getbe32(boss->filesize) - sizeof(BossHeader); - if ((payload_size + BOSS_SIZE_PAYLOAD_HEADER > MAIN_BUFFER_SIZE) || !payload_size) + if (!payload_size) { + fvx_close(&file); return 1; + } // check if encrypted, decrypt if required encrypted = (CheckBossEncrypted(boss) == 0); @@ -576,11 +582,20 @@ u32 VerifyBossFile(const char* path) { // actual hash calculation & compare u8 hash[32]; - memset(MAIN_BUFFER, 0, MAIN_BUFFER_SIZE); - GetBossPayloadHashHeader(payload_hdr, boss); - fvx_qread(path, payload, sizeof(BossHeader), payload_size, &btr); - if (encrypted) CryptBoss(payload, sizeof(BossHeader), payload_size, boss); - sha_quick(hash, MAIN_BUFFER, payload_size + BOSS_SIZE_PAYLOAD_HEADER, SHA256_MODE); + sha_init(SHA256_MODE); + GetBossPayloadHashHeader(MAIN_BUFFER, boss); + u32 read_bytes = min((MAIN_BUFFER_SIZE - BOSS_SIZE_PAYLOAD_HEADER), payload_size); + fvx_read(&file, MAIN_BUFFER + BOSS_SIZE_PAYLOAD_HEADER, read_bytes, &btr); + if (encrypted) CryptBoss(MAIN_BUFFER + BOSS_SIZE_PAYLOAD_HEADER, sizeof(BossHeader), read_bytes, boss); + sha_update(MAIN_BUFFER, read_bytes + BOSS_SIZE_PAYLOAD_HEADER); + for (u32 i = read_bytes; i < payload_size; i += MAIN_BUFFER_SIZE) { + read_bytes = min(MAIN_BUFFER_SIZE, (payload_size - i)); + fvx_read(&file, MAIN_BUFFER, read_bytes, &btr); + if (encrypted) CryptBoss(MAIN_BUFFER, sizeof(BossHeader) + i, read_bytes, boss); + sha_update(MAIN_BUFFER, read_bytes); + } + fvx_close(&file); + sha_get(hash); if (memcmp(hash, boss->hash_payload, 0x20) != 0) { ShowPrompt(false, "%s\nBOSS payload hash mismatch", pathstr); return 1;