From e8a9cfd96aa4479f50df16a22676e610683cc2b2 Mon Sep 17 00:00:00 2001 From: Aurora Date: Wed, 28 Sep 2016 14:56:11 +0200 Subject: [PATCH] Switch to arrays for otp and keysector --- source/crypto.c | 3 ++- source/fs.c | 4 ++-- source/installer.c | 46 ++++++++++++++++++++++++++-------------------- source/installer.h | 16 +++++++--------- 4 files changed, 37 insertions(+), 32 deletions(-) diff --git a/source/crypto.c b/source/crypto.c index 9ab89c0..c804325 100755 --- a/source/crypto.c +++ b/source/crypto.c @@ -423,8 +423,9 @@ u32 decryptExeFs(u8 *inbuf) ncchCtr[8] = 2; aes_setkey(0x2C, inbuf, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); + aes_advctr(ncchCtr, 0x200 / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL); aes_use_keyslot(0x2C); - aes(inbuf - 0x200, exeFsOffset, exeFsSize / AES_BLOCK_SIZE, ncchCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); + aes(inbuf, exeFsOffset + 0x200, exeFsSize / AES_BLOCK_SIZE, ncchCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); return exeFsSize - 0x200; } \ No newline at end of file diff --git a/source/fs.c b/source/fs.c index da8573b..3800abb 100644 --- a/source/fs.c +++ b/source/fs.c @@ -45,7 +45,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(!(maxSize > 0 && size > maxSize)) + if(!(size > maxSize)) f_read(&file, dest, size, (unsigned int *)&ret); f_close(&file); } @@ -135,7 +135,7 @@ u32 firmRead(void *dest) //Convert back the .app name from integer to array hexItoa(firmVersion, &path[35], 8); - fileRead(dest, path, 0); + if(!fileRead(dest, path, 0x100000)) ret = 3; } return ret; diff --git a/source/installer.c b/source/installer.c index 2c39a95..43c8682 100755 --- a/source/installer.c +++ b/source/installer.c @@ -80,34 +80,35 @@ void main(void) static inline void installer(bool isA9lh, bool isOtpless) { + bool updateA9lh = false; + u8 otp[256] = {0}, + keySector[512]; + if(!isOtpless && !mountSd()) shutdown(1, "Error: failed to mount the SD card"); - bool updateA9lh = false; - //If making a first install on O3DS, we need the OTP if(!isA9lh && !isN3DS) { const char otpPath[] = "a9lh/otp.bin"; - const u8 zeroes[256] = {0}; //Prefer OTP from memory if available - if(memcmp((void *)OTP_FROM_MEM, zeroes, 256) == 0) + if(memcmp((void *)OTP_FROM_MEM, otp, sizeof(otp)) == 0) { // Read OTP from file - if(fileRead((void *)OTP_OFFSET, otpPath, 256) != 256) + if(fileRead(otp, otpPath, sizeof(otp)) != sizeof(otp)) shutdown(1, "Error: otp.bin doesn't exist and can't be dumped"); } else { //Write OTP from memory to file - fileWrite((void *)OTP_FROM_MEM, otpPath, 256); - memcpy((void *)OTP_OFFSET, (void *)OTP_FROM_MEM, 256); + fileWrite((void *)OTP_FROM_MEM, otpPath, sizeof(otp)); + memcpy(otp, (void *)OTP_FROM_MEM, sizeof(otp)); } } //Setup the key sector de/encryption with the SHA register or otp.bin - if(isA9lh || !isN3DS) setupKeyslot0x11((void *)OTP_OFFSET, isA9lh); + if(isA9lh || !isN3DS) setupKeyslot0x11(otp, isA9lh); //Calculate the CTR for the 3DS partitions getNandCtr(); @@ -121,13 +122,13 @@ static inline void installer(bool isA9lh, bool isOtpless) } //If booting from A9LH or on N3DS, we can use the key sector from NAND - if(isA9lh || isN3DS) getSector((u8 *)SECTOR_OFFSET, isA9lh); + if(isA9lh || isN3DS) getSector(keySector, isA9lh); else { //Read decrypted key sector - if(fileRead((void *)SECTOR_OFFSET, "a9lh/secret_sector.bin", 0x200) != 0x200) + if(fileRead(keySector, "a9lh/secret_sector.bin", sizeof(keySector)) != sizeof(keySector)) shutdown(1, "Error: secret_sector.bin doesn't exist or has\na wrong size"); - if(!verifyHash((void *)SECTOR_OFFSET, 0x200, sectorHash)) + if(!verifyHash(keySector, sizeof(keySector), sectorHash)) shutdown(1, "Error: secret_sector.bin is invalid or corrupted"); } @@ -135,7 +136,7 @@ static inline void installer(bool isA9lh, bool isOtpless) { u32 i; for(i = 0; i < 3; i++) - if(memcmp((void *)(SECTOR_OFFSET + AES_BLOCK_SIZE), key2s[i], AES_BLOCK_SIZE) == 0) break; + if(memcmp(keySector + AES_BLOCK_SIZE, key2s[i], AES_BLOCK_SIZE) == 0) break; if(i == 4) shutdown(1, "Error: the OTP hash or the NAND key sector\nare invalid"); if(i == 0) updateA9lh = true; @@ -159,7 +160,7 @@ static inline void installer(bool isA9lh, bool isOtpless) } } - if(!isA9lh || updateA9lh || isOtpless) generateSector((u8 *)SECTOR_OFFSET, (isN3DS && !isA9lh) ? 1 : 0); + if(!isA9lh || updateA9lh || isOtpless) generateSector(keySector, (isN3DS && !isA9lh) ? 1 : 0); if(!isA9lh || updateA9lh) { @@ -194,7 +195,7 @@ static inline void installer(bool isA9lh, bool isOtpless) } if(!isA9lh) writeFirm((u8 *)FIRM1_OFFSET, true, FIRM1_SIZE); - if(!isA9lh || updateA9lh || isOtpless) sdmmc_nand_writesectors(0x96, 1, (u8 *)SECTOR_OFFSET); + if(!isA9lh || updateA9lh || isOtpless) sdmmc_nand_writesectors(0x96, 1, keySector); if(!isA9lh && isN3DS) { @@ -213,6 +214,8 @@ static inline void installer(bool isA9lh, bool isOtpless) static inline void uninstaller(void) { + u8 keySector[512]; + posY = drawString("You are about to uninstall A9LH!", 10, posY + 10, COLOR_RED); posY = drawString("Doing this will require having 9.0 to reinstall!", 10, posY, COLOR_RED); posY = drawString("If you would like to continue, press:", 10, posY, COLOR_WHITE); @@ -231,12 +234,12 @@ static inline void uninstaller(void) if(isN3DS) { setupKeyslot0x11(NULL, true); - getSector((u8 *)SECTOR_OFFSET, true); - if(memcmp((void *)(SECTOR_OFFSET + 0x10), key2s[1], 0x10) != 0 && memcmp((void *)(SECTOR_OFFSET + 0x10), key2s[2], 0x10) != 0) + getSector(keySector, true); + if(memcmp(keySector + AES_BLOCK_SIZE, key2s[1], AES_BLOCK_SIZE) != 0 && memcmp(keySector + AES_BLOCK_SIZE, key2s[2], AES_BLOCK_SIZE) != 0) shutdown(1, "Error: the OTP hash or the NAND key sector\nare invalid"); - generateSector((u8 *)SECTOR_OFFSET, 2); + generateSector(keySector, 2); } - else memset32((void *)SECTOR_OFFSET, 0, 0x200); + else memset32(keySector, 0, sizeof(keySector)); if(!mountCtrNand()) shutdown(1, "Error: failed to mount CTRNAND"); @@ -250,12 +253,15 @@ static inline void uninstaller(void) case 2: shutdown(1, "Error: a FIRM equal or newer than 11.0\nhas been detected"); break; + case 3: + shutdown(1, "Error: the CTRNAND FIRM is too large"); + break; default: break; } //Decrypt it and get its size - u32 firmSize = decryptExeFs((void *)FIRM0_OFFSET); + u32 firmSize = decryptExeFs((u8 *)FIRM0_OFFSET); //writeFirm encrypts in-place, so we need two copies memcpy((void *)FIRM1_OFFSET, (void *)FIRM0_OFFSET, firmSize); @@ -266,7 +272,7 @@ static inline void uninstaller(void) posY = drawString("All checks passed, uninstalling...", 10, posY + SPACING_Y, COLOR_WHITE); //Point of no return, install stuff in the safest order - sdmmc_nand_writesectors(0x96, 1, (u8 *)SECTOR_OFFSET); + sdmmc_nand_writesectors(0x96, 1, keySector); writeFirm((u8 *)FIRM0_OFFSET, false, firmSize); writeFirm((u8 *)FIRM1_OFFSET, true, firmSize); sdmmc_nand_writesectors(0x5C000, MAX_STAGE2_SIZE / 0x200, (u8 *)STAGE2_OFFSET); diff --git a/source/installer.h b/source/installer.h index aeb24e6..c7658e1 100644 --- a/source/installer.h +++ b/source/installer.h @@ -6,22 +6,20 @@ #include "types.h" -#define PDN_MPCORE_CFG (*(vu8 *)0x10140FFC) -#define PDN_SPI_CNT (*(vu8 *)0x101401C0) +#define PDN_MPCORE_CFG (*(vu32 *)0x10140FFC) +#define PDN_SPI_CNT (*(vu32 *)0x101401C0) #define OTP_FROM_MEM 0x10012000 -#define OTP_OFFSET 0x24000000 -#define SECTOR_OFFSET 0x24100000 -#define FIRM0_OFFSET 0x24200000 -#define FIRM0_100_OFFSET 0x24300000 -#define FIRM1_OFFSET 0x24400000 +#define FIRM0_OFFSET 0x24000000 +#define SECTION2_POSITION 0x66A00 +#define FIRM0_100_OFFSET 0x24100000 +#define FIRM1_OFFSET 0x24200000 #define FIRM0_SIZE 0xF3000 #define FIRM0100_SIZE 0xF2000 -#define SECTION2_POSITION 0x66A00 #define FIRM1_SIZE 0xF2000 #define STAGE1_POSITION 0xF0590 #define STAGE1_OFFSET FIRM0_OFFSET + STAGE1_POSITION -#define STAGE2_OFFSET 0x24500000 +#define STAGE2_OFFSET 0x24300000 #define MAX_STAGE1_SIZE 0x1E70 #define MAX_STAGE2_SIZE 0x89A00