Switch to structs where possible

This commit is contained in:
Aurora 2016-10-08 14:23:08 +02:00
parent b575ee9e28
commit 50b24bf6c2
3 changed files with 100 additions and 28 deletions

View File

@ -24,6 +24,7 @@
* Crypto libs from http://github.com/b1l1s/ctr
* kernel9Loader code originally adapted from https://github.com/Reisyukaku/ReiNand/blob/228c378255ba693133dec6f3368e14d386f2cde7/source/crypto.c#L233
* decryptNusFirm code adapted from https://github.com/mid-kid/CakesForeveryWan/blob/master/source/firm.c
* 3ds type structs adapted from 3DBrew and https://github.com/mid-kid/CakesForeveryWan/blob/master/source/headers.h
*/
#include "crypto.h"
@ -375,29 +376,29 @@ void set6x7xKeys(void)
memset32((void *)0x01FFCD00, 0, 0x10);
}
void decryptExeFs(u8 *inbuf)
void decryptExeFs(Ncch *ncch)
{
u8 *exeFsOffset = inbuf + *(u32 *)(inbuf + 0x1A0) * 0x200;
u32 exeFsSize = *(u32 *)(inbuf + 0x1A4) * 0x200;
u8 *exeFsOffset = (u8 *)ncch + ncch->exeFsOffset * 0x200;
u32 exeFsSize = ncch->exeFsSize * 0x200;
u8 __attribute__((aligned(4))) ncchCtr[AES_BLOCK_SIZE] = {0};
for(u32 i = 0; i < 8; i++)
ncchCtr[7 - i] = *(inbuf + 0x108 + i);
ncchCtr[7 - i] = ncch->partitionId[i];
ncchCtr[8] = 2;
aes_setkey(0x2C, inbuf, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x2C, ncch, 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, exeFsOffset + 0x200, exeFsSize / AES_BLOCK_SIZE, ncchCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
aes(ncch, exeFsOffset + 0x200, exeFsSize / AES_BLOCK_SIZE, ncchCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
}
void decryptNusFirm(const u8 *inbuf, u8 *outbuf, u32 ncchSize)
void decryptNusFirm(const Ticket *ticket, Ncch *ncch, u32 ncchSize)
{
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))) titleKey[AES_BLOCK_SIZE];
u8 __attribute__((aligned(4))) cetkIv[AES_BLOCK_SIZE] = {0};
memcpy(titleKey, inbuf + 0x1BF, sizeof(titleKey));
memcpy(cetkIv, inbuf + 0x1DC, 8);
memcpy(titleKey, ticket->titleKey, sizeof(titleKey));
memcpy(cetkIv, ticket->titleId, sizeof(ticket->titleId));
aes_setkey(0x3D, keyY0x3D, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x3D);
@ -407,16 +408,16 @@ void decryptNusFirm(const u8 *inbuf, u8 *outbuf, u32 ncchSize)
aes_setkey(0x16, titleKey, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x16);
aes(outbuf, outbuf, ncchSize / AES_BLOCK_SIZE, ncchIv, AES_CBC_DECRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
aes(ncch, ncch, ncchSize / AES_BLOCK_SIZE, ncchIv, AES_CBC_DECRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
decryptExeFs(outbuf);
decryptExeFs(ncch);
}
void kernel9Loader(u8 *arm9Section)
void kernel9Loader(Arm9Bin *arm9Section)
{
//Determine the kernel9loader version
u32 k9lVersion;
switch(arm9Section[0x53])
switch(arm9Section->magic[3])
{
case 0xFF:
k9lVersion = 0;
@ -429,7 +430,7 @@ void kernel9Loader(u8 *arm9Section)
break;
}
u32 startOfArm9Bin = *(u32 *)(arm9Section + 0x800);
u32 startOfArm9Bin = *(u32 *)((u8 *)arm9Section + 0x800);
bool needToDecrypt = startOfArm9Bin != 0x47704770 && startOfArm9Bin != 0xB0862000;
if(!isDevUnit && (k9lVersion == 2 || (k9lVersion == 1 && needToDecrypt)))
@ -452,28 +453,28 @@ void kernel9Loader(u8 *arm9Section)
//Set keyX
u8 __attribute__((aligned(4))) keyX[AES_BLOCK_SIZE];
aes_use_keyslot(0x11);
aes(keyX, arm9Section + 0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
aes(keyX, arm9Section->slot0x16keyX, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
aes_setkey(0x16, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
}
//Set keyY
u8 __attribute__((aligned(4))) keyY[AES_BLOCK_SIZE];
memcpy(keyY, arm9Section + 0x10, sizeof(keyY));
memcpy(keyY, arm9Section->keyY, sizeof(keyY));
aes_setkey(arm9BinSlot, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
//Set CTR
u8 __attribute__((aligned(4))) arm9BinCtr[AES_BLOCK_SIZE];
memcpy(arm9BinCtr, arm9Section + 0x20, sizeof(arm9BinCtr));
memcpy(arm9BinCtr, arm9Section->ctr, sizeof(arm9BinCtr));
//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++)
for(u8 *tmp = arm9Section->size; *tmp != 0; tmp++)
arm9BinSize = (arm9BinSize << 3) + (arm9BinSize << 1) + *tmp - '0';
//Decrypt ARM9 binary
aes_use_keyslot(arm9BinSlot);
aes(arm9Section + 0x800, arm9Section + 0x800, arm9BinSize / AES_BLOCK_SIZE, arm9BinCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
aes((u8 *)arm9Section + 0x800, (u8 *)arm9Section + 0x800, arm9BinSize / AES_BLOCK_SIZE, arm9BinCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
}
//Set >=9.6 KeyXs

View File

@ -24,6 +24,7 @@
* Crypto libs from http://github.com/b1l1s/ctr
* kernel9Loader code originally adapted from https://github.com/Reisyukaku/ReiNand/blob/228c378255ba693133dec6f3368e14d386f2cde7/source/crypto.c#L233
* decryptNusFirm code adapted from https://github.com/mid-kid/CakesForeveryWan/blob/master/source/firm.c
* 3ds type structs adapted from 3DBrew and https://github.com/mid-kid/CakesForeveryWan/blob/master/source/headers.h
*/
#pragma once
@ -101,6 +102,76 @@
#define SHA_224_HASH_SIZE (224 / 8)
#define SHA_1_HASH_SIZE (160 / 8)
typedef struct Ncch {
uint8_t sig[0x100]; //RSA-2048 signature of the NCCH header, using SHA-256
char magic[4]; //NCCH
uint32_t contentSize; //Media unit
uint8_t partitionId[8];
uint8_t makerCode[2];
uint16_t version;
uint8_t reserved1[4];
uint8_t programID[8];
uint8_t reserved2[0x10];
uint8_t logoHash[0x20]; //Logo Region SHA-256 hash
char productCode[0x10];
uint8_t exHeaderHash[0x20]; //Extended header SHA-256 hash
uint32_t exHeaderSize; //Extended header size
uint32_t reserved3;
uint8_t flags[8];
uint32_t plainOffset; //Media unit
uint32_t plainSize; //Media unit
uint32_t logoOffset; //Media unit
uint32_t logoSize; //Media unit
uint32_t exeFsOffset; //Media unit
uint32_t exeFsSize; //Media unit
uint32_t exeFsHashSize; //Media unit
uint32_t reserved4;
uint32_t romFsOffset; //Media unit
uint32_t romFsSize; //Media unit
uint32_t romFsHashSize; //Media unit
uint32_t reserved5;
uint8_t exeFsHash[0x20]; //ExeFS superblock SHA-256 hash
uint8_t romFsHash[0x20]; //RomFS superblock SHA-256 hash
} Ncch;
typedef struct Ticket
{
char sigIssuer[0x40];
uint8_t eccPubKey[0x3C];
uint8_t version;
uint8_t caCrlVersion;
uint8_t signerCrlVersion;
uint8_t titleKey[0x10];
uint8_t reserved1;
uint8_t ticketId[8];
uint8_t consoleId[4];
uint8_t titleId[8];
uint8_t reserved2[2];
uint16_t ticketTitleVersion;
uint8_t reserved3[8];
uint8_t licenseType;
uint8_t ticketCommonKeyYIndex; //Ticket common keyY index, usually 0x1 for retail system titles.
uint8_t reserved4[0x2A];
uint8_t unk[4]; //eShop Account ID?
uint8_t reserved5;
uint8_t audit;
uint8_t reserved6[0x42];
uint8_t limits[0x40];
uint8_t contentIndex[0xAC];
} Ticket;
typedef struct Arm9Bin {
uint8_t keyX[0x10];
uint8_t keyY[0x10];
uint8_t ctr[0x10];
uint8_t size[8];
uint8_t reserved[8];
uint8_t ctlBlock[0x10];
char magic[4];
uint8_t reserved2[0xC];
uint8_t slot0x16keyX[0x10];
} Arm9Bin;
extern u32 emuOffset;
extern bool isN3DS, isDevUnit, isA9lh;
extern FirmwareSource firmSource;
@ -109,8 +180,8 @@ void ctrNandInit(void);
int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf);
int ctrNandWrite(u32 sector, u32 sectorCount, u8 *inbuf);
void set6x7xKeys(void);
void decryptExeFs(u8 *inbuf);
void decryptNusFirm(const u8 *inbuf, u8 *outbuf, u32 ncchSize);
void kernel9Loader(u8 *arm9Section);
void decryptExeFs(Ncch *ncch);
void decryptNusFirm(const Ticket *ticket, Ncch *ncch, u32 ncchSize);
void kernel9Loader(Arm9Bin *arm9Section);
void computePinHash(u8 *outbuf, const u8 *inbuf);
void restoreShaHashBackup(void);

View File

@ -331,7 +331,7 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bo
u8 cetk[0xA50];
if(fileRead(cetk, *firmType == NATIVE_FIRM1X2X ? cetkFiles[0] : cetkFiles[(u32)*firmType], sizeof(cetk)) == sizeof(cetk))
decryptNusFirm(cetk, (u8 *)firm, firmSize);
decryptNusFirm((Ticket *)&cetk[0x140], (Ncch *)firm, firmSize);
else error("The firmware.bin in /luma is encrypted\nor corrupted.");
}
@ -346,7 +346,7 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bo
if(firmVersion != 0xFFFFFFFF)
{
if(mustLoadFromStorage) error("An old unsupported FIRM has been detected.\nCopy a firmware.bin in /luma to boot.");
decryptExeFs((u8 *)firm);
decryptExeFs((Ncch *)firm);
}
return firmVersion;
@ -360,7 +360,7 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32
if(isN3DS)
{
//Decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
kernel9Loader(arm9Section);
kernel9Loader((Arm9Bin *)arm9Section);
firm->arm9Entry = (u8 *)0x801B01C;
}
@ -440,7 +440,7 @@ static inline void patchLegacyFirm(FirmwareType firmType, u32 firmVersion, u32 d
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
if(isN3DS)
{
kernel9Loader(arm9Section);
kernel9Loader((Arm9Bin *)arm9Section);
firm->arm9Entry = (u8 *)0x801301C;
}
@ -458,7 +458,7 @@ static inline void patch1x2xNativeAndSafeFirm(u32 devMode)
if(isN3DS)
{
//Decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
kernel9Loader(arm9Section);
kernel9Loader((Arm9Bin *)arm9Section);
firm->arm9Entry = (u8 *)0x801B01C;
patchFirmWrites(arm9Section, section[2].size);
@ -481,7 +481,7 @@ static inline void copySection0AndInjectSystemModules(FirmwareType firmType, boo
for(u8 *src = (u8 *)firm + section[0].offset, *srcEnd = src + section[0].size, *dst = section[0].address;
src < srcEnd; src += srcModuleSize, dst += dstModuleSize)
{
srcModuleSize = *(u32 *)(src + 0x104) * 0x200;
srcModuleSize = ((Ncch *)src)->contentSize * 0x200;
const char *moduleName = (char *)(src + 0x200);
u32 fileSize;