First look version - some stuff not working yet

.. won't write to NAND yet
This commit is contained in:
d0k3 2017-02-01 23:41:05 +01:00
parent 5aa7fadf86
commit 64b1275c39
15 changed files with 451 additions and 21 deletions

View File

@ -18,9 +18,9 @@ include $(DEVKITARM)/ds_rules
#---------------------------------------------------------------------------------
export TARGET := SafeSigHaxInstaller
BUILD := build
SOURCES := source source/common source/fs source/crypto source/fatfs source/nand source/abstraction
SOURCES := source source/common source/fs source/crypto source/fatfs source/nand source/safety source/abstraction
DATA := data
INCLUDES := source source/common source/font source/fs source/crypto source/fatfs source/nand
INCLUDES := source source/common source/font source/fs source/crypto source/fatfs source/nand source/safety
#---------------------------------------------------------------------------------
# options for code generation

View File

@ -43,11 +43,13 @@
// input / output paths
#define INPUT_PATH "0:/sighax"
// buffer area defines (main & special for NAND)
#define MAIN_BUFFER ((u8*) 0x21000000)
#define MAIN_BUFFER_SIZE (0x400000)
#define NAND_BUFFER ((u8*) 0x25000000)
// buffer area defines (big buffer for firm)
#define WORK_BUFFER ((u8*) 0x21000000)
#define WORK_BUFFER_SIZE (0x100000)
#define NAND_BUFFER ((u8*) 0x22000000)
#define NAND_BUFFER_SIZE (0x100000)
#define FIRM_BUFFER ((u8*) 0x23000000)
#define FIRM_BUFFER_SIZE (0x400000)
inline u32 strchrcount(const char* str, char symbol) {
u32 count = 0;

View File

@ -36,3 +36,9 @@ void sha_quick(void* res, const void* src, u32 size, u32 mode) {
sha_update(src, size);
sha_get(res);
}
int sha_cmp(const void* sha, const void* src, u32 size, u32 mode) {
u8 res[0x20];
sha_quick(res, src, size, mode);
return memcmp(sha, res, 0x20);
}

View File

@ -26,3 +26,4 @@ void sha_init(u32 mode);
void sha_update(const void* src, u32 size);
void sha_get(void* res);
void sha_quick(void* res, const void* src, u32 size, u32 mode);
int sha_cmp(const void* sha, const void* src, u32 size, u32 mode);

View File

@ -39,7 +39,7 @@
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
#define _USE_MKFS 1
#define _USE_MKFS 0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
@ -160,7 +160,7 @@
/ the drive ID strings are: A-Z and 0-9. */
#define _MULTI_PARTITION 1
#define _MULTI_PARTITION 0
/* This option switches support of multi-partition on a physical drive.
/ By default (0), each logical drive number is bound to the same physical drive
/ number and only an FAT volume found on the physical drive will be mounted.

View File

@ -26,8 +26,6 @@ FRESULT f_qread (const TCHAR* path, void* buff, FSIZE_t ofs, UINT btr, UINT* br)
res = f_read(&fp, buff, btr, br);
f_close(&fp);
if (*br != btr) res = FR_DENIED; // hacky
return res;
}
@ -49,8 +47,6 @@ FRESULT f_qwrite (const TCHAR* path, const void* buff, FSIZE_t ofs, UINT btw, UI
res = f_write(&fp, buff, btw, bw);
f_close(&fp);
if (*bw != btw) res = FR_DENIED; // hacky
return res;
}

236
source/installer.c Normal file
View File

@ -0,0 +1,236 @@
#include "installer.h"
#include "validator.h"
#include "safewrite.h"
#include "nand.h"
#include "ui.h"
#include "qff.h"
#define COLOR_STATUS(s) ((s == STATUS_GREEN) ? COLOR_BRIGHTGREEN : (s == STATUS_YELLOW) ? COLOR_BRIGHTYELLOW : (s == STATUS_RED) ? COLOR_RED : COLOR_DARKGREY)
#define MIN_SD_FREE (16 * 1024 * 1024) // 16MB
#define FIRM_NAND_OFFSET 0x0B130000
#define FIRM_NAND_SIZE 0x800000
#define NAME_SIGHAXFIRM (INPUT_PATH "/sighaxfirm.bin")
#define NAME_SIGHAXFIRMSHA (INPUT_PATH "/sighaxfirm.bin.sha")
#define NAME_SECTOR0x96 (INPUT_PATH "/secret_sector.bin")
#define NAME_FIRMBACKUP (INPUT_PATH "/firm0firm1.bak")
#define NAME_SECTORBACKUP (INPUT_PATH "/sector0x96.bak")
#define STATUS_GREY -1
#define STATUS_GREEN 0
#define STATUS_YELLOW 1
#define STATUS_RED 2
static int statusA9lh = STATUS_GREY;
static int statusSdCard = STATUS_GREY;
static int statusFirm = STATUS_GREY;
static int statusSector = STATUS_GREY;
static int statusCrypto = STATUS_GREY;
static int statusBackup = STATUS_GREY;
static int statusInstall = STATUS_GREY;
static char msgA9lh[64] = "not started";
static char msgSdCard[64] = "not started";
static char msgFirm[64] = "not started";
static char msgSector[64] = "not started";
static char msgCrypto[64] = "not started";
static char msgBackup[64] = "not started";
static char msgInstall[64] = "not started";
u32 ShowInstallerStatus(void) {
const u32 pos_xb = 10;
const u32 pos_x0 = pos_xb;
const u32 pos_x1 = pos_x0 + (16*FONT_WIDTH_EXT);
const u32 pos_yb = 10;
const u32 pos_y0 = pos_yb + 20;
DrawStringF(BOT_SCREEN, pos_xb, pos_yb, COLOR_STD_FONT, COLOR_STD_BG, "SafeSigHaxInstaller v" VERSION);
DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + 0, COLOR_STD_FONT, COLOR_STD_BG, "ARM9LoaderHax :");
DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + 10, COLOR_STD_FONT, COLOR_STD_BG, "MicroSD Card :");
DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + 20, COLOR_STD_FONT, COLOR_STD_BG, "Sighaxed FIRM :");
DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + 30, COLOR_STD_FONT, COLOR_STD_BG, "Secret Sector :");
DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + 40, COLOR_STD_FONT, COLOR_STD_BG, "Crypto Status :");
DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + 50, COLOR_STD_FONT, COLOR_STD_BG, "Backup Status :");
DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + 60, COLOR_STD_FONT, COLOR_STD_BG, "Install Status:");
DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + 0, COLOR_STATUS(statusA9lh) , COLOR_STD_BG, msgA9lh );
DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + 10, COLOR_STATUS(statusSdCard) , COLOR_STD_BG, msgSdCard );
DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + 20, COLOR_STATUS(statusFirm) , COLOR_STD_BG, msgFirm );
DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + 30, COLOR_STATUS(statusSector) , COLOR_STD_BG, msgSector );
DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + 40, COLOR_STATUS(statusCrypto) , COLOR_STD_BG, msgCrypto );
DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + 50, COLOR_STATUS(statusBackup) , COLOR_STD_BG, msgBackup );
DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + 60, COLOR_STATUS(statusInstall), COLOR_STD_BG, msgInstall);
return 0;
}
u32 SafeSigHaxInstaller(void) {
UINT bt;
// initialization
ShowString("Initializing, please wait...");
// step #0 - a9lh check
InitNandCrypto(); // for sector0x96 crypto and NAND drives
snprintf(msgA9lh, 64, CheckA9lh() ? "installed" : "not installed");
statusA9lh = STATUS_GREEN;
ShowInstallerStatus();
// step #1 - init/check SD card
snprintf(msgSdCard, 64, "checking...");
statusSdCard = STATUS_YELLOW;
ShowInstallerStatus();
u64 sdFree = 0;
u64 sdTotal = 0;
if ((fs_init() != FR_OK) ||
(f_getfreebyte("0:", &sdFree) != FR_OK) ||
(f_gettotalbyte("0:", &sdTotal) != FR_OK)) {
snprintf(msgSdCard, 64, "init failed");
statusSdCard = STATUS_RED;
return 1;
}
snprintf(msgSdCard, 64, "%lluMB / %lluMB free", sdFree / (1024 * 1024), sdTotal / (1024 * 1024));
statusSdCard = (sdFree < MIN_SD_FREE) ? STATUS_RED : STATUS_GREEN;
ShowInstallerStatus();
if (sdFree < MIN_SD_FREE) return 1;
// SD card okay!
// step #2 - check sighaxed firm
snprintf(msgFirm, 64, "checking...");
statusFirm = STATUS_YELLOW;
ShowInstallerStatus();
u8 firm_sha[0x20];
UINT firm_size;
if ((f_qread(NAME_SIGHAXFIRM, FIRM_BUFFER, 0, FIRM_BUFFER_SIZE, &firm_size) != FR_OK) ||
(firm_size < 0x200)) {
snprintf(msgFirm, 64, "file not found");
statusFirm = STATUS_RED;
return 1;
}
if ((f_qread(NAME_SIGHAXFIRMSHA, firm_sha, 0, 0x20, &bt) != FR_OK) || (bt != 0x20)) {
snprintf(msgFirm, 64, ".sha file not found");
statusFirm = STATUS_RED;
return 1;
}
if (ValidateFirm(FIRM_BUFFER, firm_sha, firm_size, NULL) != 0) {
snprintf(msgFirm, 64, "invalid FIRM");
statusFirm = STATUS_RED;
return 1;
}
if (CheckFirmSigHax(FIRM_BUFFER) != 0) {
snprintf(msgFirm, 64, "not sighaxed");
statusFirm = STATUS_RED;
return 1;
}
snprintf(msgFirm, 64, "loaded & verified");
statusFirm = STATUS_GREEN;
ShowInstallerStatus();
// provided FIRM is okay!
// step #3 - check secret_sector.bin file
u8 secret_sector[0x20];
if (CheckA9lh()) {
snprintf(msgSector, 64, "checking...");
statusSector = STATUS_YELLOW;
ShowInstallerStatus();
if ((f_qread(NAME_SECTOR0x96, secret_sector, 0, 0x200, &bt) != FR_OK) || (bt != 0x200)) {
snprintf(msgSector, 64, "file not found");
statusSector = STATUS_RED;
return 1;
}
if (ValidateSector(secret_sector) != 0) {
snprintf(msgSector, 64, "invalid file");
statusSector = STATUS_RED;
return 1;
}
snprintf(msgSector, 64, "loaded & verified");
} else snprintf(msgSector, 64, "not required");
statusSector = STATUS_GREEN;
ShowInstallerStatus();
// secret_sector.bin okay or not required!
// step #3 - check NAND crypto
snprintf(msgCrypto, 64, "checking...");
statusCrypto = STATUS_YELLOW;
ShowInstallerStatus();
if (!CheckFirmCrypto()) {
snprintf(msgCrypto, 64, "FIRM crypto fail");
statusCrypto = STATUS_RED;
return 1;
}
if (CheckA9lh() && !CheckSector0x96Crypto()) {
snprintf(msgCrypto, 64, "OTP crypto fail");
statusCrypto = STATUS_RED;
return 1;
}
snprintf(msgCrypto, 64, "all checks passed");
statusCrypto = STATUS_GREEN;
ShowInstallerStatus();
// step #X - point of no return
if (!ShowUnlockSequence(1, "All input files verified.\nTo install FIRM, enter the sequence\nbelow or press B to cancel.")) {
snprintf(msgBackup, 64, "cancelled by user");
snprintf(msgInstall, 64, "cancelled by user");
return 1;
}
// step #5 - backup of current FIRMs and sector 0x96
snprintf(msgBackup, 64, "FIRM backup...");
statusBackup = STATUS_YELLOW;
ShowInstallerStatus();
FIL fp;
u32 ret = 0;
if (f_open(&fp, NAME_FIRMBACKUP, FA_READ|FA_WRITE|FA_CREATE_ALWAYS) != FR_OK) {
snprintf(msgBackup, 64, "FIRM backup fail");
statusBackup = STATUS_RED;
return 1;
}
ShowProgress(0, 0, "FIRM backup");
for (u32 pos = 0; (pos < FIRM_NAND_SIZE) && (ret == 0); pos += WORK_BUFFER_SIZE) {
UINT bytes = min(WORK_BUFFER_SIZE, FIRM_NAND_SIZE - pos);
snprintf(msgBackup, 64, "FIRM backup (%luMB/%luMB)",
pos / (1024*1024), (u32) FIRM_NAND_SIZE / (1024 * 1024));
ShowInstallerStatus();
if ((ReadNandBytes(WORK_BUFFER, FIRM_NAND_OFFSET + pos, bytes, 0xFF) != 0) ||
(SafeWriteFile(&fp, WORK_BUFFER, pos, bytes) != 0))
ret = 1;
ShowProgress(pos + bytes, FIRM_NAND_SIZE, "FIRM backup");
}
f_close(&fp);
if (ret != 0) {
snprintf(msgBackup, 64, "FIRM backup fail");
statusBackup = STATUS_RED;
return 1;
}
if (CheckA9lh()) {
snprintf(msgBackup, 64, "0x96 backup...");
ShowInstallerStatus();
u8 sector_backup0[0x200];
u8 sector_backup1[0x200];
f_unlink(NAME_SECTORBACKUP);
if ((ReadNandSectors(sector_backup0, 96, 1, 0xFF) != 0) ||
(f_qwrite(NAME_SECTORBACKUP, sector_backup0, 0, 0x200, &bt) != FR_OK) || (bt != 0x200) ||
(f_qread(NAME_SECTORBACKUP, sector_backup1, 0, 0x200, &bt) != FR_OK) || (bt != 0x200) ||
(memcmp(sector_backup0, sector_backup1, 0x200) != 0)) {
snprintf(msgBackup, 64, "0x96 backup fail");
statusBackup = STATUS_RED;
return 1;
}
}
snprintf(msgBackup, 64, "backed up & verified");
statusBackup = STATUS_GREEN;
ShowInstallerStatus();
// backups done
// step #6 - install sighaxed FIRM
return 0;
}

6
source/installer.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include "common.h"
u32 ShowInstallerStatus(void);
u32 SafeSigHaxInstaller(void);

20
source/main.c Normal file
View File

@ -0,0 +1,20 @@
#include "installer.h"
#include "ui.h"
#include "i2c.h"
void Reboot()
{
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
while(true);
}
int main()
{
u32 ret = SafeSigHaxInstaller();
ShowInstallerStatus(); // update installer status one last time
if (ret) ShowPrompt(false, "SigHaxed FIRM was not installed!\nCheck lower screen for info.");
ClearScreenF(true, true, COLOR_STD_BG);
Reboot();
return 0;
}

View File

@ -1,11 +1,8 @@
#include "nand.h"
#include "platform.h"
#include "qff.h"
#include "aes.h"
#include "sha.h"
#include "sdmmc.h"
#define NAND_MIN_SECTORS ((GetUnitPlatform() == PLATFORM_N3DS) ? NAND_MIN_SECTORS_N3DS : NAND_MIN_SECTORS_O3DS)
#include "qff.h"
static u8 slot0x05KeyY[0x10] = { 0x00 }; // need to load this from FIRM0 / external file
static const u8 slot0x05KeyY_sha256[0x20] = { // hash for slot0x05KeyY (16 byte)
@ -13,6 +10,11 @@ static const u8 slot0x05KeyY_sha256[0x20] = { // hash for slot0x05KeyY (16 byte)
0x62, 0x22, 0x5C, 0xFD, 0x6F, 0xAE, 0x9B, 0x0A, 0x85, 0xA5, 0xCE, 0x21, 0xAA, 0xB6, 0xC8, 0x4D
};
static const u8 slot0x11Key95_sha256[0x20] = { // slot0x11Key95 hash (first 16 byte of sector0x96)
0xBF, 0x01, 0x4C, 0x85, 0x9B, 0xA1, 0x07, 0xFA, 0x3B, 0xAC, 0x25, 0x20, 0x1A, 0x3F, 0x3A, 0xF4,
0x4E, 0x97, 0xE9, 0x5C, 0x06, 0x46, 0xF8, 0xE7, 0xC1, 0xC2, 0xC3, 0x29, 0x88, 0xBF, 0xF6, 0x50
};
static const u8 nand_magic_n3ds[0x60] = { // NCSD NAND header N3DS magic
0x4E, 0x43, 0x53, 0x44, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x04, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00,
@ -160,8 +162,25 @@ bool CheckSlot0x05Crypto(void)
bool CheckSector0x96Crypto(void)
{
const u8 zeroes[32] = { 0 };
return !(memcmp(OtpSha256, zeroes, 32) == 0);
u8 buffer[0x200];
ReadNandSectors(buffer, 0x96, 1, 0x11);
return (sha_cmp(slot0x11Key95_sha256, buffer, 16, SHA256_MODE) == 0);
}
bool CheckFirmCrypto(void)
{
// check the FIRM magic
const u8 magic[8] = {'F', 'I', 'R', 'M', '\0', '\0', '\0', '\0'};
const u32 sectors[] = { SECTOR_FIRM0, SECTOR_FIRM1 };
u8 buffer[0x200];
for (u32 i = 0; i < sizeof(sectors) / sizeof(u32); i++) {
ReadNandSectors(buffer, sectors[i], 1, 0x06);
ShowPrompt(false, "%016llX\n%016llX", getbe64(magic), getbe64(buffer));
if (memcmp(buffer, magic, 8) != 0) return false;
}
// success if we arrive here
return false;
}
bool CheckA9lh(void)
@ -296,12 +315,12 @@ int WriteNandSectors(const void* buffer, u32 sector, u32 count, u32 keyslot)
u32 CheckNandHeader(void* header)
{
// TWL MBR check
u8 header_dec[0x200];
// TWL MBR check - ignored
/*u8 header_dec[0x200];
memcpy(header_dec, header, 0x200);
CryptNand(header_dec, 0, 1, 0x03);
if (memcmp(header_dec + 0x1BE, twl_mbr, sizeof(twl_mbr)) != 0)
return 0; // header does not belong to console
return 0; // header does not belong to console */
// header type check
u8* header_enc = header;

View File

@ -1,6 +1,9 @@
#pragma once
#include "common.h"
#include "platform.h"
#define NAND_MIN_SECTORS ((GetUnitPlatform() == PLATFORM_N3DS) ? NAND_MIN_SECTORS_N3DS : NAND_MIN_SECTORS_O3DS)
#define NAND_SYSNAND (1<<0)
#define NAND_ZERONAND (1<<3)
@ -35,6 +38,7 @@
bool InitNandCrypto(void);
bool CheckSlot0x05Crypto(void);
bool CheckSector0x96Crypto(void);
bool CheckFirmCrypto(void);
bool CheckA9lh(void);
void CryptNand(void* buffer, u32 sector, u32 count, u32 keyslot);

32
source/safety/safewrite.c Normal file
View File

@ -0,0 +1,32 @@
#include "safewrite.h"
#include "nand.h"
#include "sha.h"
// safe file writer function, warnings:
// (1) file must be opened in RW mode for this to work
// (2) contents of buffer may change on corruption
// (3) uses SHA register
u32 SafeWriteFile(FIL* file, void* buff, FSIZE_t ofs, UINT btw) {
u8 sha_in[0x20];
UINT bw;
sha_quick(sha_in, buff, btw, SHA256_MODE);
if ((f_lseek(file, ofs) != FR_OK) || (f_write(file, buff, btw, &bw) != FR_OK) || (btw != bw) ||
(f_lseek(file, ofs) != FR_OK) || (f_read(file, buff, btw, &bw) != FR_OK) || (btw != bw))
return 1;
return (sha_cmp(sha_in, buff, btw, SHA256_MODE) == 0) ? 0 : 1;
}
// safe NAND writer function, warnings:
// (1) contents of buffer may change on corruption
// (2) uses SHA register
u32 SafeWriteNand(void* buff, u32 ofs, u32 btw, u32 keyslot) {
u8 sha_in[0x20];
sha_quick(sha_in, buff, btw, SHA256_MODE);
if ((WriteNandBytes(buff, ofs, btw, keyslot) != 0) || (ReadNandBytes(buff, ofs, btw, keyslot) != 0))
return 1;
return (sha_cmp(sha_in, buff, btw, SHA256_MODE) == 0) ? 0 : 1;
}

View File

@ -0,0 +1,7 @@
#pragma once
#include "common.h"
#include "ff.h"
u32 SafeWriteFile(FIL* file, void* buff, FSIZE_t ofs, UINT btw);
u32 SafeWriteNand(void* buff, u32 ofs, u32 btw, u32 keyslot);

94
source/safety/validator.c Normal file
View File

@ -0,0 +1,94 @@
#include "validator.h"
#include "sha.h"
#define FIRM_MAGIC 'F', 'I', 'R', 'M', '\0', '\0', '\0', '\0'
#define FIRM_MAX_SIZE 0x400000 // 4MB, due to FIRM partition size
// see: https://www.3dbrew.org/wiki/FIRM#Firmware_Section_Headers
typedef struct {
u32 offset;
u32 address;
u32 size;
u32 type;
u8 hash[0x20];
} __attribute__((packed)) FirmSectionHeader;
// see: https://www.3dbrew.org/wiki/FIRM#FIRM_Header
typedef struct {
u8 magic[8];
u32 entry_arm11;
u32 entry_arm9;
u8 reserved1[0x30];
FirmSectionHeader sections[4];
u8 signature[0x100];
} __attribute__((packed, aligned(16))) FirmHeader;
// from: https://github.com/AuroraWright/SafeA9LHInstaller/blob/master/source/installer.c#L9-L17
const u8 sectorHash[0x20] = {
0x82, 0xF2, 0x73, 0x0D, 0x2C, 0x2D, 0xA3, 0xF3, 0x01, 0x65, 0xF9, 0x87, 0xFD, 0xCC, 0xAC, 0x5C,
0xBA, 0xB2, 0x4B, 0x4E, 0x5F, 0x65, 0xC9, 0x81, 0xCD, 0x7B, 0xE6, 0xF4, 0x38, 0xE6, 0xD9, 0xD3
};
// standard sighax signature hash - still unknown
const u8 sighaxHash[0x20] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
u32 ValidateFirmHeader(FirmHeader* header, u32 data_size) {
u8 magic[] = { FIRM_MAGIC };
if (memcmp(header->magic, magic, sizeof(magic)) != 0)
return 1;
u32 firm_size = sizeof(FirmHeader);
for (u32 i = 0; i < 4; i++) {
FirmSectionHeader* section = header->sections + i;
if (!section->size) continue;
if (section->offset < firm_size) return 1;
firm_size = section->offset + section->size;
}
if ((firm_size > FIRM_MAX_SIZE) || (data_size && (firm_size > data_size)))
return 1;
return 0;
}
u32 ValidateFirm(void* firm, u8* firm_sha, u32 firm_size, char* output) {
FirmHeader* header = (FirmHeader*) firm;
// validate firm header
if (ValidateFirmHeader(header, firm_size) != 0)
return 1;
// hash verify all available sections
for (u32 i = 0; i < 4; i++) {
FirmSectionHeader* section = header->sections + i;
if (!section->size) continue;
if (sha_cmp(section->hash, (u8*) firm + section->offset, section->size, SHA256_MODE) != 0) {
if (output) snprintf(output, 64, "Section %lu hash mismatch", i);
return 1;
}
}
// check provided .SHA
if (sha_cmp(firm_sha, firm, firm_size, SHA256_MODE) != 0) {
if (output) snprintf(output, 64, "SHA hash mismatch");
return 1;
}
// ARM9 / ARM11 area check (?)
// more (?)
return 0;
}
u32 ValidateSector(void* sector) {
return (sha_cmp(sectorHash, sector, 0x200, SHA256_MODE) == 0) ? 0 : 1;
}
u32 CheckFirmSigHax(void* firm) {
return 0; // not like we can check that already
FirmHeader* header = (FirmHeader*) firm;
return (sha_cmp(sighaxHash, header->signature, 0x100, SHA256_MODE) == 0) ? 0 : 1;
}

View File

@ -0,0 +1,7 @@
#pragma once
#include "common.h"
u32 ValidateFirm(void* firm, u8* firm_sha, u32 firm_size, char* output);
u32 ValidateSector(void* sector);
u32 CheckFirmSigHax(void* firm);