1
0
Fork 0
mirror of https://github.com/Scandal-UK/Incognito_RCM.git synced 2024-11-22 20:06:42 +00:00

decrypting and reading ready, encrypting and writing todo

This commit is contained in:
jimzrt 2019-09-25 00:49:22 +02:00
parent 4ce94bc2b1
commit 76bfd54fd2
4 changed files with 250 additions and 63 deletions

View file

@ -23,7 +23,7 @@
#include "../hos/pkg1.h" #include "../hos/pkg1.h"
#include "../hos/pkg2.h" #include "../hos/pkg2.h"
#include "../hos/sept.h" #include "../hos/sept.h"
//#include "../libs/fatfs/ff.h" #include "../libs/fatfs/ff.h"
#include "../mem/heap.h" #include "../mem/heap.h"
#include "../mem/mc.h" #include "../mem/mc.h"
#include "../mem/sdram.h" #include "../mem/sdram.h"
@ -158,6 +158,7 @@ void dump_keys() {
MAX_KEY = pkg1_id->kb + 1; MAX_KEY = pkg1_id->kb + 1;
} }
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700) { if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700) {
// sd_mount(); // sd_mount();
// if (!f_stat("sd:/sept/payload.bak", NULL)) { // if (!f_stat("sd:/sept/payload.bak", NULL)) {
@ -374,12 +375,22 @@ void dump_keys() {
se_aes_key_set(8, bis_key[0] + 0x00, 0x10); se_aes_key_set(8, bis_key[0] + 0x00, 0x10);
se_aes_key_set(9, bis_key[0] + 0x10, 0x10); se_aes_key_set(9, bis_key[0] + 0x10, 0x10);
u32 length = 0x18; //u32 length = 0x18;
u8* buffer = (u8 *)malloc(length); u8 buffer[0x18];// = (u8 *)malloc(length);
readData(buffer, 0x250, length); readData(buffer, 0x250, sizeof(buffer));
gfx_hexdump(0, buffer, length);
free(buffer); // const char junkSerial[] = "XAJ40030770863";
// gfx_hexdump(0, (u8 *)junkSerial, strlen(junkSerial));
// writeData((u8 *)junkSerial, 0x250, strlen(junkSerial));
gfx_hexdump(0, buffer, sizeof(buffer));
//free(buffer);
verify();
writeClientCertHash();
writeCal0Hash();
verify(); verify();
// free(tmp_copy); // free(tmp_copy);
@ -387,6 +398,7 @@ void dump_keys() {
// pkg2_done: // pkg2_done:
// // free(pkg2); // // free(pkg2);
@ -605,7 +617,7 @@ bool readData(u8 *buffer, u32 offset, u32 length)
u32 sector = (offset / NX_EMMC_BLOCKSIZE); u32 sector = (offset / NX_EMMC_BLOCKSIZE);
u32 newOffset = (offset % NX_EMMC_BLOCKSIZE); u32 newOffset = (offset % NX_EMMC_BLOCKSIZE);
u8 sectorCount = ((newOffset + length) / NX_EMMC_BLOCKSIZE) + 1; u8 sectorCount = ((newOffset + length - 1) / (NX_EMMC_BLOCKSIZE)) + 1;
// if(length + newOffset > NX_EMMC_BLOCKSIZE * 2){ // if(length + newOffset > NX_EMMC_BLOCKSIZE * 2){
// EPRINTF("TOO BIG!!"); // EPRINTF("TOO BIG!!");
@ -614,7 +626,7 @@ bool readData(u8 *buffer, u32 offset, u32 length)
//bool needMultipleSectors = newOffset + length > NX_EMMC_BLOCKSIZE; //bool needMultipleSectors = newOffset + length > NX_EMMC_BLOCKSIZE;
u8 *tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE); u8 *tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE);
disk_read_mod(tmp, sector, sectorCount, &storage, prodinfo_part); disk_read_prod(tmp, sector, sectorCount);
// if (!needMultipleSectors) // if (!needMultipleSectors)
// { // {
@ -634,9 +646,46 @@ bool readData(u8 *buffer, u32 offset, u32 length)
return true; return true;
} }
bool verifyHash(u32 hashOffset, u32 offset, u32 sz) bool writeData(u8 *buffer, u32 offset, u32 length)
{ {
bool result = false;
u32 sector = (offset / NX_EMMC_BLOCKSIZE);
u32 newOffset = (offset % NX_EMMC_BLOCKSIZE);
u8 sectorCount = ((newOffset + length - 1) / (NX_EMMC_BLOCKSIZE)) + 1;
// if(length + newOffset > NX_EMMC_BLOCKSIZE * 2){
// EPRINTF("TOO BIG!!");
// }
//bool needMultipleSectors = newOffset + length > NX_EMMC_BLOCKSIZE;
u8 *tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE);
disk_read_prod(tmp, sector, sectorCount);
// if (!needMultipleSectors)
// {
// gfx_hexdump(0, tmp + newOffset, length);
memcpy(tmp + newOffset, buffer, length);
disk_write_prod(tmp, sector, sectorCount);
// }
// else
// {
// u32 newLength = (newOffset + length) - NX_EMMC_BLOCKSIZE;
// memcpy(buffer, tmp + newOffset, newLength);
// disk_read_mod(tmp, sector + 1, 1, &storage, prodinfo_part);
// memcpy(buffer + newLength, tmp, length - newLength);
// }
free(tmp);
return true;
}
bool writeHash(u32 hashOffset, u32 offset, u32 sz)
{
u8 *buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE); u8 *buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
SHA256_CTX ctx; SHA256_CTX ctx;
@ -646,19 +695,60 @@ bool verifyHash(u32 hashOffset, u32 offset, u32 sz)
{ {
readData(buffer, offset, NX_EMMC_BLOCKSIZE); readData(buffer, offset, NX_EMMC_BLOCKSIZE);
// gfx_hexdump(0, buffer + NX_EMMC_BLOCKSIZE - 8, 8);
sha256_update(&ctx, buffer, NX_EMMC_BLOCKSIZE); sha256_update(&ctx, buffer, NX_EMMC_BLOCKSIZE);
sz -= NX_EMMC_BLOCKSIZE; sz -= NX_EMMC_BLOCKSIZE;
offset += NX_EMMC_BLOCKSIZE; offset += NX_EMMC_BLOCKSIZE;
} }
readData(buffer, offset, sz); if(sz > 0){
readData(buffer, offset, sz);
sha256_update(&ctx, buffer, sz); sha256_update(&ctx, buffer, sz);
u8 *hash1 = (u8 *)malloc(0x20); }
u8 hash[0x20];
sha256_final(&ctx, hash);
writeData(hash, hashOffset, 0x20);
free(buffer);
return true;
}
bool verifyHash(u32 hashOffset, u32 offset, u32 sz)
{
bool result = false;
u8 *buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
SHA256_CTX ctx;
sha256_init(&ctx);
while (sz > 64)
{
readData(buffer, offset, 64);
// gfx_hexdump(0, buffer + NX_EMMC_BLOCKSIZE - 8, 8);
sha256_update(&ctx, buffer, 64);
sz -= 64;
offset += 64;
}
if(sz > 0){
readData(buffer, offset, sz);
sha256_update(&ctx, buffer, sz);
}
u8 hash1[0x20];
sha256_final(&ctx, hash1); sha256_final(&ctx, hash1);
u8 *hash2 = (u8 *)malloc(0x20); u8 hash2[0x20];
//se_calc_sha256(hash1, buffer, sz); //se_calc_sha256(hash1, buffer, sz);
//sha256CalculateHash(hash1, buffer, sz); //sha256CalculateHash(hash1, buffer, sz);
@ -667,22 +757,16 @@ bool verifyHash(u32 hashOffset, u32 offset, u32 sz)
if (memcmp(hash1, hash2, 0x20)) if (memcmp(hash1, hash2, 0x20))
{ {
EPRINTF("error: hash verification failed\n"); EPRINTF("error: hash verification failed\n");
//printf("error: hash verification failed for %x %d\n", (long)offset, (long)sz);
//print(hash1, 0x20);
//print(hash2, 0x20);
} }
else else
{ {
result = true; result = true;
} }
gfx_hexdump(0, hash1, 0x08); gfx_hexdump(0, hash1, 0x20);
gfx_hexdump(0, hash2, 0x08); gfx_hexdump(0, hash2, 0x20);
free(buffer); free(buffer);
free(hash1);
free(hash2);
return result; return result;
} }
@ -690,10 +774,8 @@ u32 certSize()
{ {
u32 buffer; u32 buffer;
readData((u8 *)&buffer, 0x0AD0, sizeof(buffer)); readData((u8 *)&buffer, 0x0AD0, sizeof(buffer));
EPRINTF("certSize"); // EPRINTF("certSize");
gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer)); // gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer));
buffer = _read_le_u32(&buffer, 0);
gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer));
return buffer; return buffer;
} }
@ -701,17 +783,102 @@ u32 calibrationDataSize()
{ {
u32 buffer; u32 buffer;
readData((u8 *)&buffer, 0x08, sizeof(buffer)); readData((u8 *)&buffer, 0x08, sizeof(buffer));
EPRINTF("calSize"); // EPRINTF("calSize");
gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer)); // gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer));
buffer = _read_le_u32(&buffer, 0);
gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer));
return buffer; return buffer;
} }
bool writeCal0Hash()
{
return writeHash(0x20, 0x40, calibrationDataSize());
}
bool writeClientCertHash()
{
return writeHash(0x12E0, 0xAE0, certSize());
}
bool verifyCal0Hash(){
return verifyHash(0x20, 0x40, calibrationDataSize());
}
bool verifyClientCertHash()
{
return verifyHash(0x12E0, 0xAE0, certSize());
}
bool verify() bool verify()
{ {
bool r = verifyHash(0x12E0, 0x0AE0, certSize()); // client cert hash return verifyClientCertHash() & verifyCal0Hash();
r &= verifyHash(0x20, 0x0040, calibrationDataSize()); // calibration hash // bool r = verifyHash(0x12E0, 0xAE0, certSize()); // client cert hash
// r &= verifyHash(0x20, 0x40, calibrationDataSize()); // calibration hash
return r; // return r;
} }
void backup(){
sd_mount();
if (f_stat("sd:/prodinfo.bin", NULL)){
f_unlink("sd:/prodinfo.bin");
}
FIL fp;
f_open(&fp, "sd:/prodinfo.bin", FA_CREATE_NEW | FA_WRITE);
u8 bufferNX[NX_EMMC_BLOCKSIZE];
u32 size = 0x3FBC00;
u32 offset = 0;
while(size > NX_EMMC_BLOCKSIZE){
readData(bufferNX, offset, NX_EMMC_BLOCKSIZE);
f_write(&fp, bufferNX, NX_EMMC_BLOCKSIZE, NULL);
offset += NX_EMMC_BLOCKSIZE;
size -= NX_EMMC_BLOCKSIZE;
}
if(size > 0){
readData(bufferNX, offset, size);
f_write(&fp, bufferNX, size, NULL);
}
f_close(&fp);
gfx_printf("\n%kBackup unecrypted done!", 4);
if (f_stat("sd:/prodinfoENC.bin", NULL)){
f_unlink("sd:/prodinfoENC.bin");
}
f_open(&fp, "sd:/prodinfoENC.bin", FA_CREATE_NEW | FA_WRITE);
size = 0x3FBC00;
offset = 0;
while(size > NX_EMMC_BLOCKSIZE){
nx_emmc_part_read(&storage, prodinfo_part, offset, 1, bufferNX);
f_write(&fp, bufferNX, NX_EMMC_BLOCKSIZE, NULL);
offset ++;
size -= NX_EMMC_BLOCKSIZE;
}
if(size > 0){
nx_emmc_part_read(&storage, prodinfo_part, offset, 1, bufferNX);
f_write(&fp, bufferNX, size, NULL);
}
f_close(&fp);
gfx_printf("\n%kBackup encrypted done!", 4);
}
// bool erase(u32 offset, u32 sz)
// {
// u8 zero = 0;
// for (u64 i = 0; i < sz; i++)
// {
// fsStorageWrite(&m_sh, offset + i, &zero, 1);
// }
// return true;
// }

View file

@ -21,6 +21,9 @@
void dump_keys(); void dump_keys();
bool readData(u8 *buffer, u32 offset, u32 length); bool readData(u8 *buffer, u32 offset, u32 length);
bool writeData(u8 *buffer, u32 offset, u32 length);
bool writeClientCertHash();
bool writeCal0Hash();
bool verify(); bool verify();
#endif #endif

View file

@ -35,6 +35,7 @@
extern sdmmc_storage_t sd_storage; extern sdmmc_storage_t sd_storage;
extern sdmmc_storage_t storage; extern sdmmc_storage_t storage;
extern emmc_part_t *system_part; extern emmc_part_t *system_part;
extern emmc_part_t *prodinfo_part;
typedef struct { typedef struct {
u32 sector; u32 sector;
@ -127,13 +128,12 @@ out:;
DRESULT disk_read_mod ( DRESULT disk_read_prod (
BYTE *buff, /* Data buffer to store read data */ BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Start sector in LBA */ DWORD sector, /* Start sector in LBA */
UINT count, /* Number of sectors to read */ UINT count /* Number of sectors to read */
sdmmc_storage_t *storage, )
emmc_part_t *partition)
{ {
@ -141,30 +141,11 @@ DRESULT disk_read_mod (
__attribute__ ((aligned (16))) static u64 prev_cluster = -1; __attribute__ ((aligned (16))) static u64 prev_cluster = -1;
__attribute__ ((aligned (16))) static u32 prev_sector = 0; __attribute__ ((aligned (16))) static u32 prev_sector = 0;
u32 tweak_exp = 0; u32 tweak_exp = 0;
bool regen_tweak = true, cache_sector = false; bool regen_tweak = true;
u32 s = 0;
if (count == 1) {
for ( ; s < secindex; s++) {
if (sector_cache[s].sector == sector) {
sector_cache[s].visit_count++;
memcpy(buff, sector_cache[s].cached_sector, 0x200);
memcpy(tweak, sector_cache[s].tweak, 0x10);
prev_sector = sector;
prev_cluster = sector / 0x20;
return RES_OK;
}
}
// add to cache
if (s == secindex && s < MAX_SEC_CACHE_ENTRIES) {
sector_cache[s].sector = sector;
sector_cache[s].visit_count++;
cache_sector = true;
secindex++;
}
}
if (nx_emmc_part_read(storage, partition, sector, count, buff)) { if (nx_emmc_part_read(&storage, prodinfo_part, sector, count, buff)) {
if (prev_cluster != sector / 0x20) { // sector in different cluster than last read if (prev_cluster != sector / 0x20) { // sector in different cluster than last read
prev_cluster = sector / 0x20; prev_cluster = sector / 0x20;
tweak_exp = sector % 0x20; tweak_exp = sector % 0x20;
@ -177,10 +158,7 @@ DRESULT disk_read_mod (
// fatfs will never pull more than a cluster // fatfs will never pull more than a cluster
_emmc_xts(9, 8, 0, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count * 0x200); _emmc_xts(9, 8, 0, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count * 0x200);
if (cache_sector) {
memcpy(sector_cache[s].cached_sector, buff, 0x200);
memcpy(sector_cache[s].tweak, tweak, 0x10);
}
prev_sector = sector + count - 1; prev_sector = sector + count - 1;
return RES_OK; return RES_OK;
} }
@ -188,6 +166,44 @@ DRESULT disk_read_mod (
return RES_ERROR; return RES_ERROR;
} }
DRESULT disk_write_prod (
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
__attribute__ ((aligned (16))) static u8 tweak[0x10];
__attribute__ ((aligned (16))) static u64 prev_cluster = -1;
__attribute__ ((aligned (16))) static u32 prev_sector = 0;
u32 tweak_exp = 0;
bool regen_tweak = true;
if (prev_cluster != sector / 0x20) { // sector in different cluster than last read
prev_cluster = sector / 0x20;
tweak_exp = sector % 0x20;
} else if (sector > prev_sector) { // sector in same cluster and past last sector
tweak_exp = sector - prev_sector - 1;
regen_tweak = false;
} else { // sector in same cluster and before or same as last sector
tweak_exp = sector % 0x20;
}
// fatfs will never pull more than a cluster
_emmc_xts(9, 8, 1, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count * 0x200);
nx_emmc_part_write(&storage, prodinfo_part, sector, count, buff);
prev_sector = sector + count - 1;
return RES_OK;
// return RES_ERROR;
}
DRESULT disk_read ( DRESULT disk_read (
BYTE pdrv, /* Physical drive number to identify the drive */ BYTE pdrv, /* Physical drive number to identify the drive */

View file

@ -33,7 +33,8 @@ typedef enum {
DSTATUS disk_initialize (BYTE pdrv); DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv); DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_read_mod (BYTE *buff, DWORD sector, UINT count, sdmmc_storage_t *storage, emmc_part_t *partition); DRESULT disk_read_prod (BYTE *buff, DWORD sector, UINT count);
DRESULT disk_write_prod (BYTE *buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);