From 75dff45fcb62b2ff047f5a4cc22bb602c766c95b Mon Sep 17 00:00:00 2001 From: d0k3 Date: Wed, 2 Mar 2016 20:01:13 +0100 Subject: [PATCH] Use alternate method of getting NAND CTR (via NAND CID) --- source/fatfs/diskio.c | 32 +++++++++++++++++++++++++++++++- source/fatfs/sha.c | 32 ++++++++++++++++++++++++++++++++ source/fatfs/sha.h | 27 +++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 source/fatfs/sha.c create mode 100644 source/fatfs/sha.h diff --git a/source/fatfs/diskio.c b/source/fatfs/diskio.c index 166b172..666925f 100644 --- a/source/fatfs/diskio.c +++ b/source/fatfs/diskio.c @@ -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; } diff --git a/source/fatfs/sha.c b/source/fatfs/sha.c new file mode 100644 index 0000000..0902ddc --- /dev/null +++ b/source/fatfs/sha.c @@ -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)); +} diff --git a/source/fatfs/sha.h b/source/fatfs/sha.h new file mode 100644 index 0000000..cb88d42 --- /dev/null +++ b/source/fatfs/sha.h @@ -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);