From cd7f7c02cc3cb2b1c22b8238eb1cf674208cf06f Mon Sep 17 00:00:00 2001 From: Aurora Date: Wed, 28 Sep 2016 21:52:51 +0200 Subject: [PATCH] Moar checks --- source/crypto.c | 31 +++++++++------- source/crypto.h | 4 +- source/fatfs/diskio.c | 22 ++--------- source/fatfs/sdmmc/sdmmc.c | 5 +-- source/fatfs/sdmmc/sdmmc.h | 2 +- source/fs.c | 76 +++++++++++++++++++------------------- source/fs.h | 3 +- source/installer.c | 11 ++++-- 8 files changed, 72 insertions(+), 82 deletions(-) diff --git a/source/crypto.c b/source/crypto.c index c804325..18294f0 100755 --- a/source/crypto.c +++ b/source/crypto.c @@ -310,14 +310,14 @@ void ctrNandInit(void) } } -u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf) +int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf) { u8 __attribute__((aligned(4))) tmpCtr[sizeof(nandCtr)]; memcpy(tmpCtr, nandCtr, sizeof(nandCtr)); aes_advctr(tmpCtr, ((sector + fatStart) * 0x200) / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL); //Read - u32 result = sdmmc_nand_readsectors(sector + fatStart, sectorCount, outbuf); + int result = sdmmc_nand_readsectors(sector + fatStart, sectorCount, outbuf); //Decrypt aes_use_keyslot(nandSlot); @@ -358,28 +358,33 @@ void writeFirm(u8 *inbuf, bool isFirm1, u32 size) void setupKeyslot0x11(const void *otp, bool isA9lh) { u8 __attribute__((aligned(4))) shasum[SHA_256_HASH_SIZE]; - u8 __attribute__((aligned(4))) keyX[AES_BLOCK_SIZE]; - u8 __attribute__((aligned(4))) keyY[AES_BLOCK_SIZE]; //If booting via A9LH, use the leftover contents of the SHA register if(isA9lh) memcpy(shasum, (void *)REG_SHA_HASH, sizeof(shasum)); - //Else calculate the otp.bin hash + //Otherwise, calculate the otp.bin hash else sha(shasum, otp, 0x90, SHA_256_MODE); //Set keyX and keyY - memcpy(keyX, shasum, sizeof(keyX)); - memcpy(keyY, shasum + sizeof(keyX), sizeof(keyY)); - aes_setkey(0x11, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); - aes_setkey(0x11, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); + aes_setkey(0x11, shasum, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); + aes_setkey(0x11, shasum + AES_BLOCK_SIZE, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); } void generateSector(u8 *keySector, u32 mode) { //Inject key2 - if(mode == 0) memcpy(keySector + AES_BLOCK_SIZE, key2s[2], AES_BLOCK_SIZE); - else if(mode == 1) memcpy(keySector + AES_BLOCK_SIZE, keySector, AES_BLOCK_SIZE); - else memcpy(keySector + AES_BLOCK_SIZE, key2s[0], AES_BLOCK_SIZE); + switch(mode) + { + case 1: + memcpy(keySector + AES_BLOCK_SIZE, keySector, AES_BLOCK_SIZE); + break; + case 2: + memcpy(keySector + AES_BLOCK_SIZE, key2s[0], AES_BLOCK_SIZE); + break; + default: + memcpy(keySector + AES_BLOCK_SIZE, key2s[2], AES_BLOCK_SIZE); + break; + } if(mode != 1) { @@ -404,7 +409,7 @@ void getSector(u8 *keySector, bool isA9lh) } } -u32 verifyHash(const void *data, u32 size, const u8 *hash) +bool verifyHash(const void *data, u32 size, const u8 *hash) { u8 __attribute__((aligned(4))) shasum[SHA_256_HASH_SIZE]; sha(shasum, data, size, SHA_256_MODE); diff --git a/source/crypto.h b/source/crypto.h index 80e60ba..aa7224e 100755 --- a/source/crypto.h +++ b/source/crypto.h @@ -84,11 +84,11 @@ const u8 key2s[3][AES_BLOCK_SIZE]; void getNandCtr(void); void ctrNandInit(void); -u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf); +int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf); void readFirm0(u8 *outbuf, u32 size); void writeFirm(u8 *inbuf, bool isFirm1, u32 size); void setupKeyslot0x11(const void *otp, bool isA9lh); void generateSector(u8 *keySector, u32 mode); void getSector(u8 *keySector, bool isA9lh); -u32 verifyHash(const void *data, u32 size, const u8 *hash); +bool verifyHash(const void *data, u32 size, const u8 *hash); u32 decryptExeFs(u8 *inbuf); \ No newline at end of file diff --git a/source/fatfs/diskio.c b/source/fatfs/diskio.c index e6f366e..aa67269 100644 --- a/source/fatfs/diskio.c +++ b/source/fatfs/diskio.c @@ -33,12 +33,10 @@ DSTATUS disk_status ( /* Inidialize a Drive */ /*-----------------------------------------------------------------------*/ - DSTATUS disk_initialize ( BYTE pdrv /* Physical drive nmuber to identify the drive */ ) { - if(pdrv == CTRNAND) ctrNandInit(); @@ -58,19 +56,8 @@ DRESULT disk_read ( UINT count /* Number of sectors to read */ ) { - switch(pdrv) - { - case SDCARD: - if(sdmmc_sdcard_readsectors(sector, count, (BYTE *)buff)) - return RES_PARERR; - break; - case CTRNAND: - if(ctrNandRead(sector, count, (BYTE *)buff)) - return RES_PARERR; - break; - } - - return RES_OK; + return ((pdrv == SDCARD && !sdmmc_sdcard_readsectors(sector, count, (BYTE *)buff)) || + (pdrv == CTRNAND && !ctrNandRead(sector, count, (BYTE *)buff))) ? RES_OK : RES_PARERR; } @@ -87,10 +74,7 @@ DRESULT disk_write ( UINT count /* Number of sectors to write */ ) { - if(pdrv == SDCARD && sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) - return RES_PARERR; - - return RES_OK; + return (pdrv == SDCARD && !sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) ? RES_OK : RES_PARERR; } #endif diff --git a/source/fatfs/sdmmc/sdmmc.c b/source/fatfs/sdmmc/sdmmc.c index 150fac3..3836853 100644 --- a/source/fatfs/sdmmc/sdmmc.c +++ b/source/fatfs/sdmmc/sdmmc.c @@ -470,9 +470,8 @@ void sdmmc_get_cid(bool isNand, u32 *info) sdmmc_send_command(device, 0x10507, device->initarg << 0x10); } -void sdmmc_sdcard_init() +bool sdmmc_sdcard_init() { InitSD(); - Nand_Init(); - SD_Init(); + return Nand_Init() + SD_Init() == 0; } \ No newline at end of file diff --git a/source/fatfs/sdmmc/sdmmc.h b/source/fatfs/sdmmc/sdmmc.h index fa3d960..6d98cba 100644 --- a/source/fatfs/sdmmc/sdmmc.h +++ b/source/fatfs/sdmmc/sdmmc.h @@ -91,7 +91,7 @@ typedef struct mmcdevice { u32 res; } mmcdevice; -void sdmmc_sdcard_init(); +bool sdmmc_sdcard_init(); int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out); int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in); int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out); diff --git a/source/fs.c b/source/fs.c index d49de60..8d2940f 100644 --- a/source/fs.c +++ b/source/fs.c @@ -27,14 +27,9 @@ static FATFS fs; -bool mountSd(void) +bool mountFs(bool isSd) { - return f_mount(&fs, "0:", 1) == FR_OK; -} - -bool mountCtrNand(void) -{ - return f_mount(&fs, "1:", 1) == FR_OK; + return isSd ? f_mount(&fs, "0:", 1) == FR_OK : f_mount(&fs, "1:", 1) == FR_OK; } u32 fileRead(void *dest, const char *path, u32 maxSize) @@ -45,7 +40,7 @@ u32 fileRead(void *dest, const char *path, u32 maxSize) if(f_open(&file, path, FA_READ) == FR_OK) { u32 size = f_size(&file); - if(!(size > maxSize)) + if(size <= maxSize) f_read(&file, dest, size, (unsigned int *)&ret); f_close(&file); } @@ -96,47 +91,50 @@ u32 firmRead(void *dest) DIR dir; FILINFO info; - f_opendir(&dir, path); - u32 firmVersion = 0xFFFFFFFF, ret = 0; - //Parse the target directory - while(f_readdir(&dir, &info) == FR_OK && info.fname[0] != 0) + if(f_opendir(&dir, path) == FR_OK) { - //Not a cxi - if(info.fname[9] != 'a' || strlen(info.fname) != 12) continue; - - //Multiple cxis were found - if(firmVersion != 0xFFFFFFFF) ret = 1; - - //Convert the .app name to an integer - u32 tempVersion = 0; - for(char *tmp = info.altname; *tmp != '.'; tmp++) + //Parse the target directory + while(f_readdir(&dir, &info) == FR_OK && info.fname[0] != 0) { - tempVersion <<= 4; - tempVersion += *tmp > '9' ? *tmp - 'A' + 10 : *tmp - '0'; + //Not a cxi + if(info.fname[9] != 'a' || strlen(info.fname) != 12) continue; + + //Multiple cxis were found + if(firmVersion != 0xFFFFFFFF) ret = 1; + + //Convert the .app name to an integer + u32 tempVersion = 0; + for(char *tmp = info.altname; *tmp != '.'; tmp++) + { + tempVersion <<= 4; + tempVersion += *tmp > '9' ? *tmp - 'A' + 10 : *tmp - '0'; + } + + //FIRM is equal or newer than 11.0 + if(tempVersion >= (isN3DS ? 0x21 : 0x52)) ret = 2; + + //Found an older cxi + if(tempVersion < firmVersion) firmVersion = tempVersion; } - //FIRM is equal or newer than 11.0 - if(tempVersion >= (isN3DS ? 0x21 : 0x52)) ret = 2; + f_closedir(&dir); - //Found an older cxi - if(tempVersion < firmVersion) firmVersion = tempVersion; + if(!ret && firmVersion != 0xFFFFFFFF) + { + //Complete the string with the .app name + concatenateStrings(path, "/00000000.app"); + + //Convert back the .app name from integer to array + hexItoa(firmVersion, &path[35], 8); + + if(!fileRead(dest, path, 0x100000)) ret = 3; + } } - f_closedir(&dir); - - if(!ret) - { - //Complete the string with the .app name - concatenateStrings(path, "/00000000.app"); - - //Convert back the .app name from integer to array - hexItoa(firmVersion, &path[35], 8); - - if(!fileRead(dest, path, 0x100000)) ret = 3; - } + if(firmVersion == 0xFFFFFFFF) ret = 4; return ret; } \ No newline at end of file diff --git a/source/fs.h b/source/fs.h index 8f12048..5ac6902 100644 --- a/source/fs.h +++ b/source/fs.h @@ -26,8 +26,7 @@ extern bool isN3DS; -bool mountSd(void); -bool mountCtrNand(void); +bool mountFs(bool isSd); u32 fileRead(void *dest, const char *path, u32 maxSize); bool fileWrite(const void *buffer, const char *path, u32 size); u32 firmRead(void *dest); \ No newline at end of file diff --git a/source/installer.c b/source/installer.c index 43c8682..a2e0664 100755 --- a/source/installer.c +++ b/source/installer.c @@ -52,12 +52,14 @@ void main(void) vu32 *magic = (vu32 *)0x25000000; bool isOtpless = isA9lh && magic[0] == 0xABADCAFE && magic[1] == 0xDEADCAFE; - sdmmc_sdcard_init(); initScreens(); drawString(TITLE, 10, 10, COLOR_TITLE); posY = drawString("Thanks to delebile, #cakey and StandardBus", 10, 40, COLOR_WHITE); + if(!sdmmc_sdcard_init() && !isOtpless) + shutdown(1, "Error: failed to initialize SD and NAND"); + u32 pressed; if(!isOtpless) @@ -84,7 +86,7 @@ static inline void installer(bool isA9lh, bool isOtpless) u8 otp[256] = {0}, keySector[512]; - if(!isOtpless && !mountSd()) + if(!isOtpless && !mountFs(true)) shutdown(1, "Error: failed to mount the SD card"); //If making a first install on O3DS, we need the OTP @@ -241,7 +243,7 @@ static inline void uninstaller(void) } else memset32(keySector, 0, sizeof(keySector)); - if(!mountCtrNand()) + if(!mountFs(false)) shutdown(1, "Error: failed to mount CTRNAND"); //Read FIRM cxi from CTRNAND @@ -256,6 +258,9 @@ static inline void uninstaller(void) case 3: shutdown(1, "Error: the CTRNAND FIRM is too large"); break; + case 4: + shutdown(1, "Error: couldn't read FIRM from CTRNAND"); + break; default: break; }