Moar checks

This commit is contained in:
Aurora 2016-09-28 21:52:51 +02:00
parent 8a280fa34b
commit cd7f7c02cc
8 changed files with 72 additions and 82 deletions

View File

@ -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)]; u8 __attribute__((aligned(4))) tmpCtr[sizeof(nandCtr)];
memcpy(tmpCtr, nandCtr, sizeof(nandCtr)); memcpy(tmpCtr, nandCtr, sizeof(nandCtr));
aes_advctr(tmpCtr, ((sector + fatStart) * 0x200) / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL); aes_advctr(tmpCtr, ((sector + fatStart) * 0x200) / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL);
//Read //Read
u32 result = sdmmc_nand_readsectors(sector + fatStart, sectorCount, outbuf); int result = sdmmc_nand_readsectors(sector + fatStart, sectorCount, outbuf);
//Decrypt //Decrypt
aes_use_keyslot(nandSlot); aes_use_keyslot(nandSlot);
@ -358,28 +358,33 @@ void writeFirm(u8 *inbuf, bool isFirm1, u32 size)
void setupKeyslot0x11(const void *otp, bool isA9lh) void setupKeyslot0x11(const void *otp, bool isA9lh)
{ {
u8 __attribute__((aligned(4))) shasum[SHA_256_HASH_SIZE]; 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 booting via A9LH, use the leftover contents of the SHA register
if(isA9lh) memcpy(shasum, (void *)REG_SHA_HASH, sizeof(shasum)); 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); else sha(shasum, otp, 0x90, SHA_256_MODE);
//Set keyX and keyY //Set keyX and keyY
memcpy(keyX, shasum, sizeof(keyX)); aes_setkey(0x11, shasum, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
memcpy(keyY, shasum + sizeof(keyX), sizeof(keyY)); aes_setkey(0x11, shasum + AES_BLOCK_SIZE, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x11, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x11, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
} }
void generateSector(u8 *keySector, u32 mode) void generateSector(u8 *keySector, u32 mode)
{ {
//Inject key2 //Inject key2
if(mode == 0) memcpy(keySector + AES_BLOCK_SIZE, key2s[2], AES_BLOCK_SIZE); switch(mode)
else if(mode == 1) memcpy(keySector + AES_BLOCK_SIZE, keySector, AES_BLOCK_SIZE); {
else memcpy(keySector + AES_BLOCK_SIZE, key2s[0], AES_BLOCK_SIZE); 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) 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]; u8 __attribute__((aligned(4))) shasum[SHA_256_HASH_SIZE];
sha(shasum, data, size, SHA_256_MODE); sha(shasum, data, size, SHA_256_MODE);

View File

@ -84,11 +84,11 @@ const u8 key2s[3][AES_BLOCK_SIZE];
void getNandCtr(void); void getNandCtr(void);
void ctrNandInit(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 readFirm0(u8 *outbuf, u32 size);
void writeFirm(u8 *inbuf, bool isFirm1, u32 size); void writeFirm(u8 *inbuf, bool isFirm1, u32 size);
void setupKeyslot0x11(const void *otp, bool isA9lh); void setupKeyslot0x11(const void *otp, bool isA9lh);
void generateSector(u8 *keySector, u32 mode); void generateSector(u8 *keySector, u32 mode);
void getSector(u8 *keySector, bool isA9lh); 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); u32 decryptExeFs(u8 *inbuf);

View File

@ -33,12 +33,10 @@ DSTATUS disk_status (
/* Inidialize a Drive */ /* Inidialize a Drive */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
DSTATUS disk_initialize ( DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */ BYTE pdrv /* Physical drive nmuber to identify the drive */
) )
{ {
if(pdrv == CTRNAND) if(pdrv == CTRNAND)
ctrNandInit(); ctrNandInit();
@ -58,19 +56,8 @@ DRESULT disk_read (
UINT count /* Number of sectors to read */ UINT count /* Number of sectors to read */
) )
{ {
switch(pdrv) return ((pdrv == SDCARD && !sdmmc_sdcard_readsectors(sector, count, (BYTE *)buff)) ||
{ (pdrv == CTRNAND && !ctrNandRead(sector, count, (BYTE *)buff))) ? RES_OK : RES_PARERR;
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;
} }
@ -87,10 +74,7 @@ DRESULT disk_write (
UINT count /* Number of sectors to write */ UINT count /* Number of sectors to write */
) )
{ {
if(pdrv == SDCARD && sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) return (pdrv == SDCARD && !sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) ? RES_OK : RES_PARERR;
return RES_PARERR;
return RES_OK;
} }
#endif #endif

View File

@ -470,9 +470,8 @@ void sdmmc_get_cid(bool isNand, u32 *info)
sdmmc_send_command(device, 0x10507, device->initarg << 0x10); sdmmc_send_command(device, 0x10507, device->initarg << 0x10);
} }
void sdmmc_sdcard_init() bool sdmmc_sdcard_init()
{ {
InitSD(); InitSD();
Nand_Init(); return Nand_Init() + SD_Init() == 0;
SD_Init();
} }

View File

@ -91,7 +91,7 @@ typedef struct mmcdevice {
u32 res; u32 res;
} mmcdevice; } mmcdevice;
void sdmmc_sdcard_init(); bool sdmmc_sdcard_init();
int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out); 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_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in);
int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out); int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out);

View File

@ -27,14 +27,9 @@
static FATFS fs; static FATFS fs;
bool mountSd(void) bool mountFs(bool isSd)
{ {
return f_mount(&fs, "0:", 1) == FR_OK; return isSd ? f_mount(&fs, "0:", 1) == FR_OK : f_mount(&fs, "1:", 1) == FR_OK;
}
bool mountCtrNand(void)
{
return f_mount(&fs, "1:", 1) == FR_OK;
} }
u32 fileRead(void *dest, const char *path, u32 maxSize) 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) if(f_open(&file, path, FA_READ) == FR_OK)
{ {
u32 size = f_size(&file); u32 size = f_size(&file);
if(!(size > maxSize)) if(size <= maxSize)
f_read(&file, dest, size, (unsigned int *)&ret); f_read(&file, dest, size, (unsigned int *)&ret);
f_close(&file); f_close(&file);
} }
@ -96,47 +91,50 @@ u32 firmRead(void *dest)
DIR dir; DIR dir;
FILINFO info; FILINFO info;
f_opendir(&dir, path);
u32 firmVersion = 0xFFFFFFFF, u32 firmVersion = 0xFFFFFFFF,
ret = 0; ret = 0;
//Parse the target directory if(f_opendir(&dir, path) == FR_OK)
while(f_readdir(&dir, &info) == FR_OK && info.fname[0] != 0)
{ {
//Not a cxi //Parse the target directory
if(info.fname[9] != 'a' || strlen(info.fname) != 12) continue; while(f_readdir(&dir, &info) == FR_OK && info.fname[0] != 0)
//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; //Not a cxi
tempVersion += *tmp > '9' ? *tmp - 'A' + 10 : *tmp - '0'; 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 f_closedir(&dir);
if(tempVersion >= (isN3DS ? 0x21 : 0x52)) ret = 2;
//Found an older cxi if(!ret && firmVersion != 0xFFFFFFFF)
if(tempVersion < firmVersion) firmVersion = tempVersion; {
//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(firmVersion == 0xFFFFFFFF) ret = 4;
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;
}
return ret; return ret;
} }

View File

@ -26,8 +26,7 @@
extern bool isN3DS; extern bool isN3DS;
bool mountSd(void); bool mountFs(bool isSd);
bool mountCtrNand(void);
u32 fileRead(void *dest, const char *path, u32 maxSize); u32 fileRead(void *dest, const char *path, u32 maxSize);
bool fileWrite(const void *buffer, const char *path, u32 size); bool fileWrite(const void *buffer, const char *path, u32 size);
u32 firmRead(void *dest); u32 firmRead(void *dest);

View File

@ -52,12 +52,14 @@ void main(void)
vu32 *magic = (vu32 *)0x25000000; vu32 *magic = (vu32 *)0x25000000;
bool isOtpless = isA9lh && magic[0] == 0xABADCAFE && magic[1] == 0xDEADCAFE; bool isOtpless = isA9lh && magic[0] == 0xABADCAFE && magic[1] == 0xDEADCAFE;
sdmmc_sdcard_init();
initScreens(); initScreens();
drawString(TITLE, 10, 10, COLOR_TITLE); drawString(TITLE, 10, 10, COLOR_TITLE);
posY = drawString("Thanks to delebile, #cakey and StandardBus", 10, 40, COLOR_WHITE); 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; u32 pressed;
if(!isOtpless) if(!isOtpless)
@ -84,7 +86,7 @@ static inline void installer(bool isA9lh, bool isOtpless)
u8 otp[256] = {0}, u8 otp[256] = {0},
keySector[512]; keySector[512];
if(!isOtpless && !mountSd()) if(!isOtpless && !mountFs(true))
shutdown(1, "Error: failed to mount the SD card"); shutdown(1, "Error: failed to mount the SD card");
//If making a first install on O3DS, we need the OTP //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)); else memset32(keySector, 0, sizeof(keySector));
if(!mountCtrNand()) if(!mountFs(false))
shutdown(1, "Error: failed to mount CTRNAND"); shutdown(1, "Error: failed to mount CTRNAND");
//Read FIRM cxi from CTRNAND //Read FIRM cxi from CTRNAND
@ -256,6 +258,9 @@ static inline void uninstaller(void)
case 3: case 3:
shutdown(1, "Error: the CTRNAND FIRM is too large"); shutdown(1, "Error: the CTRNAND FIRM is too large");
break; break;
case 4:
shutdown(1, "Error: couldn't read FIRM from CTRNAND");
break;
default: default:
break; break;
} }