From 02ab328e1cd78a298c6d9304e917cacb53cc4d64 Mon Sep 17 00:00:00 2001 From: Dan Ware Date: Sat, 6 Jun 2020 09:04:24 +0100 Subject: [PATCH 1/6] Corrected memory address offsets and bumped version --- Makefile | 2 +- source/incognito/incognito.c | 36 ++++++++++++++++++------------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index a536a5a..a91cf71 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ include $(DEVKITARM)/base_rules IPL_LOAD_ADDR := 0x40003000 LPVERSION_MAJOR := 0 LPVERSION_MINOR := 6 -LPVERSION_BUGFX := 4 +LPVERSION_BUGFX := 5 ################################################################################ diff --git a/source/incognito/incognito.c b/source/incognito/incognito.c index 20863bc..3f7b6ef 100644 --- a/source/incognito/incognito.c +++ b/source/incognito/incognito.c @@ -402,36 +402,36 @@ bool incognito() return false; } - gfx_printf("%kWriting junk serial...\n", COLOR_YELLOW); + gfx_printf("%kWriting fake serial...\n", COLOR_YELLOW); if (!writeSerial()) return false; - - gfx_printf("%kErasing client cert...\n", COLOR_YELLOW); - if (!erase(0x0AE0, 0x800)) // client cert +/* // NOTE: This is crashing Atmosphere... + gfx_printf("%kErasing ECC-B233 device cert...\n", COLOR_YELLOW); + if (!erase(0x0480, 0x180)) // (size 0x190 to include crc) + return false; +*/ + gfx_printf("%kErasing SSL cert...\n", COLOR_YELLOW); + if (!erase(0x0AE0, 0x800)) return false; - gfx_printf("%kErasing private key...\n", COLOR_YELLOW); - if (!erase(0x3AE0, 0x130)) // private key + gfx_printf("%kErasing extended SSL key...\n", COLOR_YELLOW); + if (!erase(0x3AE0, 0x130)) return false; - gfx_printf("%kErasing deviceId 1/2...\n", COLOR_YELLOW); - if (!erase(0x35E1, 0x006)) // deviceId + gfx_printf("%kErasing Amiibo ECDSA cert...\n", COLOR_YELLOW); + if (!erase(0x35A0, 0x070)) return false; - gfx_printf("%kErasing deviceId 2/2...\n", COLOR_YELLOW); - if (!erase(0x36E1, 0x006)) // deviceId + gfx_printf("%kErasing Amiibo ECQV-BLS root cert...\n", COLOR_YELLOW); + if (!erase(0x36A0, 0x090)) return false; - gfx_printf("%kErasing device cert 1/2...\n", COLOR_YELLOW); - if (!erase(0x02B0, 0x180)) // device cert + gfx_printf("%kErasing RSA-2048 extended device key...\n", COLOR_YELLOW); + if (!erase(0x3D70, 0x240)) return false; - gfx_printf("%kErasing device cert 2/2...\n", COLOR_YELLOW); - if (!erase(0x3D70, 0x240)) // device cert - return false; - - gfx_printf("%kErasing device key...\n", COLOR_YELLOW); - if (!erase(0x3FC0, 0x240)) // device key + gfx_printf("%kErasing RSA-2048 device certificate...\n", COLOR_YELLOW); + if (!erase(0x3FC0, 0x240)) return false; gfx_printf("%kWriting client cert hash...\n", COLOR_YELLOW); From 9d0149ad28d7b0617de8dbca6d732b20ea55b196 Mon Sep 17 00:00:00 2001 From: Dan Ware Date: Sat, 6 Jun 2020 10:23:43 +0100 Subject: [PATCH 2/6] Extracted crc writing into its own method --- source/incognito/incognito.c | 27 +++++++++++++++++---------- source/incognito/io/io.c | 17 ++++++++--------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/source/incognito/incognito.c b/source/incognito/incognito.c index 3f7b6ef..5990d6f 100644 --- a/source/incognito/incognito.c +++ b/source/incognito/incognito.c @@ -376,22 +376,29 @@ bool writeSerial() } const u32 serialOffset = 0x250; - const u32 serialBlockSize = 0x1E; - if (!writeData((u8 *)junkSerial, serialOffset, 14, NULL)) return false; // write crc at end of serial-number block - char serial[31] = ""; - readData((u8 *)serial, serialOffset, serialBlockSize, NULL); - - const char *serialBytes = serial; - u16 crcValue = get_crc_16(serialBytes, serialBlockSize); - u8 crc[2] = { crcValue & 0xff, crcValue >> 8 }; // bytes of u16 - - return writeData(crc, serialOffset + serialBlockSize, 2, NULL); + return writeCrc(serialOffset, 0x1E); } +bool writeCrc(u32 offset, u32 size) +{ + char buffer[size + 1]; + if (!readData((u8 *)buffer, offset, size, NULL)) + return false; + + const char *bytes = buffer; + free(buffer); + u16 crcValue = get_crc_16(bytes, size); + u8 crc[2] = { crcValue & 0xff, crcValue >> 8 }; // bytes of u16 + + return writeData(crc, offset + size, 2, NULL); +} + +// todo: write a method to add a crc! +// todo: include crc block in sizes bool incognito() { gfx_printf("%kChecking if backup exists...\n", COLOR_YELLOW); diff --git a/source/incognito/io/io.c b/source/incognito/io/io.c index 0d7cf3d..818a731 100644 --- a/source/incognito/io/io.c +++ b/source/incognito/io/io.c @@ -77,6 +77,14 @@ out:; return res; } +// replacement for nx_emmc_part_write in storage/nx_emmc, which uses sdmmc_storage_write +int nx_emummc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf) +{ + // The last LBA is inclusive. + if (part->lba_start + sector_off > part->lba_end) + return 0; + return emummc_storage_write(storage, part->lba_start + sector_off, num_sectors, buf); +} bool prodinfo_read( u8 *buff, /* Data buffer to store read data */ @@ -157,12 +165,3 @@ bool prodinfo_write( return false; } - -// replacement for nx_emmc_part_write in storage/nx_emmc, which uses sdmmc_storage_write -int nx_emummc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf) -{ - // The last LBA is inclusive. - if (part->lba_start + sector_off > part->lba_end) - return 0; - return emummc_storage_write(storage, part->lba_start + sector_off, num_sectors, buf); -} From 9506b6cf9a310d473cd9f04067eecbc27f41858d Mon Sep 17 00:00:00 2001 From: Dan Ware Date: Sat, 6 Jun 2020 14:46:20 +0100 Subject: [PATCH 3/6] Refactored checksum code into methods --- source/incognito/incognito.c | 81 ++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/source/incognito/incognito.c b/source/incognito/incognito.c index 5990d6f..57128ef 100644 --- a/source/incognito/incognito.c +++ b/source/incognito/incognito.c @@ -119,6 +119,32 @@ unsigned short int get_crc_16 (const char *p, int n) { return(crc); } +u16 calculateCrc(u32 offset, u32 size) +{ + const char buffer[size + 1]; + readData((u8 *)buffer, offset, size, NULL); + return get_crc_16(buffer, size); +} + +u16 readCrc(u32 offset) +{ + u16 buffer; + readData((u8 *)&buffer, offset, sizeof(u16), NULL); + return buffer; +} + +bool validateCrc(u32 offset, u32 size) +{ + return calculateCrc(offset, size) == readCrc(offset + size); +} + +bool calculateAndWriteCrc(u32 offset, u32 size) +{ + u16 crcValue = calculateCrc(offset, size); + u8 crc[2] = { crcValue & 0xff, crcValue >> 8 }; // bytes of u16 + return writeData(crc, offset + size, sizeof(u16), NULL); +} + bool dump_keys() { display_backlight_brightness(100, 1000); @@ -330,27 +356,17 @@ bool dump_keys() return false; } - char serial[31] = ""; - readData((u8 *)serial, 0x250, 30, NULL); + u32 serialOffset = 0x250; + + char serial[15]; + readData((u8 *)serial, serialOffset, 14, NULL); gfx_printf("%kCurrent serial: [%s]\n\n", COLOR_BLUE, serial); - // Determine stored crc - u8 *storedCrc = (u8 *)calloc(2, sizeof(u8)); - readData((u8 *)storedCrc, 0x250 + 30, 2, NULL); - - // Calculate crc - const char *serialBytes = serial; - u16 crcValue = get_crc_16(serialBytes, 30); - u8 crc[2] = { crcValue & 0xff, crcValue >> 8 }; // bytes of u16 - - // Validate crc - if (memcmp(storedCrc, crc, 0x2) == 0) - gfx_printf("%kValid serial crc\n", COLOR_GREEN); + if (validateCrc(serialOffset, 0x1E)) + gfx_printf("%kValid serial checksum\n", COLOR_GREEN); else - gfx_printf("%kWarning - invalid serial crc\n", COLOR_RED); - - free(storedCrc); + gfx_printf("%kWarning - invalid serial checksum\n", COLOR_RED); return true; } @@ -380,24 +396,9 @@ bool writeSerial() return false; // write crc at end of serial-number block - return writeCrc(serialOffset, 0x1E); + return calculateAndWriteCrc(serialOffset, 0x1E); } -bool writeCrc(u32 offset, u32 size) -{ - char buffer[size + 1]; - if (!readData((u8 *)buffer, offset, size, NULL)) - return false; - - const char *bytes = buffer; - free(buffer); - u16 crcValue = get_crc_16(bytes, size); - u8 crc[2] = { crcValue & 0xff, crcValue >> 8 }; // bytes of u16 - - return writeData(crc, offset + size, 2, NULL); -} - -// todo: write a method to add a crc! // todo: include crc block in sizes bool incognito() { @@ -412,11 +413,14 @@ bool incognito() gfx_printf("%kWriting fake serial...\n", COLOR_YELLOW); if (!writeSerial()) return false; -/* // NOTE: This is crashing Atmosphere... +/* gfx_printf("%kErasing ECC-B233 device cert...\n", COLOR_YELLOW); if (!erase(0x0480, 0x180)) // (size 0x190 to include crc) return false; */ +// if (!writeCrc(0x0480, 0x180)) // whatever I do it crashes Atmos..! +// return false; + gfx_printf("%kErasing SSL cert...\n", COLOR_YELLOW); if (!erase(0x0AE0, 0x800)) return false; @@ -441,11 +445,11 @@ bool incognito() if (!erase(0x3FC0, 0x240)) return false; - gfx_printf("%kWriting client cert hash...\n", COLOR_YELLOW); + gfx_printf("%kWriting SSL cert hash...\n", COLOR_YELLOW); if (!writeClientCertHash()) return false; - gfx_printf("%kWriting CAL0 hash...\n", COLOR_YELLOW); + gfx_printf("%kWriting body hash...\n", COLOR_YELLOW); if (!writeCal0Hash()) return false; @@ -993,6 +997,11 @@ bool restoreProdinfo() goto out; } + if (validateCrc(0x250, 0x1E)) + gfx_printf("%kValid serial checksum\n", COLOR_GREEN); + else + gfx_printf("%kWarning - invalid serial checksum\n", COLOR_RED); + result = true; gfx_printf("\n%kRestore from %s done!\n\n", COLOR_GREEN, name); out: From 0693b6c638afd0640c31b8e9409d54a15c967ca9 Mon Sep 17 00:00:00 2001 From: Dan Ware Date: Sat, 6 Jun 2020 14:46:46 +0100 Subject: [PATCH 4/6] Added missing import --- source/incognito/io/io.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/incognito/io/io.c b/source/incognito/io/io.c index 818a731..fcc9f12 100644 --- a/source/incognito/io/io.c +++ b/source/incognito/io/io.c @@ -2,6 +2,7 @@ #include "../../storage/sdmmc.h" #include "../../storage/nx_emmc.h" +#include "../../storage/emummc.h" #include #include "../../sec/se.h" From 34dd3fff4c2ff1fe6255024e93ccc336b18ee224 Mon Sep 17 00:00:00 2001 From: Dan Ware Date: Sat, 6 Jun 2020 18:29:44 +0100 Subject: [PATCH 5/6] Implemented full checksum writing and warnings where they are invalid --- source/incognito/incognito.c | 75 ++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 16 deletions(-) diff --git a/source/incognito/incognito.c b/source/incognito/incognito.c index 57128ef..e353591 100644 --- a/source/incognito/incognito.c +++ b/source/incognito/incognito.c @@ -119,32 +119,58 @@ unsigned short int get_crc_16 (const char *p, int n) { return(crc); } -u16 calculateCrc(u32 offset, u32 size) +u16 calculateCrc(u32 offset, u32 size, u8 *blob) { const char buffer[size + 1]; - readData((u8 *)buffer, offset, size, NULL); + if (blob == NULL) + readData((u8 *)buffer, offset, size, NULL); + else + memcpy((u8 *)buffer, blob + offset, size); + return get_crc_16(buffer, size); } -u16 readCrc(u32 offset) +u16 readCrc(u32 offset, u8 *blob) { u16 buffer; - readData((u8 *)&buffer, offset, sizeof(u16), NULL); + if (blob == NULL) + readData((u8 *)&buffer, offset, sizeof(u16), NULL); + else + memcpy((u8 *)&buffer, blob + offset, sizeof(u16)); + return buffer; } -bool validateCrc(u32 offset, u32 size) +bool validateCrc(u32 offset, u32 size, u8 *blob) { - return calculateCrc(offset, size) == readCrc(offset + size); + return calculateCrc(offset, size, blob) == readCrc(offset + size, blob); } bool calculateAndWriteCrc(u32 offset, u32 size) { - u16 crcValue = calculateCrc(offset, size); + u16 crcValue = calculateCrc(offset, size, NULL); u8 crc[2] = { crcValue & 0xff, crcValue >> 8 }; // bytes of u16 return writeData(crc, offset + size, sizeof(u16), NULL); } +void validateChecksums(u8 *blob) +{ + if (!validateCrc(0x0250, 0x1E, blob)) + gfx_printf("%kWarning - invalid serial number checksum\n", COLOR_GREEN); + + if (!validateCrc(0x0480, 0x18E, blob)) + gfx_printf("%kWarning - invalid ECC-B233 device cert checksum...\n", COLOR_RED); + + if (!validateCrc(0x3AE0, 0x13E, blob)) + gfx_printf("%kWarning - invalid extended SSL key checksum...\n", COLOR_RED); + + if (!validateCrc(0x35A0, 0x07E, blob)) + gfx_printf("%kWarning - invalid Amiibo ECDSA cert checksum...\n", COLOR_RED); + + if (!validateCrc(0x36A0, 0x09E, blob)) + gfx_printf("%kWarning - invalid Amiibo ECQV-BLS root cert checksum...\n", COLOR_RED); +} + bool dump_keys() { display_backlight_brightness(100, 1000); @@ -363,7 +389,7 @@ bool dump_keys() gfx_printf("%kCurrent serial: [%s]\n\n", COLOR_BLUE, serial); - if (validateCrc(serialOffset, 0x1E)) + if (validateCrc(serialOffset, 0x1E, NULL)) gfx_printf("%kValid serial checksum\n", COLOR_GREEN); else gfx_printf("%kWarning - invalid serial checksum\n", COLOR_RED); @@ -395,7 +421,6 @@ bool writeSerial() if (!writeData((u8 *)junkSerial, serialOffset, 14, NULL)) return false; - // write crc at end of serial-number block return calculateAndWriteCrc(serialOffset, 0x1E); } @@ -410,17 +435,19 @@ bool incognito() return false; } + validateChecksums(NULL); + gfx_printf("%kWriting fake serial...\n", COLOR_YELLOW); if (!writeSerial()) return false; /* gfx_printf("%kErasing ECC-B233 device cert...\n", COLOR_YELLOW); - if (!erase(0x0480, 0x180)) // (size 0x190 to include crc) + if (!erase(0x0480, 0x180)) + return false; + + if (!calculateAndWriteCrc(0x0480, 0x18E)) // whatever I do here, it crashes Atmos..? return false; */ -// if (!writeCrc(0x0480, 0x180)) // whatever I do it crashes Atmos..! -// return false; - gfx_printf("%kErasing SSL cert...\n", COLOR_YELLOW); if (!erase(0x0AE0, 0x800)) return false; @@ -429,20 +456,32 @@ bool incognito() if (!erase(0x3AE0, 0x130)) return false; + gfx_printf("%kWriting checksum...\n", COLOR_YELLOW); + if (!calculateAndWriteCrc(0x3AE0, 0x13E)) + return false; + gfx_printf("%kErasing Amiibo ECDSA cert...\n", COLOR_YELLOW); if (!erase(0x35A0, 0x070)) return false; + gfx_printf("%kWriting checksum...\n", COLOR_YELLOW); + if (!calculateAndWriteCrc(0x35A0, 0x07E)) + return false; + gfx_printf("%kErasing Amiibo ECQV-BLS root cert...\n", COLOR_YELLOW); if (!erase(0x36A0, 0x090)) return false; + gfx_printf("%kWriting checksum...\n", COLOR_YELLOW); + if (!calculateAndWriteCrc(0x36A0, 0x09E)) + return false; + gfx_printf("%kErasing RSA-2048 extended device key...\n", COLOR_YELLOW); - if (!erase(0x3D70, 0x240)) + if (!erase(0x3D70, 0x240)) // seems empty & unused... return false; gfx_printf("%kErasing RSA-2048 device certificate...\n", COLOR_YELLOW); - if (!erase(0x3FC0, 0x240)) + if (!erase(0x3FC0, 0x240)) // seems empty & unused... return false; gfx_printf("%kWriting SSL cert hash...\n", COLOR_YELLOW); @@ -817,6 +856,8 @@ bool verifyProdinfo(u8 *blob) if (verifyClientCertHash(blob) && verifyCal0Hash(blob)) { + validateChecksums(blob); + char serial[15] = ""; if (blob == NULL) { @@ -997,10 +1038,12 @@ bool restoreProdinfo() goto out; } - if (validateCrc(0x250, 0x1E)) + /* + if (validateCrc(0x250, 0x1E, NULL)) gfx_printf("%kValid serial checksum\n", COLOR_GREEN); else gfx_printf("%kWarning - invalid serial checksum\n", COLOR_RED); + */ result = true; gfx_printf("\n%kRestore from %s done!\n\n", COLOR_GREEN, name); From d29010a84b3cd38af470804acc68ac7c3e3ee0bc Mon Sep 17 00:00:00 2001 From: Dan Ware Date: Sat, 6 Jun 2020 19:23:28 +0100 Subject: [PATCH 6/6] Cleaned up output warnings --- source/incognito/incognito.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/source/incognito/incognito.c b/source/incognito/incognito.c index e353591..fb45f41 100644 --- a/source/incognito/incognito.c +++ b/source/incognito/incognito.c @@ -156,19 +156,19 @@ bool calculateAndWriteCrc(u32 offset, u32 size) void validateChecksums(u8 *blob) { if (!validateCrc(0x0250, 0x1E, blob)) - gfx_printf("%kWarning - invalid serial number checksum\n", COLOR_GREEN); + gfx_printf("%kWarning - invalid serial crc\n", COLOR_RED); if (!validateCrc(0x0480, 0x18E, blob)) - gfx_printf("%kWarning - invalid ECC-B233 device cert checksum...\n", COLOR_RED); + gfx_printf("%kWarning - invalid ECC-B233 crc...\n", COLOR_RED); if (!validateCrc(0x3AE0, 0x13E, blob)) - gfx_printf("%kWarning - invalid extended SSL key checksum...\n", COLOR_RED); + gfx_printf("%kWarning - invalid ext SSL key crc...\n", COLOR_RED); if (!validateCrc(0x35A0, 0x07E, blob)) - gfx_printf("%kWarning - invalid Amiibo ECDSA cert checksum...\n", COLOR_RED); + gfx_printf("%kWarning - invalid ECDSA cert crc...\n", COLOR_RED); if (!validateCrc(0x36A0, 0x09E, blob)) - gfx_printf("%kWarning - invalid Amiibo ECQV-BLS root cert checksum...\n", COLOR_RED); + gfx_printf("%kWarning - invalid ECQV-BLS cert crc...\n", COLOR_RED); } bool dump_keys() @@ -382,18 +382,11 @@ bool dump_keys() return false; } - u32 serialOffset = 0x250; - char serial[15]; - readData((u8 *)serial, serialOffset, 14, NULL); + readData((u8 *)serial, 0x250, 14, NULL); gfx_printf("%kCurrent serial: [%s]\n\n", COLOR_BLUE, serial); - if (validateCrc(serialOffset, 0x1E, NULL)) - gfx_printf("%kValid serial checksum\n", COLOR_GREEN); - else - gfx_printf("%kWarning - invalid serial checksum\n", COLOR_RED); - return true; } @@ -424,7 +417,6 @@ bool writeSerial() return calculateAndWriteCrc(serialOffset, 0x1E); } -// todo: include crc block in sizes bool incognito() { gfx_printf("%kChecking if backup exists...\n", COLOR_YELLOW); @@ -477,11 +469,11 @@ bool incognito() return false; gfx_printf("%kErasing RSA-2048 extended device key...\n", COLOR_YELLOW); - if (!erase(0x3D70, 0x240)) // seems empty & unused... + if (!erase(0x3D70, 0x240)) // seems empty & unused! return false; gfx_printf("%kErasing RSA-2048 device certificate...\n", COLOR_YELLOW); - if (!erase(0x3FC0, 0x240)) // seems empty & unused... + if (!erase(0x3FC0, 0x240)) // seems empty & unused! return false; gfx_printf("%kWriting SSL cert hash...\n", COLOR_YELLOW);