Use alternate method of getting NAND CTR (via NAND CID)

This commit is contained in:
d0k3 2016-03-02 20:01:13 +01:00
parent 21a51e8138
commit 75dff45fcb
3 changed files with 90 additions and 1 deletions

View File

@ -9,6 +9,7 @@
#include "diskio.h" /* FatFs lower layer API */
#include "aes.h"
#include "sha.h"
#include "platform.h"
#include "sdmmc.h"
@ -65,7 +66,7 @@ static u32 emunand_base_sector = 0x000000;
/* Get counter for NAND AES decryption */
/*-----------------------------------------------------------------------*/
u32 GetNandCtr(u8* ctr, u32 sector)
/*u32 GetNandCtr(u8* ctr, u32 sector)
{
static const u8* version_ctrs[] = {
(u8*)0x080D7CAC,
@ -112,6 +113,35 @@ u32 GetNandCtr(u8* ctr, u32 sector)
// increment counter
add_ctr(ctr, sector * (0x200/0x10));
return 0;
}*/
u32 GetNandCtr(u8* ctr, u32 sector)
{
static u8* NandCid = NULL;
static u8 CtrNandCtr[16];
static u8 TwlNandCtr[16];
if (!NandCid) {
NandCid = (u8*) 0x01FFCD84;
u8 shasum[32];
sha_init(SHA256_MODE);
sha_update(NandCid, 16);
sha_get(shasum);
memcpy(CtrNandCtr, shasum, 16);
sha_init(SHA1_MODE);
sha_update(NandCid, 16);
sha_get(shasum);
for(u32 i = 0; i < 16; i++) // little endian and reversed order
TwlNandCtr[i] = shasum[15-i];
}
// copy NAND CTR over
memcpy(ctr, (sector >= (0x0B100000 / 0x200)) ? CtrNandCtr : TwlNandCtr, 16);
// increment counter
add_ctr(ctr, sector * (0x200/0x10));
return 0;
}

32
source/fatfs/sha.c Normal file
View File

@ -0,0 +1,32 @@
#include "sha.h"
void sha_init(u32 mode)
{
while(*REG_SHACNT & 1);
*REG_SHACNT = mode | SHA_CNT_OUTPUT_ENDIAN | SHA_NORMAL_ROUND;
}
void sha_update(const void* src, u32 size)
{
const u32* src32 = (const u32*)src;
while(size >= 0x40) {
while(*REG_SHACNT & 1);
for(u32 i = 0; i < 4; i++) {
*REG_SHAINFIFO = *src32++;
*REG_SHAINFIFO = *src32++;
*REG_SHAINFIFO = *src32++;
*REG_SHAINFIFO = *src32++;
}
size -= 0x40;
}
while(*REG_SHACNT & 1);
memcpy((void*)REG_SHAINFIFO, src32, size);
}
void sha_get(void* res) {
*REG_SHACNT = (*REG_SHACNT & ~SHA_NORMAL_ROUND) | SHA_FINAL_ROUND;
while(*REG_SHACNT & SHA_FINAL_ROUND);
while(*REG_SHACNT & 1);
memcpy(res, (void*)REG_SHAHASH, (256 / 8));
}

27
source/fatfs/sha.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
#include "common.h"
#define REG_SHACNT ((volatile uint32_t*)0x1000A000)
#define REG_SHABLKCNT ((volatile uint32_t*)0x1000A004)
#define REG_SHAHASH ((volatile uint32_t*)0x1000A040)
#define REG_SHAINFIFO ((volatile uint32_t*)0x1000A080)
#define SHA_CNT_STATE 0x00000003
#define SHA_CNT_OUTPUT_ENDIAN 0x00000008
#define SHA_CNT_MODE 0x00000030
#define SHA_CNT_ENABLE 0x00010000
#define SHA_CNT_ACTIVE 0x00020000
#define SHA_HASH_READY 0x00000000
#define SHA_NORMAL_ROUND 0x00000001
#define SHA_FINAL_ROUND 0x00000002
#define SHA256_MODE 0
#define SHA224_MODE 0x00000010
#define SHA1_MODE 0x00000020
void sha_init(u32 mode);
void sha_update(const void* src, u32 size);
void sha_get(void* res);