|
3 | 3 | #include "hid.h" |
4 | 4 | #include "platform.h" |
5 | 5 | #include "decryptor/aes.h" |
| 6 | +#include "decryptor/sha.h" |
6 | 7 | #include "decryptor/decryptor.h" |
7 | 8 | #include "decryptor/nand.h" |
8 | 9 | #include "fatfs/sdmmc.h" |
@@ -105,6 +106,86 @@ static inline int WriteNandSectors(u32 sector_no, u32 numsectors, u8 *in) |
105 | 106 | } else return sdmmc_nand_writesectors(sector_no, numsectors, in); |
106 | 107 | } |
107 | 108 |
|
| 109 | +u32 SetupNandCrypto(u8* ctr, u32 offset) |
| 110 | +{ |
| 111 | + static bool initial_setup_done = false; |
| 112 | + static u8 CtrNandCtr[16]; |
| 113 | + //static u8 TwlNandCtr[16]; |
| 114 | + |
| 115 | + if (!initial_setup_done) { |
| 116 | + // CTRNAND |
| 117 | + u8 NandCid[16]; |
| 118 | + u8 shasum[32]; |
| 119 | + |
| 120 | + sdmmc_get_cid( 1, (uint32_t*) NandCid); |
| 121 | + sha_init(SHA256_MODE); |
| 122 | + sha_update(NandCid, 16); |
| 123 | + sha_get(shasum); |
| 124 | + memcpy(CtrNandCtr, shasum, 16); |
| 125 | + |
| 126 | + /*sha_init(SHA1_MODE); |
| 127 | + sha_update(NandCid, 16); |
| 128 | + sha_get(shasum); |
| 129 | + for(u32 i = 0; i < 16; i++) // little endian and reversed order |
| 130 | + TwlNandCtr[i] = shasum[15-i]; |
| 131 | + |
| 132 | + Debug("NAND CID: %08X%08X%08X%08X", getbe32(NandCid), getbe32(NandCid+4), getbe32(NandCid+8), getbe32(NandCid+12)); |
| 133 | + |
| 134 | + // part #2: TWL KEY |
| 135 | + // see: https://www.3dbrew.org/wiki/Memory_layout#ARM9_ITCM |
| 136 | + u32* TwlCustId = (u32*) (0x01FFB808+8); |
| 137 | + u8 TwlKeyX[16]; |
| 138 | + u8 TwlKeyY[16]; |
| 139 | + |
| 140 | + Debug("TWL Customer ID: %08X%08X", TwlCustId[0], TwlCustId[1]); |
| 141 | + |
| 142 | + // see source from https://gbatemp.net/threads/release-twltool-dsi-downgrading-save-injection-etc-multitool.393488/ |
| 143 | + const char* nintendo = "NINTENDO"; |
| 144 | + u32* TwlKeyXW = (u32*) TwlKeyX; |
| 145 | + TwlKeyXW[0] = (TwlCustId[0] ^ 0xB358A6AF) | 0x80000000; |
| 146 | + TwlKeyXW[3] = TwlCustId[1] ^ 0x08C267B7; |
| 147 | + memcpy(TwlKeyX + 4, nintendo, 8); |
| 148 | + |
| 149 | + // see: https://www.3dbrew.org/wiki/Memory_layout#ARM9_ITCM |
| 150 | + u32 TwlKeyYW3 = 0xE1A00005; |
| 151 | + memcpy(TwlKeyY, (u8*) 0x01FFD3C8, 12); |
| 152 | + memcpy(TwlKeyY + 12, &TwlKeyYW3, 4); |
| 153 | + |
| 154 | + setup_aeskeyX(0x03, TwlKeyX); |
| 155 | + setup_aeskeyY(0x03, TwlKeyY); |
| 156 | + Debug("0x03 KeyX: %08X%08X%08X%08X", getbe32(TwlKeyX), getbe32(TwlKeyX+4), getbe32(TwlKeyX+8), getbe32(TwlKeyX+12)); |
| 157 | + Debug("0x03 KeyY: %08X%08X%08X%08X", getbe32(TwlKeyY), getbe32(TwlKeyY+4), getbe32(TwlKeyY+8), getbe32(TwlKeyY+12)); |
| 158 | + |
| 159 | + // part #3: CTRNAND N3DS KEY |
| 160 | + while (GetUnitPlatform() == PLATFORM_N3DS) { |
| 161 | + u8 CtrNandKeyY[16]; |
| 162 | + |
| 163 | + if (!FileOpen("slot0x05KeyY.bin")) { |
| 164 | + Debug("0x05 KeyY: not set, slot0x05KeyY.bin not found"); |
| 165 | + break; |
| 166 | + } |
| 167 | + if (FileRead(CtrNandKeyY, 16, 0) != 16) { |
| 168 | + Debug("0x05 KeyY: not set, bad file"); |
| 169 | + FileClose(); |
| 170 | + break; |
| 171 | + } |
| 172 | + FileClose(); |
| 173 | + |
| 174 | + setup_aeskeyY(0x05, CtrNandKeyY); |
| 175 | + Debug("0x05 KeyY: %08X%08X%08X%08X", getbe32(CtrNandKeyY), getbe32(CtrNandKeyY+4), getbe32(CtrNandKeyY+8), getbe32(CtrNandKeyY+12)); |
| 176 | + break; |
| 177 | + }*/ |
| 178 | + |
| 179 | + initial_setup_done = true; |
| 180 | + } |
| 181 | + |
| 182 | + // get the correct CTR and increment counter |
| 183 | + memcpy(ctr, CtrNandCtr, 16); |
| 184 | + add_ctr(ctr, offset / 0x10); |
| 185 | + |
| 186 | + return 0; |
| 187 | +} |
| 188 | + |
108 | 189 | u32 OutputFileNameSelector(char* filename, const char* basename, char* extension, bool emuname) { |
109 | 190 | char bases[3][64] = { 0 }; |
110 | 191 | char* dotpos = NULL; |
@@ -404,7 +485,7 @@ u32 GetNandCtr(u8* ctr, u32 offset) |
404 | 485 | u32 DecryptNandToMem(u8* buffer, u32 offset, u32 size, PartitionInfo* partition) |
405 | 486 | { |
406 | 487 | CryptBufferInfo info = {.keyslot = partition->keyslot, .setKeyY = 0, .size = size, .buffer = buffer, .mode = partition->mode}; |
407 | | - if(GetNandCtr(info.ctr, offset) != 0) |
| 488 | + if(SetupNandCrypto(info.ctr, offset) != 0) |
408 | 489 | return 1; |
409 | 490 |
|
410 | 491 | u32 n_sectors = (size + NAND_SECTOR_SIZE - 1) / NAND_SECTOR_SIZE; |
@@ -668,23 +749,23 @@ u32 DumpAgbSave(u32 parm) |
668 | 749 | memcpy(&Saveadder, Header + (sizeof(u8) * 0x50), sizeof(u32)); |
669 | 750 | char *Magic = ".SAV"; |
670 | 751 | if (Saveadder != 0x200 || memcmp(Magic, Header, 4)) { |
671 | | - Debug("The Agb_save partiton is corrupted."); |
672 | | - Debug("Did you run an Agb_firm game?"); |
| 752 | + Debug("The AGBSAVE partition is corrupted."); |
| 753 | + Debug("Did you run a GBA VC game?"); |
673 | 754 | return 1; |
674 | 755 | } |
675 | 756 | u32 Savesize; |
676 | 757 | memcpy(&Savesize, Header + (sizeof(u8) * 0x54), sizeof(u32)); |
677 | 758 | u32 Titleid; |
678 | 759 | memcpy(&Titleid, Header + 0x38, 4); |
679 | | - Debug("Title id %08x", Titleid); |
| 760 | + Debug("Title ID: %08x", Titleid); |
680 | 761 | if (Savesize == 32768) { |
681 | | - Debug("Use save type 0"); |
| 762 | + Debug("Use save type 0: SRAM"); |
682 | 763 | } else if (Savesize == 65536) { |
683 | | - Debug("Use save type 1"); |
| 764 | + Debug("Use save type 1: Flash"); |
684 | 765 | } else if (Savesize == 0x2000) { |
685 | | - Debug("Use save type 2"); |
| 766 | + Debug("Use save type 2: EEPROM"); |
686 | 767 | } else { |
687 | | - Debug("Injecton support for this game is not yet ready"); |
| 768 | + Debug("Injection support for this game is not yet ready"); |
688 | 769 | } |
689 | 770 | if (Savesize == 0x2000) { |
690 | 771 | u8* buffer = BUFFER_ADDRESS; |
|
0 commit comments