285 lines
8.2 KiB
C
285 lines
8.2 KiB
C
#include "mxk.h"
|
|
|
|
unsigned int KEYCHIP_STATUS;
|
|
unsigned char KEYCHIP_ERROR;
|
|
|
|
static MXK_STATUS mxkPacketReqRandomBytes(unsigned char* packet) {
|
|
if (packet == NULL) return MXK_STATUS_INVALID_PARAM;
|
|
|
|
amtime_t now;
|
|
FILETIME filetime;
|
|
for (int i = 0; i < MXK_BLOCK_SIZE; i++) {
|
|
amiTimerGet(&now);
|
|
GetSystemTimeAsFileTime(&filetime);
|
|
packet[i] = (filetime.dwHighDateTime & 0xff) ^ (filetime.dwLowDateTime & 0xff) ^
|
|
(now.microseconds & 0xff);
|
|
}
|
|
return MXK_STATUS_OK;
|
|
}
|
|
|
|
MXK_STATUS mxkExchengeAesKey(void) {
|
|
unsigned char key_s[16];
|
|
unsigned char key_r[16];
|
|
unsigned char packet[16];
|
|
|
|
mxkPacketReqRandomBytes(key_s);
|
|
mxkPacketReqRandomBytes(key_r);
|
|
|
|
if (mxkPacketReqSetKeyS(packet) != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkPacketReqSetKeyS");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
if (mxkSendPacket(packet) != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkSendPacket Command KeyS");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
if (mxkSendPacket(key_s) != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkSendPacket KeyS");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
if (mxkRecvPacket(packet) != MXK_STATUS_OK || packet[0] != SetKeyS) {
|
|
amiDebugLog("Error mxkRecvPacket KeyS");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
mxkSetKeyS(key_s);
|
|
|
|
if (mxkPacketReqSetKeyR(packet) != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkPacketReqSetKeyR");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
if (mxkSendPacket(packet) != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkSendPacket Command SetKeyR");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
if (mxkSendPacket(key_r) != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkSendPacket KeyR");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
mxkSetKeyR(key_r);
|
|
if (mxkRecvPacket(packet) != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkRecvPacket KeyR");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
|
|
return MXK_STATUS_OK;
|
|
}
|
|
|
|
BOOL mxkVersionDirty;
|
|
unsigned short mxkVersionCache;
|
|
MXK_STATUS mxkVersion(unsigned short* version, MXK_CACHE cache, unsigned char* err) {
|
|
unsigned char packet[16];
|
|
|
|
if (version == NULL || err == NULL) return MXK_STATUS_INVALID_PARAM;
|
|
|
|
if (KEYCHIP_STATUS == 2) {
|
|
amiDebugLog("Error MXK_STATUS_ERROR!!");
|
|
*err = KEYCHIP_ERROR;
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
|
|
if (cache == MXK_CACHE_USE) {
|
|
if (!mxkVersionDirty) {
|
|
*version = mxkVersionCache;
|
|
return MXK_STATUS_OK;
|
|
}
|
|
} else {
|
|
mxkVersionDirty = true;
|
|
}
|
|
|
|
mxkPacketReqGetVersion(packet);
|
|
if (mxkSendPacket(packet) != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkSendPacket!!");
|
|
goto error;
|
|
}
|
|
if (mxkRecvPacket(packet) != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkRecvPacket!!");
|
|
goto error;
|
|
}
|
|
|
|
*version = mxkVersionCache = ((unsigned short*)packet)[0];
|
|
mxkVersionDirty = false;
|
|
return MXK_STATUS_OK;
|
|
|
|
error:
|
|
KEYCHIP_ERROR = 2;
|
|
KEYCHIP_STATUS = 2;
|
|
*err = 2;
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
|
|
BOOL mxkSetMainId(const unsigned char* main_id) {
|
|
unsigned char packet[16];
|
|
|
|
mxkPacketReqSetMainId(packet);
|
|
if (!mxkSendPacket(packet)) return FALSE;
|
|
if (!mxkSendPacket(main_id)) return FALSE;
|
|
|
|
mxkRecvPacket(packet);
|
|
|
|
return packet[0] != 0xff;
|
|
}
|
|
BOOL mxkGetMainId(unsigned char* main_id) {
|
|
unsigned char packet[16];
|
|
|
|
mxkPacketReqGetMainId(packet);
|
|
if (!mxkSendPacket(packet)) return FALSE;
|
|
if (!mxkRecvPacket(main_id)) return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
BOOL mxkGetKeyId(unsigned char* key_id) {
|
|
unsigned char packet[16];
|
|
|
|
mxkPacketReqGetKeyId(packet);
|
|
if (!mxkSendPacket(packet)) return FALSE;
|
|
if (!mxkRecvPacket(key_id)) return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL mxkGetPlayCounter(DWORD* play_counter) {
|
|
unsigned char packet[16];
|
|
|
|
mxkPacketReqGetPlayCounter(packet);
|
|
if (!mxkSendPacket(packet)) return FALSE;
|
|
if (!mxkRecvPacket(packet)) return FALSE;
|
|
|
|
*play_counter = ((DWORD*)packet)[0];
|
|
return TRUE;
|
|
}
|
|
BOOL mxkFlashRead(unsigned int address, unsigned int nbytes, unsigned char* buffer) {
|
|
unsigned char packet[16];
|
|
mxkPacketReqFlashRead(packet, address, nbytes);
|
|
if (!mxkSendPacket(packet)) return FALSE;
|
|
|
|
for (unsigned int i = 0; i < nbytes; i += 0x100) {
|
|
unsigned int rest = (nbytes - i) > 0x100 ? 0x100 : (nbytes - i);
|
|
if (!mxkTransportRecv(buffer + i, rest)) return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
BOOL mxkEepromRead(unsigned char page, unsigned char* data) {
|
|
unsigned char packet[16];
|
|
mxkPacketReqEepromRead(packet, page);
|
|
if (!mxkSendPacket(packet)) return FALSE;
|
|
if (!mxkRecvPacket(data)) return FALSE;
|
|
return TRUE;
|
|
}
|
|
BOOL mxkNvramRead(unsigned short addr, unsigned char blocks, unsigned char* data) {
|
|
unsigned char packet[16];
|
|
mxkPacketReqNvramRead(packet, addr, blocks);
|
|
if (!mxkSendPacket(packet)) return FALSE;
|
|
|
|
for (size_t i = 0; i < blocks; i++) {
|
|
if (!mxkRecvPacket(data + (i * 16))) return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool mxkValidString(const char* string, unsigned int length) {
|
|
for (unsigned int i = 0; i < length; i++) {
|
|
char c = string[i];
|
|
if (isalnum(c)) continue;
|
|
if (c != '.' && c != '_' && c != '-' && c != ':' && c != '@' && c != '%' && c != '/' &&
|
|
c != '\\')
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
MXK_STATUS mxkGetKeychipIdFromN2(void) {
|
|
N2KeychipId_t kcId;
|
|
|
|
memset(&kcId, 0, sizeof kcId);
|
|
int err = mxkN2CmdReadKeychipID(&kcId);
|
|
if (err != 0) {
|
|
amiDebugLog("Error: mxkN2CmdReadKeychipID().ErrorCode %d", err);
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
|
|
amiCrc32RInit();
|
|
uint32_t crcCalc = amiCrc32RCalc((sizeof kcId.m_AppBoot) - 4, (LPBYTE)&kcId.m_AppBoot + 4, 0);
|
|
if (crcCalc != kcId.m_AppBoot.m_Header.m_Crc) {
|
|
amiDebugLog("Error AppBootInfo CRC!!!");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
|
|
crcCalc = amiCrc32RCalc(sizeof kcId - 4, (LPBYTE)&kcId + 4, 0);
|
|
if (crcCalc != kcId.m_Crc) {
|
|
amiDebugLog("Error KeychipID CRC!!!");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
|
|
// N2 keychip ID is a smaller, more compact, format than normal appboot. Restructure it to match
|
|
// before committing it to memory!
|
|
unsigned char keyId[16];
|
|
AM_APPBOOT_256 appboot;
|
|
|
|
memcpy_s(keyId, sizeof keyId, kcId.m_KeyId, sizeof kcId.m_KeyId);
|
|
memcpy_s(&appboot, sizeof appboot, &kcId.m_AppBoot,
|
|
sizeof kcId.m_AppBoot - sizeof kcId.m_AppBoot.m_Seed);
|
|
memcpy_s(appboot.m_Seed, sizeof appboot.m_Seed, kcId.m_AppBoot.m_Seed,
|
|
sizeof kcId.m_AppBoot.m_Seed);
|
|
|
|
printf("Got N2 key ID: %.16s\n", keyId);
|
|
printf("Got N2 game ID: %.4s\n", kcId.m_AppBoot.m_Header.m_GameId);
|
|
|
|
// ...but we're not actually committing it to memory at the moment!
|
|
// memcpy_s(&APPBOOT, 256, &appboot, sizeof appboot);
|
|
// memcpy_s(N2_KEYID, 16, keyId, 16);
|
|
// DAT_004adc95 = 0;
|
|
// DAT_004adda4 = 0;
|
|
return MXK_STATUS_OK;
|
|
}
|
|
|
|
MXK_STATUS mxkInit(void) {
|
|
mxkVersionDirty = true;
|
|
AppBoot.m_cacheDirty = true;
|
|
|
|
if (mxkTransportInit() != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkTransportInit!!");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
if (mxkCryptInit() != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkCryptInit!!");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
if (mxkExchengeAesKey() != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkExchengeAesKey!!");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
if (mxkSmbusInit() != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkSmbusInit!!");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
// TODO: SSD
|
|
// mxkSsdInit();
|
|
if (mxkAuthenticationDs() != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkAuthenticationDs!!");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
if (mxkGetAppBootInfo() != MXK_STATUS_OK) {
|
|
amiDebugLog("Error mxkGetAppBootInfo!!");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
|
|
unsigned char system_flag;
|
|
unsigned char err;
|
|
if (mxkAbSystemFlag(MXK_CACHE_USE, &system_flag, &err) == MXK_STATUS_OK && system_flag & 1) {
|
|
// appboot_flash();
|
|
// eeprom_playcount();
|
|
}
|
|
|
|
if (mxkN2Init() != 0) {
|
|
amiDebugLog("Error mxkN2Init!!");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
|
|
if (mxkGetKeychipIdFromN2() != 0) {
|
|
amiDebugLog("Error mxkGetKeychipIdFromN2!!");
|
|
return MXK_STATUS_ERROR;
|
|
}
|
|
|
|
return MXK_STATUS_OK;
|
|
}
|