Minor stuff
This commit is contained in:
parent
420ccdcb82
commit
b7b3400296
@ -64,7 +64,7 @@ void writeConfig(ConfigurationStatus needConfig, u32 configTemp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void configMenu(bool oldPinStatus)
|
void configMenu(bool oldPinStatus, u32 oldPinMode)
|
||||||
{
|
{
|
||||||
const char *multiOptionsText[] = { "Default EmuNAND: 1( ) 2( ) 3( ) 4( )",
|
const char *multiOptionsText[] = { "Default EmuNAND: 1( ) 2( ) 3( ) 4( )",
|
||||||
"Screen brightness: 4( ) 3( ) 2( ) 1( )",
|
"Screen brightness: 4( ) 3( ) 2( ) 1( )",
|
||||||
@ -327,8 +327,6 @@ void configMenu(bool oldPinStatus)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 oldPinLength = MULTICONFIG(PIN);
|
|
||||||
|
|
||||||
//Preserve the last-used boot options (first 9 bits)
|
//Preserve the last-used boot options (first 9 bits)
|
||||||
configData.config &= 0x1FF;
|
configData.config &= 0x1FF;
|
||||||
|
|
||||||
@ -338,7 +336,9 @@ void configMenu(bool oldPinStatus)
|
|||||||
for(u32 i = 0; i < singleOptionsAmount; i++)
|
for(u32 i = 0; i < singleOptionsAmount; i++)
|
||||||
configData.config |= (singleOptions[i].enabled ? 1 : 0) << (i + 21);
|
configData.config |= (singleOptions[i].enabled ? 1 : 0) << (i + 21);
|
||||||
|
|
||||||
if(MULTICONFIG(PIN) != 0) newPin(oldPinStatus && MULTICONFIG(PIN) == oldPinLength);
|
u32 newPinMode = MULTICONFIG(PIN);
|
||||||
|
|
||||||
|
if(newPinMode != 0) newPin(oldPinStatus && newPinMode == oldPinMode, newPinMode);
|
||||||
else if(oldPinStatus) fileDelete(PIN_PATH);
|
else if(oldPinStatus) fileDelete(PIN_PATH);
|
||||||
|
|
||||||
//Wait for the pressed buttons to change
|
//Wait for the pressed buttons to change
|
||||||
|
@ -79,4 +79,4 @@ extern bool isN3DS;
|
|||||||
|
|
||||||
bool readConfig(void);
|
bool readConfig(void);
|
||||||
void writeConfig(ConfigurationStatus needConfig, u32 configTemp);
|
void writeConfig(ConfigurationStatus needConfig, u32 configTemp);
|
||||||
void configMenu(bool oldPinStatus);
|
void configMenu(bool oldPinStatus, u32 oldPinMode);
|
170
source/crypto.c
170
source/crypto.c
@ -294,22 +294,22 @@ static void sha(void *res, const void *src, u32 size, u32 mode)
|
|||||||
|
|
||||||
/*****************************************************************/
|
/*****************************************************************/
|
||||||
|
|
||||||
static u8 __attribute__((aligned(4))) nandCTR[0x10];
|
static u8 __attribute__((aligned(4))) nandCtr[AES_BLOCK_SIZE];
|
||||||
static u8 nandSlot;
|
static u8 nandSlot;
|
||||||
static u32 fatStart;
|
static u32 fatStart;
|
||||||
|
|
||||||
void ctrNandInit(void)
|
void ctrNandInit(void)
|
||||||
{
|
{
|
||||||
u8 __attribute__((aligned(4))) cid[0x10];
|
u8 __attribute__((aligned(4))) cid[AES_BLOCK_SIZE];
|
||||||
u8 __attribute__((aligned(4))) shaSum[0x20];
|
u8 __attribute__((aligned(4))) shaSum[SHA_256_HASH_SIZE];
|
||||||
|
|
||||||
sdmmc_get_cid(1, (u32 *)cid);
|
sdmmc_get_cid(1, (u32 *)cid);
|
||||||
sha(shaSum, cid, 0x10, SHA_256_MODE);
|
sha(shaSum, cid, sizeof(cid), SHA_256_MODE);
|
||||||
memcpy(nandCTR, shaSum, 0x10);
|
memcpy(nandCtr, shaSum, sizeof(nandCtr));
|
||||||
|
|
||||||
if(isN3DS)
|
if(isN3DS)
|
||||||
{
|
{
|
||||||
u8 __attribute__((aligned(4))) keyY0x5[0x10] = {0x4D, 0x80, 0x4F, 0x4E, 0x99, 0x90, 0x19, 0x46, 0x13, 0xA2, 0x04, 0xAC, 0x58, 0x44, 0x60, 0xBE};
|
u8 __attribute__((aligned(4))) keyY0x5[AES_BLOCK_SIZE] = {0x4D, 0x80, 0x4F, 0x4E, 0x99, 0x90, 0x19, 0x46, 0x13, 0xA2, 0x04, 0xAC, 0x58, 0x44, 0x60, 0xBE};
|
||||||
aes_setkey(0x05, keyY0x5, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(0x05, keyY0x5, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
nandSlot = 0x05;
|
nandSlot = 0x05;
|
||||||
@ -324,9 +324,9 @@ void ctrNandInit(void)
|
|||||||
|
|
||||||
u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf)
|
u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf)
|
||||||
{
|
{
|
||||||
u8 __attribute__((aligned(4))) tmpCTR[0x10];
|
u8 __attribute__((aligned(4))) tmpCtr[sizeof(nandCtr)];
|
||||||
memcpy(tmpCTR, nandCTR, 0x10);
|
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;
|
u32 result;
|
||||||
@ -340,7 +340,7 @@ u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf)
|
|||||||
|
|
||||||
//Decrypt
|
//Decrypt
|
||||||
aes_use_keyslot(nandSlot);
|
aes_use_keyslot(nandSlot);
|
||||||
aes(outbuf, outbuf, sectorCount * 0x200 / AES_BLOCK_SIZE, tmpCTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes(outbuf, outbuf, sectorCount * 0x200 / AES_BLOCK_SIZE, tmpCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -349,8 +349,8 @@ void set6x7xKeys(void)
|
|||||||
{
|
{
|
||||||
if(!isDevUnit)
|
if(!isDevUnit)
|
||||||
{
|
{
|
||||||
const u8 __attribute__((aligned(4))) keyX0x25[0x10] = {0xCE, 0xE7, 0xD8, 0xAB, 0x30, 0xC0, 0x0D, 0xAE, 0x85, 0x0E, 0xF5, 0xE3, 0x82, 0xAC, 0x5A, 0xF3};
|
const u8 __attribute__((aligned(4))) keyX0x25[AES_BLOCK_SIZE] = {0xCE, 0xE7, 0xD8, 0xAB, 0x30, 0xC0, 0x0D, 0xAE, 0x85, 0x0E, 0xF5, 0xE3, 0x82, 0xAC, 0x5A, 0xF3};
|
||||||
const u8 __attribute__((aligned(4))) keyY0x2F[0x10] = {0xC3, 0x69, 0xBA, 0xA2, 0x1E, 0x18, 0x8A, 0x88, 0xA9, 0xAA, 0x94, 0xE5, 0x50, 0x6A, 0x9F, 0x16};
|
const u8 __attribute__((aligned(4))) keyY0x2F[AES_BLOCK_SIZE] = {0xC3, 0x69, 0xBA, 0xA2, 0x1E, 0x18, 0x8A, 0x88, 0xA9, 0xAA, 0x94, 0xE5, 0x50, 0x6A, 0x9F, 0x16};
|
||||||
|
|
||||||
aes_setkey(0x25, keyX0x25, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(0x25, keyX0x25, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
aes_setkey(0x2F, keyY0x2F, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(0x2F, keyY0x2F, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
@ -366,30 +366,31 @@ void decryptExeFs(u8 *inbuf)
|
|||||||
{
|
{
|
||||||
u8 *exeFsOffset = inbuf + *(u32 *)(inbuf + 0x1A0) * 0x200;
|
u8 *exeFsOffset = inbuf + *(u32 *)(inbuf + 0x1A0) * 0x200;
|
||||||
u32 exeFsSize = *(u32 *)(inbuf + 0x1A4) * 0x200;
|
u32 exeFsSize = *(u32 *)(inbuf + 0x1A4) * 0x200;
|
||||||
u8 __attribute__((aligned(4))) ncchCTR[0x10] = {0};
|
u8 __attribute__((aligned(4))) ncchCtr[AES_BLOCK_SIZE] = {0};
|
||||||
|
|
||||||
for(u32 i = 0; i < 8; i++)
|
for(u32 i = 0; i < 8; i++)
|
||||||
ncchCTR[7 - i] = *(inbuf + 0x108 + i);
|
ncchCtr[7 - i] = *(inbuf + 0x108 + i);
|
||||||
ncchCTR[8] = 2;
|
ncchCtr[8] = 2;
|
||||||
|
|
||||||
aes_setkey(0x2C, inbuf, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(0x2C, inbuf, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
aes_use_keyslot(0x2C);
|
aes_use_keyslot(0x2C);
|
||||||
aes(inbuf - 0x200, exeFsOffset, exeFsSize / AES_BLOCK_SIZE, ncchCTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes(inbuf - 0x200, exeFsOffset, exeFsSize / AES_BLOCK_SIZE, ncchCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void decryptNusFirm(u8 *inbuf, u8 *outbuf, u32 ncchSize)
|
void decryptNusFirm(u8 *inbuf, u8 *outbuf, u32 ncchSize)
|
||||||
{
|
{
|
||||||
const u8 keyY0x3D[0x10] = {0x0C, 0x76, 0x72, 0x30, 0xF0, 0x99, 0x8F, 0x1C, 0x46, 0x82, 0x82, 0x02, 0xFA, 0xAC, 0xBE, 0x4C};
|
const u8 keyY0x3D[AES_BLOCK_SIZE] = {0x0C, 0x76, 0x72, 0x30, 0xF0, 0x99, 0x8F, 0x1C, 0x46, 0x82, 0x82, 0x02, 0xFA, 0xAC, 0xBE, 0x4C};
|
||||||
u8 __attribute__((aligned(4))) cetkIv[0x10] = {0};
|
u8 __attribute__((aligned(4))) cetkIv[AES_BLOCK_SIZE] = {0};
|
||||||
u8 __attribute__((aligned(4))) titleKey[0x10];
|
u8 __attribute__((aligned(4))) titleKey[AES_BLOCK_SIZE];
|
||||||
memcpy(titleKey, inbuf + 0x1BF, 0x10);
|
|
||||||
|
memcpy(titleKey, inbuf + 0x1BF, sizeof(titleKey));
|
||||||
memcpy(cetkIv, inbuf + 0x1DC, 8);
|
memcpy(cetkIv, inbuf + 0x1DC, 8);
|
||||||
|
|
||||||
aes_setkey(0x3D, keyY0x3D, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(0x3D, keyY0x3D, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
aes_use_keyslot(0x3D);
|
aes_use_keyslot(0x3D);
|
||||||
aes(titleKey, titleKey, 1, cetkIv, AES_CBC_DECRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes(titleKey, titleKey, 1, cetkIv, AES_CBC_DECRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
u8 ncchIv[0x10] = {0};
|
u8 ncchIv[AES_BLOCK_SIZE] = {0};
|
||||||
|
|
||||||
aes_setkey(0x16, titleKey, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(0x16, titleKey, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
aes_use_keyslot(0x16);
|
aes_use_keyslot(0x16);
|
||||||
@ -400,87 +401,86 @@ void decryptNusFirm(u8 *inbuf, u8 *outbuf, u32 ncchSize)
|
|||||||
|
|
||||||
void arm9Loader(u8 *arm9Section)
|
void arm9Loader(u8 *arm9Section)
|
||||||
{
|
{
|
||||||
#ifdef DEV
|
|
||||||
//Check if FIRM is already decrypted
|
//Check if FIRM is already decrypted
|
||||||
if(*(u32 *)(arm9Section + 0x800) == 0x47704770) return;
|
if(*(u32 *)(arm9Section + 0x800) != 0x47704770)
|
||||||
#endif
|
|
||||||
|
|
||||||
//Determine the arm9loader version
|
|
||||||
u32 a9lVersion;
|
|
||||||
switch(arm9Section[0x53])
|
|
||||||
{
|
{
|
||||||
case 0xFF:
|
//Determine the arm9loader version
|
||||||
a9lVersion = 0;
|
u32 a9lVersion;
|
||||||
break;
|
switch(arm9Section[0x53])
|
||||||
case '1':
|
|
||||||
a9lVersion = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
a9lVersion = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Firm keys
|
|
||||||
u8 __attribute__((aligned(4))) keyY[0x10];
|
|
||||||
u8 __attribute__((aligned(4))) arm9BinCTR[0x10];
|
|
||||||
u8 arm9BinSlot = a9lVersion > 0 ? 0x16 : 0x15;
|
|
||||||
|
|
||||||
//Setup keys needed for arm9bin decryption
|
|
||||||
memcpy(keyY, arm9Section + 0x10, 0x10);
|
|
||||||
memcpy(arm9BinCTR, arm9Section + 0x20, 0x10);
|
|
||||||
|
|
||||||
//Calculate the size of the ARM9 binary
|
|
||||||
u32 arm9BinSize = 0;
|
|
||||||
//http://stackoverflow.com/questions/12791077/atoi-implementation-in-c
|
|
||||||
for(u8 *tmp = arm9Section + 0x30; *tmp != 0; tmp++)
|
|
||||||
arm9BinSize = (arm9BinSize << 3) + (arm9BinSize << 1) + *tmp - '0';
|
|
||||||
|
|
||||||
if(a9lVersion > 0)
|
|
||||||
{
|
|
||||||
u8 __attribute__((aligned(4))) keyX[0x10];
|
|
||||||
|
|
||||||
if(!isDevUnit)
|
|
||||||
{
|
{
|
||||||
const u8 __attribute__((aligned(4))) key1[0x10] = {0x07, 0x29, 0x44, 0x38, 0xF8, 0xC9, 0x75, 0x93, 0xAA, 0x0E, 0x4A, 0xB4, 0xAE, 0x84, 0xC1, 0xD8};
|
case 0xFF:
|
||||||
const u8 __attribute__((aligned(4))) key2[0x10] = {0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0};
|
a9lVersion = 0;
|
||||||
|
break;
|
||||||
aes_setkey(0x11, a9lVersion == 2 ? key2 : key1, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
case '1':
|
||||||
|
a9lVersion = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
a9lVersion = 2;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
aes_use_keyslot(0x11);
|
//Firm keys
|
||||||
aes(keyX, arm9Section + 0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
u8 __attribute__((aligned(4))) keyY[AES_BLOCK_SIZE];
|
||||||
aes_setkey(arm9BinSlot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
u8 __attribute__((aligned(4))) arm9BinCTR[AES_BLOCK_SIZE];
|
||||||
}
|
u8 arm9BinSlot = a9lVersion > 0 ? 0x16 : 0x15;
|
||||||
|
|
||||||
aes_setkey(arm9BinSlot, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
//Setup keys needed for arm9bin decryption
|
||||||
aes_use_keyslot(arm9BinSlot);
|
memcpy(keyY, arm9Section + 0x10, sizeof(keyY));
|
||||||
|
memcpy(arm9BinCTR, arm9Section + 0x20, sizeof(arm9BinCTR));
|
||||||
|
|
||||||
//Decrypt arm9bin
|
//Calculate the size of the ARM9 binary
|
||||||
aes(arm9Section + 0x800, arm9Section + 0x800, arm9BinSize / AES_BLOCK_SIZE, arm9BinCTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
u32 arm9BinSize = 0;
|
||||||
|
//http://stackoverflow.com/questions/12791077/atoi-implementation-in-c
|
||||||
|
for(u8 *tmp = arm9Section + 0x30; *tmp != 0; tmp++)
|
||||||
|
arm9BinSize = (arm9BinSize << 3) + (arm9BinSize << 1) + *tmp - '0';
|
||||||
|
|
||||||
//Set >=9.6 KeyXs
|
if(a9lVersion > 0)
|
||||||
if(a9lVersion == 2 && !isDevUnit)
|
|
||||||
{
|
|
||||||
u8 __attribute__((aligned(4))) keyData[0x10] = {0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D, 0x9D, 0x2A, 0x21, 0x98};
|
|
||||||
u8 __attribute__((aligned(4))) decKey[0x10];
|
|
||||||
|
|
||||||
//Set keys 0x19..0x1F keyXs
|
|
||||||
aes_use_keyslot(0x11);
|
|
||||||
for(u8 slot = 0x19; slot < 0x20; slot++, keyData[0xF]++)
|
|
||||||
{
|
{
|
||||||
aes(decKey, keyData, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
u8 __attribute__((aligned(4))) keyX[AES_BLOCK_SIZE];
|
||||||
aes_setkey(slot, decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
|
if(!isDevUnit)
|
||||||
|
{
|
||||||
|
const u8 __attribute__((aligned(4))) key1[AES_BLOCK_SIZE] = {0x07, 0x29, 0x44, 0x38, 0xF8, 0xC9, 0x75, 0x93, 0xAA, 0x0E, 0x4A, 0xB4, 0xAE, 0x84, 0xC1, 0xD8};
|
||||||
|
const u8 __attribute__((aligned(4))) key2[AES_BLOCK_SIZE] = {0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0};
|
||||||
|
|
||||||
|
aes_setkey(0x11, a9lVersion == 2 ? key2 : key1, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
aes_use_keyslot(0x11);
|
||||||
|
aes(keyX, arm9Section + 0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||||
|
aes_setkey(arm9BinSlot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
aes_setkey(arm9BinSlot, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
aes_use_keyslot(arm9BinSlot);
|
||||||
|
|
||||||
|
//Decrypt arm9bin
|
||||||
|
aes(arm9Section + 0x800, arm9Section + 0x800, arm9BinSize / AES_BLOCK_SIZE, arm9BinCTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
|
//Set >=9.6 KeyXs
|
||||||
|
if(a9lVersion == 2 && !isDevUnit)
|
||||||
|
{
|
||||||
|
u8 __attribute__((aligned(4))) keyData[AES_BLOCK_SIZE] = {0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D, 0x9D, 0x2A, 0x21, 0x98};
|
||||||
|
u8 __attribute__((aligned(4))) decKey[sizeof(keyData)];
|
||||||
|
|
||||||
|
//Set keys 0x19..0x1F keyXs
|
||||||
|
aes_use_keyslot(0x11);
|
||||||
|
for(u8 slot = 0x19; slot < 0x20; slot++, keyData[0xF]++)
|
||||||
|
{
|
||||||
|
aes(decKey, keyData, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||||
|
aes_setkey(slot, decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void computePinHash(u8 *out, u8 *in)
|
void computePinHash(u8 *out, u8 *in)
|
||||||
{
|
{
|
||||||
u8 __attribute__((aligned(4))) cid[0x10];
|
u8 __attribute__((aligned(4))) cid[AES_BLOCK_SIZE];
|
||||||
u8 __attribute__((aligned(4))) cipherText[0x10];
|
u8 __attribute__((aligned(4))) cipherText[AES_BLOCK_SIZE];
|
||||||
|
|
||||||
sdmmc_get_cid(1, (u32 *)cid);
|
sdmmc_get_cid(1, (u32 *)cid);
|
||||||
aes_use_keyslot(4); //Console-unique keyslot whose keys are set by the ARM9 bootROM
|
aes_use_keyslot(4); //Console-unique keyslot whose keys are set by the ARM9 bootROM
|
||||||
aes(cipherText, in, 1, cid, AES_CBC_ENCRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes(cipherText, in, 1, cid, AES_CBC_ENCRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
sha(out, cipherText, 0x10, SHA_256_MODE);
|
sha(out, cipherText, sizeof(cipherText), SHA_256_MODE);
|
||||||
}
|
}
|
@ -70,6 +70,8 @@ void main(void)
|
|||||||
//Attempt to read the configuration file
|
//Attempt to read the configuration file
|
||||||
needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;
|
needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;
|
||||||
|
|
||||||
|
u32 devMode = MULTICONFIG(DEVOPTIONS);
|
||||||
|
|
||||||
//Determine if this is a firmlaunch boot
|
//Determine if this is a firmlaunch boot
|
||||||
if(launchedFirmTidLow[5] != 0)
|
if(launchedFirmTidLow[5] != 0)
|
||||||
{
|
{
|
||||||
@ -126,26 +128,29 @@ void main(void)
|
|||||||
|
|
||||||
if(needConfig == DONT_CONFIGURE)
|
if(needConfig == DONT_CONFIGURE)
|
||||||
{
|
{
|
||||||
if(MULTICONFIG(DEVOPTIONS) != 0 && isA9lh) installArm9Handlers();
|
if(devMode != 0 && isA9lh) installArm9Handlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Boot options aren't being forced
|
//Boot options aren't being forced
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool pinExists = MULTICONFIG(PIN) != 0 && verifyPin();
|
u32 pinMode = MULTICONFIG(PIN);
|
||||||
|
bool pinExists = pinMode != 0 && verifyPin(pinMode);
|
||||||
|
|
||||||
//If no configuration file exists or SELECT is held, load configuration menu
|
//If no configuration file exists or SELECT is held, load configuration menu
|
||||||
bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & BUTTON_SELECT) && !(pressed & BUTTON_L1));
|
bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & BUTTON_SELECT) && !(pressed & BUTTON_L1));
|
||||||
|
|
||||||
if(shouldLoadConfigMenu)
|
if(shouldLoadConfigMenu)
|
||||||
{
|
{
|
||||||
configMenu(pinExists);
|
configMenu(pinExists, pinMode);
|
||||||
|
|
||||||
//Update pressed buttons
|
//Update pressed buttons
|
||||||
pressed = HID_PAD;
|
pressed = HID_PAD;
|
||||||
|
|
||||||
|
devMode = MULTICONFIG(DEVOPTIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(MULTICONFIG(DEVOPTIONS) != 0 && isA9lh) installArm9Handlers();
|
if(devMode != 0 && isA9lh) installArm9Handlers();
|
||||||
|
|
||||||
if(isA9lh && !CFG_BOOTENV && pressed == SAFE_MODE)
|
if(isA9lh && !CFG_BOOTENV && pressed == SAFE_MODE)
|
||||||
{
|
{
|
||||||
@ -164,7 +169,9 @@ void main(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(MULTICONFIG(SPLASH) == 1 && loadSplash()) pressed = HID_PAD;
|
u32 splashMode = MULTICONFIG(SPLASH);
|
||||||
|
|
||||||
|
if(splashMode == 1 && loadSplash()) pressed = HID_PAD;
|
||||||
|
|
||||||
/* If L and R/A/Select or one of the single payload buttons are pressed,
|
/* If L and R/A/Select or one of the single payload buttons are pressed,
|
||||||
chainload an external payload */
|
chainload an external payload */
|
||||||
@ -173,7 +180,7 @@ void main(void)
|
|||||||
|
|
||||||
if(shouldLoadPayload) loadPayload(pressed);
|
if(shouldLoadPayload) loadPayload(pressed);
|
||||||
|
|
||||||
if(MULTICONFIG(SPLASH) == 2) loadSplash();
|
if(splashMode == 2) loadSplash();
|
||||||
|
|
||||||
//Determine if the user chose to use the SysNAND FIRM as default for a R boot
|
//Determine if the user chose to use the SysNAND FIRM as default for a R boot
|
||||||
bool useSysAsDefault = isA9lh ? CONFIG(USESYSFIRM) : false;
|
bool useSysAsDefault = isA9lh ? CONFIG(USESYSFIRM) : false;
|
||||||
@ -246,15 +253,14 @@ void main(void)
|
|||||||
switch(firmType)
|
switch(firmType)
|
||||||
{
|
{
|
||||||
case NATIVE_FIRM:
|
case NATIVE_FIRM:
|
||||||
patchNativeFirm(firmVersion, nandType, emuHeader, isA9lh);
|
patchNativeFirm(firmVersion, nandType, emuHeader, isA9lh, devMode);
|
||||||
break;
|
break;
|
||||||
case SAFE_FIRM:
|
case SAFE_FIRM:
|
||||||
case NATIVE_FIRM1X2X:
|
case NATIVE_FIRM1X2X:
|
||||||
if(isA9lh) patch1x2xNativeAndSafeFirm();
|
if(isA9lh) patch1x2xNativeAndSafeFirm(devMode);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//Skip patching on unsupported O3DS AGB/TWL FIRMs
|
patchLegacyFirm(firmType, firmVersion, devMode);
|
||||||
if(isN3DS || firmVersion >= (firmType == TWL_FIRM ? 0x16 : 0xB)) patchLegacyFirm(firmType);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,7 +337,7 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bo
|
|||||||
return firmVersion;
|
return firmVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh)
|
static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh, u32 devMode)
|
||||||
{
|
{
|
||||||
u8 *arm9Section = (u8 *)firm + section[2].offset,
|
u8 *arm9Section = (u8 *)firm + section[2].offset,
|
||||||
*arm11Section1 = (u8 *)firm + section[1].offset;
|
*arm11Section1 = (u8 *)firm + section[1].offset;
|
||||||
@ -387,9 +393,9 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32
|
|||||||
implementSvcGetCFWInfo(arm11Section1, arm11SvcTable, baseK11VA, &freeK11Space);
|
implementSvcGetCFWInfo(arm11Section1, arm11SvcTable, baseK11VA, &freeK11Space);
|
||||||
|
|
||||||
//Apply UNITINFO patch
|
//Apply UNITINFO patch
|
||||||
if(MULTICONFIG(DEVOPTIONS) == 2) patchUnitInfoValueSet(arm9Section, section[2].size);
|
if(devMode == 2) patchUnitInfoValueSet(arm9Section, section[2].size);
|
||||||
|
|
||||||
if(isA9lh && MULTICONFIG(DEVOPTIONS) != 0)
|
if(devMode != 0 && isA9lh)
|
||||||
{
|
{
|
||||||
//ARM11 exception handlers
|
//ARM11 exception handlers
|
||||||
u32 codeSetOffset,
|
u32 codeSetOffset,
|
||||||
@ -412,7 +418,7 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void patchLegacyFirm(FirmwareType firmType)
|
static inline void patchLegacyFirm(FirmwareType firmType, u32 firmVersion, u32 devMode)
|
||||||
{
|
{
|
||||||
u8 *arm9Section = (u8 *)firm + section[3].offset;
|
u8 *arm9Section = (u8 *)firm + section[3].offset;
|
||||||
|
|
||||||
@ -423,13 +429,14 @@ static inline void patchLegacyFirm(FirmwareType firmType)
|
|||||||
firm->arm9Entry = (u8 *)0x801301C;
|
firm->arm9Entry = (u8 *)0x801301C;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyLegacyFirmPatches((u8 *)firm, firmType);
|
if(isN3DS || firmVersion >= (firmType == TWL_FIRM ? 0x16 : 0xB))
|
||||||
|
applyLegacyFirmPatches((u8 *)firm, firmType);
|
||||||
|
|
||||||
//Apply UNITINFO patch
|
//Apply UNITINFO patch
|
||||||
if(MULTICONFIG(DEVOPTIONS) == 2) patchUnitInfoValueSet(arm9Section, section[3].size);
|
if(devMode == 2) patchUnitInfoValueSet(arm9Section, section[3].size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void patch1x2xNativeAndSafeFirm(void)
|
static inline void patch1x2xNativeAndSafeFirm(u32 devMode)
|
||||||
{
|
{
|
||||||
u8 *arm9Section = (u8 *)firm + section[2].offset;
|
u8 *arm9Section = (u8 *)firm + section[2].offset;
|
||||||
|
|
||||||
@ -443,7 +450,7 @@ static inline void patch1x2xNativeAndSafeFirm(void)
|
|||||||
}
|
}
|
||||||
else patchOldFirmWrites(arm9Section, section[2].size);
|
else patchOldFirmWrites(arm9Section, section[2].size);
|
||||||
|
|
||||||
if(MULTICONFIG(DEVOPTIONS) != 0)
|
if(devMode != 0)
|
||||||
{
|
{
|
||||||
//ARM9 exception handlers
|
//ARM9 exception handlers
|
||||||
patchArm9ExceptionHandlersInstall(arm9Section, section[2].size);
|
patchArm9ExceptionHandlersInstall(arm9Section, section[2].size);
|
||||||
|
@ -48,8 +48,8 @@ typedef struct firmHeader {
|
|||||||
} firmHeader;
|
} firmHeader;
|
||||||
|
|
||||||
static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bool loadFromSd);
|
static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bool loadFromSd);
|
||||||
static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh);
|
static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh, u32 devMode);
|
||||||
static inline void patchLegacyFirm(FirmwareType firmType);
|
static inline void patchLegacyFirm(FirmwareType firmType, u32 firmVersion, u32 devMode);
|
||||||
static inline void patch1x2xNativeAndSafeFirm(void);
|
static inline void patch1x2xNativeAndSafeFirm(u32 devMode);
|
||||||
static inline void copySection0AndInjectSystemModules(FirmwareType firmType, bool loadFromSd);
|
static inline void copySection0AndInjectSystemModules(FirmwareType firmType, bool loadFromSd);
|
||||||
static inline void launchFirm(FirmwareType firmType, bool loadFromSd);
|
static inline void launchFirm(FirmwareType firmType, bool loadFromSd);
|
20
source/pin.c
20
source/pin.c
@ -44,11 +44,11 @@ static char pinKeyToLetter(u32 pressed)
|
|||||||
return keys[31 - i];
|
return keys[31 - i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void newPin(bool allowSkipping)
|
void newPin(bool allowSkipping, u32 pinMode)
|
||||||
{
|
{
|
||||||
clearScreens(true, true);
|
clearScreens(true, true);
|
||||||
|
|
||||||
u8 length = 4 + 2 * (MULTICONFIG(PIN) - 1);
|
u8 length = 4 + 2 * (pinMode - 1);
|
||||||
|
|
||||||
char *title = allowSkipping ? "Press START to skip or enter a new PIN" : "Enter a new PIN to proceed";
|
char *title = allowSkipping ? "Press START to skip or enter a new PIN" : "Enter a new PIN to proceed";
|
||||||
drawString(title, true, 10, 10, COLOR_TITLE);
|
drawString(title, true, 10, 10, COLOR_TITLE);
|
||||||
@ -56,7 +56,7 @@ void newPin(bool allowSkipping)
|
|||||||
drawCharacter('0' + length, true, 10 + 5 * SPACING_X, 10 + 2 * SPACING_Y, COLOR_WHITE);
|
drawCharacter('0' + length, true, 10 + 5 * SPACING_X, 10 + 2 * SPACING_Y, COLOR_WHITE);
|
||||||
|
|
||||||
//Pad to AES block length with zeroes
|
//Pad to AES block length with zeroes
|
||||||
u8 __attribute__((aligned(4))) enteredPassword[0x10] = {0};
|
u8 __attribute__((aligned(4))) enteredPassword[AES_BLOCK_SIZE] = {0};
|
||||||
|
|
||||||
u8 cnt = 0;
|
u8 cnt = 0;
|
||||||
u32 charDrawPos = 16 * SPACING_X;
|
u32 charDrawPos = 16 * SPACING_X;
|
||||||
@ -91,8 +91,8 @@ void newPin(bool allowSkipping)
|
|||||||
pin.formatVersionMinor = PIN_VERSIONMINOR;
|
pin.formatVersionMinor = PIN_VERSIONMINOR;
|
||||||
pin.length = length;
|
pin.length = length;
|
||||||
|
|
||||||
u8 __attribute__((aligned(4))) tmp[0x20];
|
u8 __attribute__((aligned(4))) tmp[SHA_256_HASH_SIZE];
|
||||||
u8 __attribute__((aligned(4))) zeroes[0x10] = {0};
|
u8 __attribute__((aligned(4))) zeroes[AES_BLOCK_SIZE] = {0};
|
||||||
|
|
||||||
computePinHash(tmp, zeroes);
|
computePinHash(tmp, zeroes);
|
||||||
memcpy(pin.testHash, tmp, sizeof(tmp));
|
memcpy(pin.testHash, tmp, sizeof(tmp));
|
||||||
@ -104,7 +104,7 @@ void newPin(bool allowSkipping)
|
|||||||
error("Error writing the PIN file");
|
error("Error writing the PIN file");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool verifyPin(void)
|
bool verifyPin(u32 pinMode)
|
||||||
{
|
{
|
||||||
PinData pin;
|
PinData pin;
|
||||||
|
|
||||||
@ -112,11 +112,11 @@ bool verifyPin(void)
|
|||||||
memcmp(pin.magic, "PINF", 4) != 0 ||
|
memcmp(pin.magic, "PINF", 4) != 0 ||
|
||||||
pin.formatVersionMajor != PIN_VERSIONMAJOR ||
|
pin.formatVersionMajor != PIN_VERSIONMAJOR ||
|
||||||
pin.formatVersionMinor != PIN_VERSIONMINOR ||
|
pin.formatVersionMinor != PIN_VERSIONMINOR ||
|
||||||
pin.length != 4 + 2 * (MULTICONFIG(PIN) - 1))
|
pin.length != 4 + 2 * (pinMode - 1))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
u8 __attribute__((aligned(4))) zeroes[0x10] = {0};
|
u8 __attribute__((aligned(4))) zeroes[AES_BLOCK_SIZE] = {0};
|
||||||
u8 __attribute__((aligned(4))) tmp[0x20];
|
u8 __attribute__((aligned(4))) tmp[SHA_256_HASH_SIZE];
|
||||||
|
|
||||||
computePinHash(tmp, zeroes);
|
computePinHash(tmp, zeroes);
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ bool verifyPin(void)
|
|||||||
initScreens();
|
initScreens();
|
||||||
|
|
||||||
//Pad to AES block length with zeroes
|
//Pad to AES block length with zeroes
|
||||||
u8 __attribute__((aligned(4))) enteredPassword[0x10] = {0};
|
u8 __attribute__((aligned(4))) enteredPassword[AES_BLOCK_SIZE] = {0};
|
||||||
|
|
||||||
bool unlock = false;
|
bool unlock = false;
|
||||||
u8 cnt = 0;
|
u8 cnt = 0;
|
||||||
|
@ -42,5 +42,5 @@ typedef struct __attribute__((packed))
|
|||||||
u8 hash[32];
|
u8 hash[32];
|
||||||
} PinData;
|
} PinData;
|
||||||
|
|
||||||
void newPin(bool allowSkipping);
|
void newPin(bool allowSkipping, u32 pinMode);
|
||||||
bool verifyPin(void);
|
bool verifyPin(u32 pinMode);
|
Reference in New Issue
Block a user