2015-05-12 11:15:16 +12:00
|
|
|
// Copyright 2014 Normmatt
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
2015-05-10 13:09:49 -07:00
|
|
|
#include "protocol.h"
|
|
|
|
|
2015-05-10 00:53:09 -07:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "common.h"
|
2015-05-10 13:09:49 -07:00
|
|
|
#include "aes.h"
|
2015-05-10 00:53:09 -07:00
|
|
|
#include "protocol_ctr.h"
|
|
|
|
#include "protocol_ntr.h"
|
2015-05-10 12:51:46 -07:00
|
|
|
#include "command_ctr.h"
|
|
|
|
#include "command_ntr.h"
|
2015-05-10 00:53:09 -07:00
|
|
|
#include "delay.h"
|
|
|
|
|
|
|
|
extern u8* bottomScreen;
|
|
|
|
|
|
|
|
int CartID = -1;
|
|
|
|
u32 CartType = 0;
|
|
|
|
int A0_Response = -1;
|
|
|
|
|
|
|
|
u32 rand1 = 0;
|
|
|
|
u32 rand2 = 0;
|
|
|
|
|
|
|
|
u32 BSWAP32(u32 val) {
|
|
|
|
return (((val >> 24) & 0xFF)) |
|
|
|
|
(((val >> 16) & 0xFF) << 8) |
|
|
|
|
(((val >> 8) & 0xFF) << 16) |
|
|
|
|
((val & 0xFF) << 24);
|
|
|
|
}
|
|
|
|
|
2015-05-10 01:22:47 -07:00
|
|
|
// TODO: Verify
|
|
|
|
void ResetCartSlot()
|
2015-05-10 00:53:09 -07:00
|
|
|
{
|
|
|
|
REG_CARDCONF2 = 0x0C;
|
|
|
|
REG_CARDCONF &= ~3;
|
|
|
|
|
2015-05-10 01:22:47 -07:00
|
|
|
if (REG_CARDCONF2 == 0xC) {
|
|
|
|
while (REG_CARDCONF2 != 0);
|
2015-05-10 00:53:09 -07:00
|
|
|
}
|
|
|
|
|
2015-05-10 01:22:47 -07:00
|
|
|
if (REG_CARDCONF2 != 0)
|
2015-05-10 00:53:09 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
REG_CARDCONF2 = 0x4;
|
|
|
|
while(REG_CARDCONF2 != 0x4);
|
|
|
|
|
|
|
|
REG_CARDCONF2 = 0x8;
|
|
|
|
while(REG_CARDCONF2 != 0x8);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SwitchToNTRCARD()
|
|
|
|
{
|
|
|
|
REG_NTRCARDROMCNT = 0x20000000;
|
|
|
|
REG_CARDCONF &= ~3;
|
|
|
|
REG_CARDCONF &= ~0x100;
|
|
|
|
REG_NTRCARDMCNT = NTRCARD_CR1_ENABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SwitchToCTRCARD()
|
|
|
|
{
|
|
|
|
REG_CTRCARDCNT = 0x10000000;
|
2015-05-10 12:51:46 -07:00
|
|
|
REG_CARDCONF = (REG_CARDCONF & ~3) | 2;
|
2015-05-10 00:53:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int Cart_IsInserted()
|
|
|
|
{
|
2015-05-10 12:51:46 -07:00
|
|
|
return (0x9000E2C2 == CTR_CmdGetSecureId(rand1, rand2) );
|
2015-05-10 00:53:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
u32 Cart_GetID()
|
|
|
|
{
|
|
|
|
return CartID;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cart_Init()
|
|
|
|
{
|
2015-05-10 01:22:47 -07:00
|
|
|
ResetCartSlot(); //Seems to reset the cart slot?
|
2015-05-10 00:53:09 -07:00
|
|
|
|
|
|
|
REG_CTRCARDSECCNT &= 0xFFFFFFFB;
|
|
|
|
ioDelay(0xF000);
|
|
|
|
|
|
|
|
SwitchToNTRCARD();
|
|
|
|
ioDelay(0xF000);
|
|
|
|
|
|
|
|
REG_NTRCARDROMCNT = 0;
|
2015-05-10 12:51:46 -07:00
|
|
|
REG_NTRCARDMCNT &= 0xFF;
|
2015-05-10 00:53:09 -07:00
|
|
|
ioDelay(167550);
|
2015-05-10 01:22:47 -07:00
|
|
|
|
2015-05-10 00:53:09 -07:00
|
|
|
REG_NTRCARDMCNT |= (NTRCARD_CR1_ENABLE | NTRCARD_CR1_IRQ);
|
|
|
|
REG_NTRCARDROMCNT = NTRCARD_nRESET | NTRCARD_SEC_SEED;
|
|
|
|
while (REG_NTRCARDROMCNT & NTRCARD_BUSY);
|
|
|
|
|
|
|
|
// Reset
|
2015-05-10 12:51:46 -07:00
|
|
|
NTR_CmdReset();
|
|
|
|
CartID = NTR_CmdGetCartId();
|
2015-05-10 00:53:09 -07:00
|
|
|
|
2015-05-10 01:22:47 -07:00
|
|
|
// 3ds
|
|
|
|
if (CartID & 0x10000000) {
|
2015-05-10 00:53:09 -07:00
|
|
|
u32 unknowna0_cmd[2] = { 0xA0000000, 0x00000000 };
|
|
|
|
NTR_SendCommand(unknowna0_cmd, 0x4, 0, &A0_Response);
|
|
|
|
|
2015-05-10 12:51:46 -07:00
|
|
|
NTR_CmdEnter16ByteMode();
|
2015-05-10 00:53:09 -07:00
|
|
|
SwitchToCTRCARD();
|
|
|
|
ioDelay(0xF000);
|
|
|
|
|
|
|
|
REG_CTRCARDBLKCNT = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//returns 1 if MAC valid otherwise 0
|
|
|
|
u8 card_aes(u32 *out, u32 *buff, size_t size) { // note size param ignored
|
|
|
|
u8 tmp = REG_AESKEYCNT;
|
|
|
|
REG_AESCNT |= 0x2800000;
|
|
|
|
REG_AESCTR[0] = buff[14];
|
|
|
|
REG_AESCTR[1] = buff[13];
|
|
|
|
REG_AESCTR[2] = buff[12];
|
|
|
|
REG_AESCNT |= 0x2800000;
|
|
|
|
REG_AESKEYCNT = (REG_AESKEYCNT & 0xC0) | 0x3B;
|
|
|
|
REG_AESKEYYFIFO = buff[0];
|
|
|
|
REG_AESKEYYFIFO = buff[1];
|
|
|
|
REG_AESKEYYFIFO = buff[2];
|
|
|
|
REG_AESKEYYFIFO = buff[3];
|
|
|
|
REG_AESKEYCNT = tmp;
|
|
|
|
REG_AESKEYSEL = 0x3B;
|
|
|
|
REG_AESCNT |= 0x4000000;
|
|
|
|
REG_AESCNT |= 0x2970000;
|
|
|
|
REG_AESMAC[0] = buff[11];
|
|
|
|
REG_AESMAC[1] = buff[10];
|
|
|
|
REG_AESMAC[2] = buff[9];
|
|
|
|
REG_AESMAC[3] = buff[8];
|
|
|
|
REG_AESBLKCNT = 0x10000;
|
|
|
|
REG_AESCNT = 0x83D70C00;
|
|
|
|
REG_AESWRFIFO = buff[4];
|
|
|
|
REG_AESWRFIFO = buff[5];
|
|
|
|
REG_AESWRFIFO = buff[6];
|
|
|
|
REG_AESWRFIFO = buff[7];
|
|
|
|
while (((REG_AESCNT >> 5) & 0x1F) <= 3);
|
|
|
|
out[0] = REG_AESRDFIFO;
|
|
|
|
out[1] = REG_AESRDFIFO;
|
|
|
|
out[2] = REG_AESRDFIFO;
|
|
|
|
out[3] = REG_AESRDFIFO;
|
|
|
|
return ((REG_AESCNT >> 21) & 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AES_SetKeyControl(u32 a) {
|
|
|
|
*((volatile u8*)0x10009011) = a | 0x80;
|
|
|
|
}
|
|
|
|
|
2015-05-10 12:51:46 -07:00
|
|
|
void Cart_Secure_Init(u32 *buf, u32 *out)
|
2015-05-10 00:53:09 -07:00
|
|
|
{
|
|
|
|
AES_SetKeyControl(0x3B);
|
|
|
|
|
|
|
|
u8 mac_valid = card_aes(out, buf, 0x200);
|
|
|
|
|
2015-05-10 01:22:47 -07:00
|
|
|
// if (!mac_valid)
|
2015-05-10 00:53:09 -07:00
|
|
|
// ClearScreen(bottomScreen, RGB(255, 0, 0));
|
|
|
|
|
|
|
|
ioDelay(0xF0000);
|
|
|
|
|
|
|
|
CTR_SetSecKey(A0_Response);
|
|
|
|
CTR_SetSecSeed(out, true);
|
|
|
|
|
|
|
|
rand1 = 0x42434445;//*((vu32*)0x10011000);
|
|
|
|
rand2 = 0x46474849;//*((vu32*)0x10011010);
|
|
|
|
|
2015-05-10 12:51:46 -07:00
|
|
|
CTR_CmdSeed(rand1, rand2);
|
2015-05-10 00:53:09 -07:00
|
|
|
|
|
|
|
out[3] = BSWAP32(rand2);
|
|
|
|
out[2] = BSWAP32(rand1);
|
|
|
|
CTR_SetSecSeed(out, false);
|
|
|
|
|
|
|
|
u32 test = 0;
|
2015-05-10 01:22:47 -07:00
|
|
|
const u32 A2_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 };
|
|
|
|
CTR_SendCommand(A2_cmd, 4, 1, 0x100822C, &test);
|
2015-05-10 00:53:09 -07:00
|
|
|
|
|
|
|
u32 test2 = 0;
|
2015-05-10 01:22:47 -07:00
|
|
|
const u32 A3_cmd[4] = { 0xA3000000, 0x00000000, rand1, rand2 };
|
|
|
|
CTR_SendCommand(A3_cmd, 4, 1, 0x100822C, &test2);
|
2015-05-10 00:53:09 -07:00
|
|
|
|
2015-05-10 01:22:47 -07:00
|
|
|
const u32 C5_cmd[4] = { 0xC5000000, 0x00000000, rand1, rand2 };
|
|
|
|
CTR_SendCommand(C5_cmd, 0, 1, 0x100822C, NULL);
|
2015-05-10 00:53:09 -07:00
|
|
|
|
2015-05-10 01:22:47 -07:00
|
|
|
CTR_SendCommand(A2_cmd, 4, 1, 0x100822C, &test);
|
|
|
|
CTR_SendCommand(A2_cmd, 4, 1, 0x100822C, &test);
|
|
|
|
CTR_SendCommand(A2_cmd, 4, 1, 0x100822C, &test);
|
|
|
|
CTR_SendCommand(A2_cmd, 4, 1, 0x100822C, &test);
|
|
|
|
CTR_SendCommand(A2_cmd, 4, 1, 0x100822C, &test);
|
2015-05-10 00:53:09 -07:00
|
|
|
}
|