forked from Mirror/GodMode9
Enable crypto for sector 0x96
This commit is contained in:
parent
f448f48ad7
commit
67b54ec633
@ -7,7 +7,7 @@
|
||||
#include "virtual.h"
|
||||
#include "image.h"
|
||||
|
||||
#define VERSION "0.4.0"
|
||||
#define VERSION "0.4.1"
|
||||
|
||||
#define N_PANES 2
|
||||
#define IMG_DRV "789I"
|
||||
|
@ -6,17 +6,16 @@ void setup_aeskeyX(u8 keyslot, void* keyx)
|
||||
u32 * _keyx = (u32*)keyx;
|
||||
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
||||
if (keyslot > 3) {
|
||||
*REG_AESCNT = (*REG_AESCNT | (AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER));
|
||||
*REG_AESKEYXFIFO = _keyx[0];
|
||||
*REG_AESKEYXFIFO = _keyx[1];
|
||||
*REG_AESKEYXFIFO = _keyx[2];
|
||||
*REG_AESKEYXFIFO = _keyx[3];
|
||||
} else {
|
||||
u32 old_aescnt = *REG_AESCNT;
|
||||
vu32* reg_aeskeyx = REG_AESKEY0123 + (((0x30*keyslot) + 0x10)/4);
|
||||
*REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER));
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
reg_aeskeyx[i] = _keyx[i];
|
||||
*REG_AESCNT = old_aescnt;
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,17 +24,16 @@ void setup_aeskeyY(u8 keyslot, void* keyy)
|
||||
u32 * _keyy = (u32*)keyy;
|
||||
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
||||
if (keyslot > 3) {
|
||||
*REG_AESCNT = (*REG_AESCNT | (AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER));
|
||||
*REG_AESKEYYFIFO = _keyy[0];
|
||||
*REG_AESKEYYFIFO = _keyy[1];
|
||||
*REG_AESKEYYFIFO = _keyy[2];
|
||||
*REG_AESKEYYFIFO = _keyy[3];
|
||||
} else {
|
||||
u32 old_aescnt = *REG_AESCNT;
|
||||
vu32* reg_aeskeyy = REG_AESKEY0123 + (((0x30*keyslot) + 0x20)/4);
|
||||
*REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER));
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
reg_aeskeyy[i] = _keyy[i];
|
||||
*REG_AESCNT = old_aescnt;
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,17 +42,16 @@ void setup_aeskey(u8 keyslot, void* key)
|
||||
u32 * _key = (u32*)key;
|
||||
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
||||
if (keyslot > 3) {
|
||||
*REG_AESCNT = (*REG_AESCNT | (AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER));
|
||||
*REG_AESKEYFIFO = _key[0];
|
||||
*REG_AESKEYFIFO = _key[1];
|
||||
*REG_AESKEYFIFO = _key[2];
|
||||
*REG_AESKEYFIFO = _key[3];
|
||||
} else {
|
||||
u32 old_aescnt = *REG_AESCNT;
|
||||
vu32* reg_aeskey = REG_AESKEY0123 + ((0x30*keyslot)/4);
|
||||
*REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER));
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
reg_aeskey[i] = _key[i];
|
||||
*REG_AESCNT = old_aescnt;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,8 @@
|
||||
#define AES_CNT_TWLNAND_MODE AES_CTR_MODE
|
||||
#define AES_CNT_TITLEKEY_DECRYPT_MODE (AES_CBC_DECRYPT_MODE | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER | AES_CNT_INPUT_ENDIAN | AES_CNT_OUTPUT_ENDIAN)
|
||||
#define AES_CNT_TITLEKEY_ENCRYPT_MODE (AES_CBC_ENCRYPT_MODE | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER | AES_CNT_INPUT_ENDIAN | AES_CNT_OUTPUT_ENDIAN)
|
||||
#define AES_CNT_ECB_DECRYPT_MODE (AES_ECB_DECRYPT_MODE | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER | AES_CNT_INPUT_ENDIAN | AES_CNT_OUTPUT_ENDIAN)
|
||||
#define AES_CNT_ECB_ENCRYPT_MODE (AES_ECB_ENCRYPT_MODE | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER | AES_CNT_INPUT_ENDIAN | AES_CNT_OUTPUT_ENDIAN)
|
||||
|
||||
|
||||
void setup_aeskeyX(u8 keyslot, void* keyx);
|
||||
|
@ -36,6 +36,7 @@ static u8 nand_magic_o3ds[0x60] = { // NCSD NAND header O3DS magic
|
||||
|
||||
static u8 CtrNandCtr[16];
|
||||
static u8 TwlNandCtr[16];
|
||||
static u8 OtpSha256[32] = { 0 };
|
||||
|
||||
static u32 emunand_base_sector = 0x000000;
|
||||
|
||||
@ -108,7 +109,21 @@ bool LoadKeyFromFile(const char* folder, u8* keydata, u32 keyslot, char type, ch
|
||||
|
||||
bool InitNandCrypto(void)
|
||||
{
|
||||
// STEP #1: Get NAND CID, set up TWL/CTR counter
|
||||
// part #0: KeyX / KeyY for secret sector 0x96
|
||||
// on a9lh this MUST be run before accessing the SHA register in any other way
|
||||
if ((*(u32*) 0x101401C0) == 0) { // for a9lh
|
||||
// store the current SHA256 from register
|
||||
memcpy(OtpSha256, (void*)REG_SHAHASH, 32);
|
||||
} else {
|
||||
u8 otp[0x100];
|
||||
if ((FileGetData("0:/otp.bin", otp, 0x100, 0) == 0x100) ||
|
||||
(FileGetData("0:/otp0x108.bin", otp, 0x100, 0) == 0x100) ||
|
||||
(FileGetData("0:/Decrypt9/otp.bin", otp, 0x100, 0) == 0x100) ||
|
||||
(FileGetData("0:/Decrypt9/otp0x108.bin", otp, 0x100, 0) == 0x100))
|
||||
sha_quick(OtpSha256, otp, 0x90, SHA256_MODE);
|
||||
}
|
||||
|
||||
// part #1: Get NAND CID, set up TWL/CTR counter
|
||||
u8 NandCid[16];
|
||||
u8 shasum[32];
|
||||
|
||||
@ -206,6 +221,12 @@ bool CheckSlot0x05Crypto(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckSector0x96Crypto(void)
|
||||
{
|
||||
const u8 zeroes[32] = { 0 };
|
||||
return !(memcmp(OtpSha256, zeroes, 32) == 0);
|
||||
}
|
||||
|
||||
void CryptNand(u8* buffer, u32 sector, u32 count, u32 keyslot)
|
||||
{
|
||||
u32 mode = (sector >= (0x0B100000 / 0x200)) ? AES_CNT_CTRNAND_MODE : AES_CNT_TWLNAND_MODE;
|
||||
@ -226,6 +247,20 @@ void CryptNand(u8* buffer, u32 sector, u32 count, u32 keyslot)
|
||||
}
|
||||
}
|
||||
|
||||
void CryptSector0x96(u8* buffer, bool encrypt)
|
||||
{
|
||||
u32 mode = encrypt ? AES_CNT_ECB_ENCRYPT_MODE : AES_CNT_ECB_DECRYPT_MODE;
|
||||
|
||||
// setup the key
|
||||
setup_aeskeyX(0x11, OtpSha256);
|
||||
setup_aeskeyY(0x11, OtpSha256 + 16);
|
||||
|
||||
// decrypt the sector
|
||||
use_aeskey(0x11);
|
||||
for (u32 b = 0x0; b < 0x200; b += 0x10, buffer += 0x10)
|
||||
aes_decrypt((void*) buffer, (void*) buffer, 1, mode);
|
||||
}
|
||||
|
||||
int ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, u32 nand_src)
|
||||
{
|
||||
if (!count) return 0; // <--- just to be safe
|
||||
@ -248,7 +283,8 @@ int ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, u32 nand_src
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
if (keyslot < 0x40) CryptNand(buffer, sector, count, keyslot);
|
||||
if ((keyslot == 0x11) && (sector == 0x96)) CryptSector0x96(buffer, false);
|
||||
else if (keyslot < 0x40) CryptNand(buffer, sector, count, keyslot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -259,7 +295,8 @@ int WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, u32 n
|
||||
for (u32 s = 0; s < count; s += (NAND_BUFFER_SIZE / 0x200)) {
|
||||
u32 pcount = min((NAND_BUFFER_SIZE/0x200), (count - s));
|
||||
memcpy(NAND_BUFFER, buffer + (s*0x200), pcount * 0x200);
|
||||
if (keyslot < 0x40) CryptNand(NAND_BUFFER, sector + s, pcount, keyslot);
|
||||
if ((keyslot == 0x11) && (sector == 0x96)) CryptSector0x96((u8*) buffer, true);
|
||||
else if (keyslot < 0x40) CryptNand(NAND_BUFFER, sector + s, pcount, keyslot);
|
||||
if (nand_dst == NAND_EMUNAND) {
|
||||
int errorcode = 0;
|
||||
if ((sector + s == 0) && (emunand_base_sector % 0x200000 == 0)) { // GW EmuNAND header handling
|
||||
|
@ -12,8 +12,10 @@
|
||||
bool LoadKeyFromFile(const char* folder, u8* keydata, u32 keyslot, char type, char* id);
|
||||
bool InitNandCrypto(void);
|
||||
bool CheckSlot0x05Crypto(void);
|
||||
bool CheckSector0x96Crypto(void);
|
||||
|
||||
void CryptNand(u8* buffer, u32 sector, u32 count, u32 keyslot);
|
||||
void CryptSector0x96(u8* buffer, bool encrypt);
|
||||
int ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, u32 src);
|
||||
int WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, u32 dest);
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#define VFLAG_ON_NO3DS NAND_TYPE_NO3DS
|
||||
#define VFLAG_ON_NAND (VFLAG_ON_O3DS | VFLAG_ON_N3DS | VFLAG_ON_NO3DS)
|
||||
#define VFLAG_ON_MEMORY VRT_MEMORY
|
||||
#define VFLAG_NEEDS_OTP (1<<29)
|
||||
#define VFLAG_N3DS_ONLY (1<<30)
|
||||
#define VFLAG_NAND_SIZE (1<<31)
|
||||
|
||||
@ -24,10 +25,10 @@ VirtualFile virtualFileTemplates[] = {
|
||||
{ "ctrnand_full.bin" , 0x0B930000, 0x2F5D0000, 0x04, VFLAG_ON_O3DS },
|
||||
{ "ctrnand_full.bin" , 0x0B930000, 0x41ED0000, 0x05, VFLAG_ON_N3DS },
|
||||
{ "ctrnand_full.bin" , 0x0B930000, 0x41ED0000, 0x04, VFLAG_ON_NO3DS },
|
||||
{ "sector0x96.bin" , 0x00012C00, 0x00000200, 0x11, VFLAG_ON_NAND | VFLAG_NEEDS_OTP | VFLAG_A9LH_AREA },
|
||||
{ "nand.bin" , 0x00000000, 0x00000000, 0xFF, VFLAG_ON_NAND | VFLAG_NAND_SIZE | VFLAG_A9LH_AREA },
|
||||
{ "nand_minsize.bin" , 0x00000000, 0x3AF00000, 0xFF, VFLAG_ON_O3DS | VFLAG_A9LH_AREA },
|
||||
{ "nand_minsize.bin" , 0x00000000, 0x4D800000, 0xFF, VFLAG_ON_N3DS | VFLAG_ON_NO3DS | VFLAG_A9LH_AREA },
|
||||
{ "sector0x96.bin" , 0x00012C00, 0x00000200, 0xFF, VFLAG_ON_NAND | VFLAG_A9LH_AREA },
|
||||
{ "nand_hdr.bin" , 0x00000000, 0x00000200, 0xFF, VFLAG_ON_NAND | VFLAG_A9LH_AREA },
|
||||
{ "itcm.mem" , 0x01FF8000, 0x00008000, 0xFF, VFLAG_ON_MEMORY },
|
||||
{ "arm9.mem" , 0x08000000, 0x00100000, 0xFF, VFLAG_ON_MEMORY },
|
||||
@ -99,6 +100,8 @@ bool FindVirtualFile(VirtualFile* vfile, const char* path, u32 size)
|
||||
// process special flags
|
||||
if ((vfile->keyslot == 0x05) && !CheckSlot0x05Crypto())
|
||||
return false; // keyslot 0x05 not properly set up
|
||||
if ((vfile->flags & VFLAG_NEEDS_OTP) && !CheckSector0x96Crypto())
|
||||
return false; // sector 0x96 crypto not set up
|
||||
if (!(virtual_src & VRT_SYSNAND) || (*(vu32*) 0x101401C0))
|
||||
vfile->flags &= ~VFLAG_A9LH_AREA; // flag is meaningless outside of A9LH / SysNAND
|
||||
if ((vfile->flags & VFLAG_N3DS_ONLY) && (GetUnitPlatform() != PLATFORM_N3DS))
|
||||
|
Loading…
x
Reference in New Issue
Block a user