diff options
author | Arisotura <thetotalworm@gmail.com> | 2019-08-07 12:57:12 +0200 |
---|---|---|
committer | Arisotura <thetotalworm@gmail.com> | 2019-08-07 12:57:12 +0200 |
commit | dcda848cdfd94aaa5549841d8ba3cb54370f9cbc (patch) | |
tree | a72586dbb095042261a0b6b03c1f18fcbe4974b5 | |
parent | 9c1ea0e539d797720ec5b0eaf999577ee5747eef (diff) |
* base for potentially re-encrypting modcrypt, doesn't seem to be required? but can also serve to decrypt it
* revise SD IRQ behavior (fixing potential hang when loading DS games)
-rw-r--r-- | src/DSi_AES.cpp | 61 | ||||
-rw-r--r-- | src/DSi_AES.h | 3 | ||||
-rw-r--r-- | src/DSi_SD.cpp | 29 | ||||
-rw-r--r-- | src/DSi_SD.h | 1 | ||||
-rw-r--r-- | src/NDSCart.cpp | 23 |
5 files changed, 111 insertions, 6 deletions
diff --git a/src/DSi_AES.cpp b/src/DSi_AES.cpp index 4aa97bc..e49ebf5 100644 --- a/src/DSi_AES.cpp +++ b/src/DSi_AES.cpp @@ -398,7 +398,7 @@ void Update() { Ctx.Iv[13] = 0x00; Ctx.Iv[14] = 0x00; - Ctx.Iv[15] = 0x00;_printhex(Ctx.Iv, 16); + Ctx.Iv[15] = 0x00; AES_CTR_xcrypt_buffer(&Ctx, CurMAC, 16); //printf("FINAL MAC: "); _printhexR(CurMAC, 16); @@ -505,4 +505,63 @@ void WriteKeyY(u32 slot, u32 offset, u32 val, u32 mask) } } + +// utility + +void GetModcryptKey(u8* romheader, u8* key) +{ + if ((romheader[0x01C] & 0x04) || (romheader[0x1BF] & 0x80)) + { + // dev key + memcpy(key, &romheader[0x000], 16); + return; + } + + u8 oldkeys[16*3]; + memcpy(&oldkeys[16*0], KeyX[0], 16); + memcpy(&oldkeys[16*1], KeyY[0], 16); + memcpy(&oldkeys[16*2], KeyNormal[0], 16); + + KeyX[0][8] = romheader[0x00C]; + KeyX[0][9] = romheader[0x00D]; + KeyX[0][10] = romheader[0x00E]; + KeyX[0][11] = romheader[0x00F]; + KeyX[0][12] = romheader[0x00F]; + KeyX[0][13] = romheader[0x00E]; + KeyX[0][14] = romheader[0x00D]; + KeyX[0][15] = romheader[0x00C]; + + memcpy(KeyY[0], &romheader[0x350], 16); + + DeriveNormalKey(0); + memcpy(key, KeyNormal[0], 16); + + memcpy(KeyX[0], &oldkeys[16*0], 16); + memcpy(KeyY[0], &oldkeys[16*1], 16); + memcpy(KeyNormal[0], &oldkeys[16*2], 16); +} + +void ApplyModcrypt(u8* data, u32 len, u8* key, u8* iv) +{ + u8 key_rev[16], iv_rev[16]; + u8 data_rev[16]; + u8 oldkeys[16*2]; + memcpy(&oldkeys[16*0], Ctx.RoundKey, 16); + memcpy(&oldkeys[16*1], Ctx.Iv, 16); + + Swap16(key_rev, key); + Swap16(iv_rev, iv); + AES_init_ctx_iv(&Ctx, key_rev, iv_rev); + + for (u32 i = 0; i < len; i += 16) + { + Swap16(data_rev, &data[i]); + AES_CTR_xcrypt_buffer(&Ctx, data_rev, 16); + Swap16(&data[i], data_rev); + } + + memcpy(Ctx.RoundKey, &oldkeys[16*0], 16); + memcpy(Ctx.Iv, &oldkeys[16*1], 16); +} + } diff --git a/src/DSi_AES.h b/src/DSi_AES.h index 5e726cd..354c4a7 100644 --- a/src/DSi_AES.h +++ b/src/DSi_AES.h @@ -46,6 +46,9 @@ void WriteKeyNormal(u32 slot, u32 offset, u32 val, u32 mask); void WriteKeyX(u32 slot, u32 offset, u32 val, u32 mask); void WriteKeyY(u32 slot, u32 offset, u32 val, u32 mask); +void GetModcryptKey(u8* romheader, u8* key); +void ApplyModcrypt(u8* data, u32 len, u8* key, u8* iv); + } #endif // DSI_AES_H diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index 44d8d62..796466d 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -149,6 +149,15 @@ void DSi_SDHost::SetIRQ(u32 irq) if (irq == 24 || irq == 25) UpdateData32IRQ(); } +void DSi_SDHost::UpdateIRQ(u32 oldmask) +{ + u32 oldflags = IRQStatus & ~oldmask; + u32 newflags = IRQStatus & ~IRQMask; + + if ((oldflags == 0) && (newflags != 0)) + NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO : NDS::IRQ2_DSi_SDMMC); +} + void DSi_SDHost::SetCardIRQ() { if (!(CardIRQCtl & (1<<0))) return; @@ -424,7 +433,7 @@ u32 DSi_SDHost::ReadFIFO32() return ret; } -int morp = 0; + void DSi_SDHost::Write(u32 addr, u16 val) { //if(Num)printf("SDIO WRITE %08X %04X %08X\n", addr, val, NDS::GetPC(1)); @@ -464,11 +473,21 @@ void DSi_SDHost::Write(u32 addr, u16 val) case 0x01C: IRQStatus &= (val | 0xFFFF0000); return; case 0x01E: IRQStatus &= ((val << 16) | 0xFFFF); return; - case 0x020: IRQMask = (IRQMask & 0x8B7F0000) | (val & 0x031D); return; + case 0x020: + { + u32 oldmask = IRQMask; + IRQMask = (IRQMask & 0x8B7F0000) | (val & 0x031D); + UpdateIRQ(oldmask); + } + return; case 0x022: - IRQMask = (IRQMask & 0x0000031D) | ((val & 0x8B7F) << 16); - if (!DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(24); // checkme - if (DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(25); // checkme + { + u32 oldmask = IRQMask; + IRQMask = (IRQMask & 0x0000031D) | ((val & 0x8B7F) << 16); + UpdateIRQ(oldmask); + if (!DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(24); // checkme + if (DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(25); // checkme + } return; case 0x024: SDClock = val & 0x03FF; return; diff --git a/src/DSi_SD.h b/src/DSi_SD.h index 149b72a..f4ca26c 100644 --- a/src/DSi_SD.h +++ b/src/DSi_SD.h @@ -84,6 +84,7 @@ private: void UpdateData32IRQ(); void ClearIRQ(u32 irq); void SetIRQ(u32 irq); + void UpdateIRQ(u32 oldmask); }; diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index c3765d8..65cf8ae 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -23,6 +23,7 @@ #include "NDSCart.h" #include "ARM.h" #include "CRC32.h" +#include "DSi_AES.h" #include "Platform.h" @@ -599,6 +600,15 @@ void Key2_Encrypt(u8* data, u32 len) } +void ApplyModcrypt(u32 addr, u32 len, u8* iv) +{return; + u8 key[16]; + + DSi_AES::GetModcryptKey(&CartROM[0], key); + DSi_AES::ApplyModcrypt(&CartROM[addr], len, key, iv); +} + + bool Init() { if (!NDSCart_SRAM::Init()) return false; @@ -980,6 +990,19 @@ bool LoadROM(const char* path, const char* sram, bool direct) CartIsHomebrew = true; } + // re-encrypt modcrypt areas if needed + // TODO: somehow detect whether those are already encrypted + if (true) + { + u32 mod1 = *(u32*)&CartROM[0x220]; + u32 mod2 = *(u32*)&CartROM[0x228]; + + printf("Re-encrypting modcrypt areas: %08X, %08X\n", mod1, mod2); + + if (mod1) ApplyModcrypt(mod1, *(u32*)&CartROM[0x224], &CartROM[0x300]); + if (mod2) ApplyModcrypt(mod2, *(u32*)&CartROM[0x22C], &CartROM[0x314]); + } + // save printf("Save file: %s\n", sram); |