mirror of
https://github.com/AuroraWright/SafeA9LHInstaller.git
synced 2025-06-26 13:42:45 +00:00
Moar checks
This commit is contained in:
parent
8a280fa34b
commit
cd7f7c02cc
@ -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);
|
||||
|
@ -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);
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
||||
|
76
source/fs.c
76
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;
|
||||
}
|
@ -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);
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user