diff options
author | Arisotura <thetotalworm@gmail.com> | 2019-06-19 14:24:49 +0200 |
---|---|---|
committer | Arisotura <thetotalworm@gmail.com> | 2019-06-19 14:24:49 +0200 |
commit | 81dde71ebac19cf9a68dd7a2a41561cbcbfacc68 (patch) | |
tree | eee34280de6e267ebde0fe384fe669900c7b2098 /src | |
parent | f0131cfac9fc82dd0e1a74ba06f840a0b26d8966 (diff) |
add AES, fix a bunch of bugs
we're getting an error screen! wee
Diffstat (limited to 'src')
-rw-r--r-- | src/ARM.cpp | 37 | ||||
-rw-r--r-- | src/DSi.cpp | 55 | ||||
-rw-r--r-- | src/DSi.h | 3 | ||||
-rw-r--r-- | src/DSi_AES.cpp | 303 | ||||
-rw-r--r-- | src/DSi_AES.h | 26 | ||||
-rw-r--r-- | src/DSi_NDMA.cpp | 21 | ||||
-rw-r--r-- | src/DSi_SD.cpp | 21 | ||||
-rw-r--r-- | src/NDS.cpp | 6 |
8 files changed, 416 insertions, 56 deletions
diff --git a/src/ARM.cpp b/src/ARM.cpp index 60dec9a..b7fe3c7 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -239,36 +239,6 @@ void ARMv4::JumpTo(u32 addr, bool restorecpsr) else addr &= ~0x1; } - /*if (addr==0x037D4668) printf("MYSTERY START\n"); - if (addr==0x037CA71C) printf("MYSTERY END\n"); - if (addr==0x037CCD68) printf("atomic_store %08X %08X, %08X\n", R[0], R[1], R[15]); - if (addr==0x037CDD00) printf("zog %08X\n", R[15]);*/ - /*if (addr==0x037CDC00) printf("sendcmd %08X %08X\n", R[0], R[15]); - if (addr==0x037CA700) printf("prepare CID, %08X\n", R[15]); - if(addr==0x037D4498) printf("READ SHITTY FIFO. %08X\n", R[15]); - if (addr==0x037CCD68) printf("atomic_store %08X %08X, %08X\n", R[0], R[1], R[15]); - if (addr>=0x037CEE00 && addr<=0x037CEE30) printf("shitty loop: %08X->%08X\n", R[15], addr); - if (R[15]==0x037CCD8C) printf("BERG!!! %08X\n", addr); - if (addr==0x037CD600) printf("XFER IRQ HANDLER\n"); - if (R[15]==0x037CD62C) printf("TERRIBLE HANDLER: %08X\n", addr); - if (addr==0x037CCE24) printf("SD IRQ HANDLER\n"); - if (addr==0x037CCD94) printf("atomic_load %08X %08X, %08X\n", R[0], R[1], R[15]); - if (addr==0x037CEB7C) printf("CHECK CSR RESULT. %08X %08X %08X, %08X\n", R[0], R[1], R[2], R[15]); - if (R[15]==0x037CEC6C) printf("RETURN FROM CSR CHECK: %08X %08X\n", R[0], R[3]+0x38); - if (addr==0x037CB2AC) printf("ZOG!\n"); - if (addr==0x037CB2A0) printf("GONP %08X %08X, %08X\n", R[1]+0x28, R[3]+0x34, R[15]); - if (addr==0x037CCFC0) printf("SDMMC TIMEOUT. %08X\n", R[15]); - if (addr==0x037D68A8) printf("BARKBARKBARK. %08X\n", R[15]); - if (addr==0x037CCF04) printf("BAKAAA\n"); - if (addr==0x037D6988) printf("MORPMORPMORPMORPMORPMORPMORPMORPMORP %08X\n", R[15]); - if (addr==0x37D6904) printf("TIMEOUT FARTORED! %08X, %08X %08X, %08X\n", R[4], R[3], R[12], R[15]); - // TIMEOUT FARTORED! 037E89B8, 00000000 00200BFB, 037D68FC - if (addr==0x037CD660) printf("BRAAAAAAAAAAAP %08X\n", R[15]); - if (addr==0x037CD798) printf("BRAAPP SHATORED. %08X, %08X %08X\n", R[0], R[1], R[2]); - if (addr==0x037CCD34) printf("atomic_and %08X %08X, %08X\n", R[0], R[1], R[15]);*/ - // atomic_and 0400481C 0000FFE7, 037CD850 - - u32 oldregion = R[15] >> 23; u32 newregion = addr >> 23; @@ -607,13 +577,6 @@ void ARMv4::Execute() } else AddCycles_C(); - - /*if (R[15]==0x037CEE18) printf("SHITTY POINTER = %08X\n", R[0]+0x34); - if (R[15]==0x037CEE1C) printf("SHITTY FLAG = %08X\n", R[0]); - if (R[15]==0x037D68F0) printf("TIMESTAMP THING = %08X:%08X, CUR=%08X:%08X, ptr=%08X\n", - R[3], R[12], R[1], R[0], R[4]); - //if (R[15]==0x037CB29C) printf("GLORG!!! %08X\n", R[3]+0x34); 037E8A8C - if (R[15]==0x037CD730) printf("COUNT OF SHITO. %08X %08X\n", R[0], R[2]);*/ } // TODO optimize this shit!!! diff --git a/src/DSi.cpp b/src/DSi.cpp index fc590e1..fd58872 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -28,6 +28,7 @@ #include "DSi_NDMA.h" #include "DSi_I2C.h" #include "DSi_SD.h" +#include "DSi_AES.h" namespace NDS @@ -71,6 +72,7 @@ u8 eMMC_CID[16]; bool Init() { if (!DSi_I2C::Init()) return false; + if (!DSi_AES::Init()) return false; NDMAs[0] = new DSi_NDMA(0, 0); NDMAs[1] = new DSi_NDMA(0, 1); @@ -90,6 +92,7 @@ bool Init() void DeInit() { DSi_I2C::DeInit(); + DSi_AES::DeInit(); for (int i = 0; i < 8; i++) delete NDMAs[i]; @@ -110,6 +113,7 @@ void Reset() for (int i = 0; i < 8; i++) NDMAs[i]->Reset(); DSi_I2C::Reset(); + DSi_AES::Reset(); SDMMC->Reset(); SDIO->Reset(); @@ -336,6 +340,24 @@ bool NDMAsRunning(u32 cpu) return false; } +void CheckNDMAs(u32 cpu, u32 mode) +{ + cpu <<= 2; + NDMAs[cpu+0]->StartIfNeeded(mode); + NDMAs[cpu+1]->StartIfNeeded(mode); + NDMAs[cpu+2]->StartIfNeeded(mode); + NDMAs[cpu+3]->StartIfNeeded(mode); +} + +void StopNDMAs(u32 cpu, u32 mode) +{ + cpu <<= 2; + NDMAs[cpu+0]->StopIfNeeded(mode); + NDMAs[cpu+1]->StopIfNeeded(mode); + NDMAs[cpu+2]->StopIfNeeded(mode); + NDMAs[cpu+3]->StopIfNeeded(mode); +} + // new WRAM mapping // TODO: find out what happens upon overlapping slots!! @@ -1097,6 +1119,9 @@ u32 ARM7IORead32(u32 addr) case 0x04004168: return NDMAs[7]->SubblockTimer; case 0x0400416C: return NDMAs[7]->FillData; case 0x04004170: return NDMAs[7]->Cnt; + + case 0x04004400: return DSi_AES::ReadCnt(); + case 0x0400440C: return DSi_AES::ReadOutputFIFO(); } if (addr >= 0x04004800 && addr < 0x04004A00) @@ -1182,6 +1207,36 @@ void ARM7IOWrite32(u32 addr, u32 val) case 0x04004168: NDMAs[7]->SubblockTimer = val & 0x0003FFFF; return; case 0x0400416C: NDMAs[7]->FillData = val; return; case 0x04004170: NDMAs[7]->WriteCnt(val); return; + + case 0x04004400: DSi_AES::WriteCnt(val); return; + case 0x04004404: DSi_AES::WriteBlkCnt(val); return; + case 0x04004408: DSi_AES::WriteInputFIFO(val); return; + } + + if (addr >= 0x04004420 && addr < 0x04004430) + { + addr -= 0x04004420; + DSi_AES::WriteIV(addr, val, 0xFFFFFFFF); + return; + } + if (addr >= 0x04004430 && addr < 0x04004440) + { + addr -= 0x04004430; + DSi_AES::WriteMAC(addr, val, 0xFFFFFFFF); + return; + } + if (addr >= 0x04004440 && addr < 0x04004500) + { + addr -= 0x04004440; + int n = 0; + while (addr > 0x30) { addr -= 0x30; n++; } + + switch (addr >> 4) + { + case 0: DSi_AES::WriteKeyNormal(n, addr&0xF, val, 0xFFFFFFFF); return; + case 1: DSi_AES::WriteKeyX(n, addr&0xF, val, 0xFFFFFFFF); return; + case 2: DSi_AES::WriteKeyY(n, addr&0xF, val, 0xFFFFFFFF); return; + } } if (addr >= 0x04004800 && addr < 0x04004A00) @@ -26,6 +26,7 @@ namespace DSi { extern u8 eMMC_CID[16]; +extern u64 ConsoleID; extern DSi_SDHost* SDMMC; extern DSi_SDHost* SDIO; @@ -41,6 +42,8 @@ bool LoadNAND(); void RunNDMAs(u32 cpu); void StallNDMAs(); bool NDMAsRunning(u32 cpu); +void CheckNDMAs(u32 cpu, u32 mode); +void StopNDMAs(u32 cpu, u32 mode); void MapNWRAM_A(u32 num, u8 val); void MapNWRAM_B(u32 num, u8 val); diff --git a/src/DSi_AES.cpp b/src/DSi_AES.cpp index 6a524dd..8271e3e 100644 --- a/src/DSi_AES.cpp +++ b/src/DSi_AES.cpp @@ -15,3 +15,306 @@ You should have received a copy of the GNU General Public License along with melonDS. If not, see http://www.gnu.org/licenses/. */ + +#include <stdio.h> +#include <string.h> +#include "DSi.h" +#include "DSi_AES.h" +#include "FIFO.h" +#include "tiny-AES-c/aes.hpp" + + +namespace DSi_AES +{ + +u32 Cnt; + +u32 BlkCnt; +u32 RemBlocks; + +u32 InputDMASize, OutputDMASize; +u32 AESMode; + +FIFO<u32>* InputFIFO; +FIFO<u32>* OutputFIFO; + +u8 IV[16]; + +u8 KeyNormal[4][16]; +u8 KeyX[4][16]; +u8 KeyY[4][16]; + +u8 CurKey[16]; + +AES_ctx Ctx; + + +void Swap16(u8* dst, u8* src) +{ + for (int i = 0; i < 16; i++) + dst[i] = src[15-i]; +} + +void ROL16(u8* val, u32 n) +{ + u32 n_coarse = n >> 3; + u32 n_fine = n & 7; + u8 tmp[16]; + + for (u32 i = 0; i < 16; i++) + { + tmp[i] = val[(i - n_coarse) & 0xF]; + } + + for (u32 i = 0; i < 16; i++) + { + val[i] = (tmp[i] << n_fine) | (tmp[(i - 1) & 0xF] >> (8-n_fine)); + } +} + +#define _printhex(str, size) { for (int z = 0; z < (size); z++) printf("%02X", (str)[z]); printf("\n"); } + + +bool Init() +{ + InputFIFO = new FIFO<u32>(16); + OutputFIFO = new FIFO<u32>(16); + + const u8 zero[16] = {0}; + AES_init_ctx_iv(&Ctx, zero, zero); + + return true; +} + +void DeInit() +{ + delete InputFIFO; + delete OutputFIFO; +} + +void Reset() +{ + Cnt = 0; + + BlkCnt = 0; + RemBlocks = 0; + + InputDMASize = 0; + OutputDMASize = 0; + AESMode = 0; + + InputFIFO->Clear(); + OutputFIFO->Clear(); + + memset(KeyNormal, 0, sizeof(KeyNormal)); + memset(KeyX, 0, sizeof(KeyX)); + memset(KeyY, 0, sizeof(KeyY)); + + memset(CurKey, 0, sizeof(CurKey)); + + // initialize keys, as per GBAtek + + // slot 3: console-unique eMMC crypto + *(u32*)&KeyX[3][0] = (u32)DSi::ConsoleID; + *(u32*)&KeyX[3][4] = (u32)DSi::ConsoleID ^ 0x24EE6906; + *(u32*)&KeyX[3][8] = (u32)(DSi::ConsoleID >> 32) ^ 0xE65B601D; + *(u32*)&KeyX[3][12] = (u32)(DSi::ConsoleID >> 32); + *(u32*)&KeyY[3][0] = 0x0AB9DC76; + *(u32*)&KeyY[3][4] = 0xBD4DC4D3; + *(u32*)&KeyY[3][8] = 0x202DDD1D; +} + + +void ProcessBlock_CTR() +{ + u8 data[16]; + u8 data_rev[16]; + + *(u32*)&data[0] = InputFIFO->Read(); + *(u32*)&data[4] = InputFIFO->Read(); + *(u32*)&data[8] = InputFIFO->Read(); + *(u32*)&data[12] = InputFIFO->Read(); + + //printf("AES-CTR: INPUT: "); _printhex(data, 16); + + Swap16(data_rev, data); + AES_CTR_xcrypt_buffer(&Ctx, data_rev, 16); + Swap16(data, data_rev); + + //printf("AES-CTR: OUTPUT: "); _printhex(data, 16); + + OutputFIFO->Write(*(u32*)&data[0]); + OutputFIFO->Write(*(u32*)&data[4]); + OutputFIFO->Write(*(u32*)&data[8]); + OutputFIFO->Write(*(u32*)&data[12]); +} + + +u32 ReadCnt() +{ + u32 ret = Cnt; + + ret |= InputFIFO->Level(); + ret |= (OutputFIFO->Level() << 5); + + return ret; +} + +void WriteCnt(u32 val) +{ + u32 oldcnt = Cnt; + Cnt = val & 0xFC1FF000; + + if (val & (1<<10)) InputFIFO->Clear(); + if (val & (1<<11)) OutputFIFO->Clear(); + + u32 dmasize[4] = {4, 8, 12, 16}; + InputDMASize = dmasize[3 - ((val >> 12) & 0x3)]; + OutputDMASize = dmasize[(val >> 14) & 0x3]; + + AESMode = (val >> 28) & 0x3; + if (AESMode < 2) printf("AES-CCM TODO\n"); + + if (val & (1<<24)) + { + u32 slot = (val >> 26) & 0x3; + memcpy(CurKey, KeyNormal[slot], 16); + + //printf("AES: key(%d): ", slot); _printhex(CurKey, 16); + + u8 tmp[16]; + Swap16(tmp, CurKey); + AES_init_ctx(&Ctx, tmp); + } + + if (!(oldcnt & (1<<31)) && (val & (1<<31))) + { + // transfer start (checkme) + RemBlocks = BlkCnt >> 16; + } + + printf("AES CNT: %08X / mode=%d inDMA=%d outDMA=%d blocks=%d\n", + val, AESMode, InputDMASize, OutputDMASize, RemBlocks); +} + +void WriteBlkCnt(u32 val) +{ + BlkCnt = val; +} + +u32 ReadOutputFIFO() +{ + return OutputFIFO->Read(); +} + +void WriteInputFIFO(u32 val) +{ + // TODO: add some delay to processing + + InputFIFO->Write(val); + + if (!(Cnt & (1<<31))) return; + + while (InputFIFO->Level() >= 4 && RemBlocks > 0) + { + switch (AESMode) + { + case 2: + case 3: ProcessBlock_CTR(); break; + default: + // dorp + OutputFIFO->Write(InputFIFO->Read()); + OutputFIFO->Write(InputFIFO->Read()); + OutputFIFO->Write(InputFIFO->Read()); + OutputFIFO->Write(InputFIFO->Read()); + } + + RemBlocks--; + } + + if (OutputFIFO->Level() >= OutputDMASize) + { + // trigger DMA + DSi::CheckNDMAs(1, 0x2B); + } + // TODO: DMA the other way around + + if (RemBlocks == 0) + { + Cnt &= ~(1<<31); + if (Cnt & (1<<30)) NDS::SetIRQ2(NDS::IRQ2_DSi_AES); + } +} + + +void WriteIV(u32 offset, u32 val, u32 mask) +{ + u32 old = *(u32*)&IV[offset]; + + *(u32*)&IV[offset] = (old & ~mask) | (val & mask); + + //printf("AES: IV: "); _printhex(IV, 16); + + u8 tmp[16]; + Swap16(tmp, IV); + AES_ctx_set_iv(&Ctx, tmp); +} + +void WriteMAC(u32 offset, u32 val, u32 mask) +{ + // +} + +void DeriveNormalKey(u32 slot) +{ + const u8 key_const[16] = {0xFF, 0xFE, 0xFB, 0x4E, 0x29, 0x59, 0x02, 0x58, 0x2A, 0x68, 0x0F, 0x5F, 0x1A, 0x4F, 0x3E, 0x79}; + u8 tmp[16]; + + //printf("keyX: "); _printhex(KeyX[slot], 16); + //printf("keyY: "); _printhex(KeyY[slot], 16); + + for (int i = 0; i < 16; i++) + tmp[i] = KeyX[slot][i] ^ KeyY[slot][i]; + + u32 carry = 0; + for (int i = 0; i < 16; i++) + { + u32 res = tmp[i] + key_const[15-i] + carry; + tmp[i] = res & 0xFF; + carry = res >> 8; + } + + ROL16(tmp, 42); + + //printf("derive normalkey %d\n", slot); _printhex(tmp, 16); + + memcpy(KeyNormal[slot], tmp, 16); +} + +void WriteKeyNormal(u32 slot, u32 offset, u32 val, u32 mask) +{ + u32 old = *(u32*)&KeyNormal[slot][offset]; + + *(u32*)&KeyNormal[slot][offset] = (old & ~mask) | (val & mask); +} + +void WriteKeyX(u32 slot, u32 offset, u32 val, u32 mask) +{ + u32 old = *(u32*)&KeyX[slot][offset]; + + *(u32*)&KeyX[slot][offset] = (old & ~mask) | (val & mask); +} + +void WriteKeyY(u32 slot, u32 offset, u32 val, u32 mask) +{ + u32 old = *(u32*)&KeyY[slot][offset]; + + *(u32*)&KeyY[slot][offset] = (old & ~mask) | (val & mask); + + if (offset >= 0xC) + { + DeriveNormalKey(slot); + } +} + +} diff --git a/src/DSi_AES.h b/src/DSi_AES.h index 028523a..7c388f5 100644 --- a/src/DSi_AES.h +++ b/src/DSi_AES.h @@ -19,6 +19,30 @@ #ifndef DSI_AES_H #define DSI_AES_H -// +#include "types.h" + +namespace DSi_AES +{ + +extern u32 Cnt; + +bool Init(); +void DeInit(); +void Reset(); + +u32 ReadCnt(); +void WriteCnt(u32 val); +void WriteBlkCnt(u32 val); + +u32 ReadOutputFIFO(); +void WriteInputFIFO(u32 val); + +void WriteIV(u32 offset, u32 val, u32 mask); +void WriteMAC(u32 offset, u32 val, u32 mask); +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); + +} #endif // DSI_AES_H diff --git a/src/DSi_NDMA.cpp b/src/DSi_NDMA.cpp index 7c0b2a1..aed78af 100644 --- a/src/DSi_NDMA.cpp +++ b/src/DSi_NDMA.cpp @@ -99,7 +99,8 @@ void DSi_NDMA::WriteCnt(u32 val) if ((StartMode & 0x1F) == 0x10) Start(); - if (StartMode != 0x10 && StartMode != 0x30) + if (StartMode != 0x10 && StartMode != 0x30 && + StartMode != 0x2B) printf("UNIMPLEMENTED ARM%d NDMA%d START MODE %02X, %08X->%08X\n", CPU?7:9, Num, StartMode, SrcAddr, DstAddr); } } @@ -223,16 +224,19 @@ void DSi_NDMA::Run9() } if ((StartMode & 0x1F) == 0x10) // CHECKME + { Cnt &= ~(1<<31); + if (Cnt & (1<<30)) NDS::SetIRQ(0, NDS::IRQ_DSi_NDMA0 + Num); + } else if (!(Cnt & (1<<29))) { if (TotalRemCount == 0) + { Cnt &= ~(1<<31); + if (Cnt & (1<<30)) NDS::SetIRQ(0, NDS::IRQ_DSi_NDMA0 + Num); + } } - if (Cnt & (1<<30)) - NDS::SetIRQ(0, NDS::IRQ_DSi_NDMA0 + Num); - Running = 0; InProgress = false; NDS::ResumeCPU(0, 1<<(Num+4)); @@ -305,16 +309,19 @@ void DSi_NDMA::Run7() } if ((StartMode & 0x1F) == 0x10) // CHECKME + { Cnt &= ~(1<<31); + if (Cnt & (1<<30)) NDS::SetIRQ(1, NDS::IRQ_DSi_NDMA0 + Num); + } else if (!(Cnt & (1<<29))) { if (TotalRemCount == 0) + { Cnt &= ~(1<<31); + if (Cnt & (1<<30)) NDS::SetIRQ(1, NDS::IRQ_DSi_NDMA0 + Num); + } } - if (Cnt & (1<<30)) - NDS::SetIRQ(1, NDS::IRQ_DSi_NDMA0 + Num); - Running = 0; InProgress = false; NDS::ResumeCPU(1, 1<<(Num+4)); diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index 42b515c..bb3c4a4 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -473,10 +473,10 @@ void DSi_MMCStorage::SendCMD(u8 cmd, u32 param) case 2: case 10: // get CID - Host->SendResponse(*(u32*)&CID[0], false); - Host->SendResponse(*(u32*)&CID[1], false); - Host->SendResponse(*(u32*)&CID[2], false); - Host->SendResponse(*(u32*)&CID[3], true); + Host->SendResponse(*(u32*)&CID[12], false); + Host->SendResponse(*(u32*)&CID[8], false); + Host->SendResponse(*(u32*)&CID[4], false); + Host->SendResponse(*(u32*)&CID[0], true); //if (cmd == 2) SetState(0x02); return; @@ -502,13 +502,18 @@ void DSi_MMCStorage::SendCMD(u8 cmd, u32 param) return; case 9: // get CSD - Host->SendResponse(*(u32*)&CSD[0], false); - Host->SendResponse(*(u32*)&CSD[1], false); - Host->SendResponse(*(u32*)&CSD[2], false); - Host->SendResponse(*(u32*)&CSD[3], true); + Host->SendResponse(*(u32*)&CSD[12], false); + Host->SendResponse(*(u32*)&CSD[8], false); + Host->SendResponse(*(u32*)&CSD[4], false); + Host->SendResponse(*(u32*)&CSD[0], true); return; case 12: // stop operation + // TODO + Host->SendResponse(CSR, true); + return; + + case 13: // get status Host->SendResponse(CSR, true); return; diff --git a/src/NDS.cpp b/src/NDS.cpp index e20f62f..7513d57 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1582,12 +1582,12 @@ void debug(u32 param) printf("ARM7 PC=%08X LR=%08X %08X\n", ARM7->R[15], ARM7->R[14], ARM7->R_IRQ[1]); printf("ARM9 IME=%08X IE=%08X IF=%08X\n", IME[0], IE[0], IF[0]); - printf("ARM7 IME=%08X IE=%08X IF=%08X\n", IME[1], IE[1], IF[1]); + printf("ARM7 IME=%08X IE=%08X IF=%08X IE2=%04X IF2=%04X\n", IME[1], IE[1], IF[1], IE2, IF2); //for (int i = 0; i < 9; i++) // printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]); - FILE* + /*FILE* shit = fopen("debug/card.bin", "wb"); for (u32 i = 0x02000000; i < 0x02400000; i+=4) { @@ -1599,7 +1599,7 @@ void debug(u32 param) u32 val = ARM7Read32(i); fwrite(&val, 4, 1, shit); } - fclose(shit); + fclose(shit);*/ } |