From 76bfd54fd298b71c8656557ecc901ca388a62584 Mon Sep 17 00:00:00 2001 From: jimzrt Date: Wed, 25 Sep 2019 00:49:22 +0200 Subject: [PATCH] decrypting and reading ready, encrypting and writing todo --- source/keys/keys.c | 231 ++++++++++++++++++++++++++++++++----- source/keys/keys.h | 3 + source/libs/fatfs/diskio.c | 76 +++++++----- source/libs/fatfs/diskio.h | 3 +- 4 files changed, 250 insertions(+), 63 deletions(-) diff --git a/source/keys/keys.c b/source/keys/keys.c index c2d0711..594481e 100644 --- a/source/keys/keys.c +++ b/source/keys/keys.c @@ -23,7 +23,7 @@ #include "../hos/pkg1.h" #include "../hos/pkg2.h" #include "../hos/sept.h" -//#include "../libs/fatfs/ff.h" +#include "../libs/fatfs/ff.h" #include "../mem/heap.h" #include "../mem/mc.h" #include "../mem/sdram.h" @@ -158,6 +158,7 @@ void dump_keys() { MAX_KEY = pkg1_id->kb + 1; } + if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700) { // sd_mount(); // 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(9, bis_key[0] + 0x10, 0x10); - u32 length = 0x18; - u8* buffer = (u8 *)malloc(length); - readData(buffer, 0x250, length); + //u32 length = 0x18; + u8 buffer[0x18];// = (u8 *)malloc(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(); // free(tmp_copy); @@ -387,6 +398,7 @@ void dump_keys() { + // pkg2_done: // // free(pkg2); @@ -605,7 +617,7 @@ bool readData(u8 *buffer, u32 offset, u32 length) u32 sector = (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){ // EPRINTF("TOO BIG!!"); @@ -614,7 +626,7 @@ bool readData(u8 *buffer, u32 offset, u32 length) //bool needMultipleSectors = newOffset + length > 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) // { @@ -634,9 +646,46 @@ bool readData(u8 *buffer, u32 offset, u32 length) 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); SHA256_CTX ctx; @@ -646,19 +695,60 @@ bool verifyHash(u32 hashOffset, u32 offset, u32 sz) { readData(buffer, offset, NX_EMMC_BLOCKSIZE); + // gfx_hexdump(0, buffer + NX_EMMC_BLOCKSIZE - 8, 8); sha256_update(&ctx, buffer, NX_EMMC_BLOCKSIZE); sz -= NX_EMMC_BLOCKSIZE; offset += NX_EMMC_BLOCKSIZE; } - readData(buffer, offset, sz); + if(sz > 0){ + + readData(buffer, offset, 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); - u8 *hash2 = (u8 *)malloc(0x20); + u8 hash2[0x20]; //se_calc_sha256(hash1, buffer, sz); //sha256CalculateHash(hash1, buffer, sz); @@ -667,22 +757,16 @@ bool verifyHash(u32 hashOffset, u32 offset, u32 sz) if (memcmp(hash1, hash2, 0x20)) { 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 { result = true; } - gfx_hexdump(0, hash1, 0x08); - gfx_hexdump(0, hash2, 0x08); + gfx_hexdump(0, hash1, 0x20); + gfx_hexdump(0, hash2, 0x20); free(buffer); - free(hash1); - free(hash2); return result; } @@ -690,10 +774,8 @@ u32 certSize() { u32 buffer; readData((u8 *)&buffer, 0x0AD0, sizeof(buffer)); - EPRINTF("certSize"); - gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer)); - buffer = _read_le_u32(&buffer, 0); - gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer)); + // EPRINTF("certSize"); + // gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer)); return buffer; } @@ -701,17 +783,102 @@ u32 calibrationDataSize() { u32 buffer; readData((u8 *)&buffer, 0x08, sizeof(buffer)); - EPRINTF("calSize"); - gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer)); - buffer = _read_le_u32(&buffer, 0); - gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer)); + // EPRINTF("calSize"); + // gfx_hexdump(0, (u8 *)&buffer, sizeof(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 r = verifyHash(0x12E0, 0x0AE0, certSize()); // client cert hash - r &= verifyHash(0x20, 0x0040, calibrationDataSize()); // calibration hash + return verifyClientCertHash() & verifyCal0Hash(); + // 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; +// } diff --git a/source/keys/keys.h b/source/keys/keys.h index 9d4eaa2..e3f9f33 100644 --- a/source/keys/keys.h +++ b/source/keys/keys.h @@ -21,6 +21,9 @@ void dump_keys(); bool readData(u8 *buffer, u32 offset, u32 length); +bool writeData(u8 *buffer, u32 offset, u32 length); +bool writeClientCertHash(); +bool writeCal0Hash(); bool verify(); #endif diff --git a/source/libs/fatfs/diskio.c b/source/libs/fatfs/diskio.c index 000a5fe..b9952d6 100644 --- a/source/libs/fatfs/diskio.c +++ b/source/libs/fatfs/diskio.c @@ -35,6 +35,7 @@ extern sdmmc_storage_t sd_storage; extern sdmmc_storage_t storage; extern emmc_part_t *system_part; +extern emmc_part_t *prodinfo_part; typedef struct { u32 sector; @@ -127,13 +128,12 @@ out:; -DRESULT disk_read_mod ( +DRESULT disk_read_prod ( BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Start sector in LBA */ - UINT count, /* Number of sectors to read */ - sdmmc_storage_t *storage, - emmc_part_t *partition) + UINT count /* Number of sectors to read */ + ) { @@ -141,30 +141,11 @@ DRESULT disk_read_mod ( __attribute__ ((aligned (16))) static u64 prev_cluster = -1; __attribute__ ((aligned (16))) static u32 prev_sector = 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 prev_cluster = sector / 0x20; tweak_exp = sector % 0x20; @@ -177,10 +158,7 @@ DRESULT disk_read_mod ( // fatfs will never pull more than a cluster _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; return RES_OK; } @@ -188,6 +166,44 @@ DRESULT disk_read_mod ( 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 ( BYTE pdrv, /* Physical drive number to identify the drive */ diff --git a/source/libs/fatfs/diskio.h b/source/libs/fatfs/diskio.h index 714eb8b..7791f45 100644 --- a/source/libs/fatfs/diskio.h +++ b/source/libs/fatfs/diskio.h @@ -33,7 +33,8 @@ typedef enum { DSTATUS disk_initialize (BYTE pdrv); DSTATUS disk_status (BYTE pdrv); 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_ioctl (BYTE pdrv, BYTE cmd, void* buff);