Lots of work on keychip communication
This commit is contained in:
parent
b88e279b32
commit
09bd2e4792
@ -115,6 +115,8 @@ BOOL smbus_ds28cn01_write(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) {
|
||||
memcpy(&MAC_INPUT_BUFFER[4], USER_EEPROM[page], DS28CN01_EEPROM_PAGE_SIZE);
|
||||
memcpy(&MAC_INPUT_BUFFER[36], &data[0], 4);
|
||||
MAC_INPUT_BUFFER[40] = 0x40 | page;
|
||||
// TODO: Where did I get that the unique number is factored in?
|
||||
// This seems like it would cause sums to calculate wrong!
|
||||
memcpy(&MAC_INPUT_BUFFER[41], UNIQUE_NUMBER, 7);
|
||||
memcpy(&MAC_INPUT_BUFFER[48], &SECRET[4], 4);
|
||||
memcpy(&MAC_INPUT_BUFFER[52], &data[4], 3);
|
||||
|
@ -13,8 +13,9 @@ LOG_FACILITY _lf = {
|
||||
};
|
||||
PLOG_FACILITY plf = &_lf;
|
||||
|
||||
#define N2_IO_BUFFER 0x1000
|
||||
#define N2_IO_BUFFER 512
|
||||
|
||||
BYTE n2_auth_level = 1;
|
||||
BYTE n2_in_buffer[N2_IO_BUFFER];
|
||||
WORD n2_in_pointer = 0;
|
||||
BYTE n2_out_buffer[N2_IO_BUFFER];
|
||||
@ -25,7 +26,7 @@ WORD n2_error_code = 0;
|
||||
BYTE n2_auth_key[20] = { 0x96, 0xed, 0x31, 0xb2, 0x28, 0x71, 0x05, 0xa5, 0xa3, 0x30,
|
||||
0x54, 0x0f, 0x25, 0xbe, 0xd8, 0x51, 0xa5, 0xc8, 0x36, 0x21 };
|
||||
|
||||
BYTE n2_session_nonce[20];
|
||||
BYTE n2_session_salt[20];
|
||||
struct {
|
||||
BYTE key[16];
|
||||
BYTE iv[16];
|
||||
@ -67,24 +68,26 @@ typedef struct {
|
||||
} N2_KEYCHIP_INFO, *PN2_KEYCHIP_INFO;
|
||||
#pragma pack(pop)
|
||||
|
||||
N2_KEYCHIP_INFO n2_keychip_info = { .m_KeyId = KEY_ID,
|
||||
.m_Appboot = {
|
||||
.m_Format = 1,
|
||||
.m_GameId = GAME_ID,
|
||||
.m_Region = 0xff,
|
||||
.m_ModelType = 2,
|
||||
.m_SystemFlag = 0x24,
|
||||
.m_PlatformId = HW_ID,
|
||||
.m_DvdFlag = 1,
|
||||
.m_NetworkAddr =
|
||||
(192 << 0) | (168 << 8) | (103 << 16) | (0 << 24),
|
||||
} };
|
||||
N2_KEYCHIP_INFO n2_keychip_info = {
|
||||
.m_KeyId = KEY_ID,
|
||||
.m_Appboot = {
|
||||
.m_Format = 1,
|
||||
.m_GameId = GAME_ID,
|
||||
.m_Region = 0xff,
|
||||
.m_ModelType = 2,
|
||||
.m_SystemFlag = 0x24,
|
||||
.m_PlatformId = HW_ID,
|
||||
.m_DvdFlag = 1,
|
||||
.m_NetworkAddr =
|
||||
(192 << 0) | (168 << 8) | (103 << 16) | (0 << 24),
|
||||
},
|
||||
};
|
||||
|
||||
WORD n2_enable_session(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 20;
|
||||
|
||||
RAND_bytes(n2_session_nonce, sizeof n2_session_nonce);
|
||||
memcpy(dataOut, n2_session_nonce, sizeof n2_session_nonce);
|
||||
RAND_bytes(n2_session_salt, sizeof n2_session_salt);
|
||||
memcpy(dataOut, n2_session_salt, sizeof n2_session_salt);
|
||||
|
||||
log_misc(plf, "Session open");
|
||||
return N2_SUCCESS;
|
||||
@ -97,6 +100,8 @@ WORD n2_set_auth_key(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut)
|
||||
mxkCryptDecryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataIn, pt, sizeof pt);
|
||||
memcpy(n2_auth_key, pt, sizeof n2_auth_key);
|
||||
|
||||
n2_auth_level = 2;
|
||||
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
WORD n2_set_enc_key(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
@ -108,11 +113,13 @@ WORD n2_set_enc_key(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut)
|
||||
memcpy(n2_enc_key.key, pt, sizeof n2_enc_key.key);
|
||||
memcpy(n2_enc_key.iv, pt + sizeof n2_enc_key.key, sizeof n2_enc_key.iv);
|
||||
|
||||
n2_auth_level = 3;
|
||||
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
WORD n2_get_auth_level(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 1;
|
||||
dataOut[0] = 3; // TODO: ?
|
||||
dataOut[0] = n2_auth_level;
|
||||
log_misc(plf, "Auth level get");
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
@ -241,6 +248,9 @@ void n2_install_commands() {
|
||||
}
|
||||
|
||||
void do_n2_command(WORD tag, WORD paramSize, WORD command, LPBYTE data) {
|
||||
EVP_MD_CTX* ctx;
|
||||
unsigned int outlen;
|
||||
|
||||
n2_install_commands();
|
||||
|
||||
log_info(plf, "Processing command: %04x/%04x (%d bytes)", tag, command, paramSize);
|
||||
@ -257,16 +267,50 @@ void do_n2_command(WORD tag, WORD paramSize, WORD command, LPBYTE data) {
|
||||
WORD expectedExtraData = N2_CHECKSUM_SIZE + N2_HEADER_SIZE;
|
||||
if (tag == N2_TAG_RQU_AUTH_COMMAND) expectedExtraData += N2_AUTH_SIZE;
|
||||
|
||||
n2_command handler = N2_COMMANDS[command & 0xff];
|
||||
if (handler.handler == NULL) {
|
||||
result = N2_BAD_ORDINAL;
|
||||
} else if (handler.tag != tag) {
|
||||
result = N2_BAD_TAG;
|
||||
} else if (handler.paramSize + expectedExtraData != paramSize) {
|
||||
result = N2_BAD_DATASIZE;
|
||||
unsigned char sha1sum[20];
|
||||
ctx = EVP_MD_CTX_create();
|
||||
EVP_DigestInit(ctx, EVP_sha1());
|
||||
EVP_DigestUpdate(ctx, n2_in_buffer, N2_HEADER_SIZE + paramSize - expectedExtraData);
|
||||
EVP_DigestFinal_ex(ctx, sha1sum, &outlen);
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
|
||||
HMAC_CTX hmac_ctx;
|
||||
if (tag == N2_TAG_RQU_COMMAND) {
|
||||
if (memcmp(sha1sum, n2_in_buffer + paramSize - N2_CHECKSUM_SIZE, N2_CHECKSUM_SIZE) != 0) {
|
||||
log_error(plf, "SHA1Sum chek failed!");
|
||||
result = N2_SUMFAIL;
|
||||
}
|
||||
} else {
|
||||
result = (*handler.handler)(paramSize, n2_in_buffer + N2_HEADER_SIZE,
|
||||
n2_out_buffer + N2_HEADER_SIZE, &bodyLength);
|
||||
unsigned char nonce[20];
|
||||
memcpy_s(nonce, 20, n2_in_buffer + paramSize - N2_CHECKSUM_SIZE - N2_AUTH_SIZE, 20);
|
||||
unsigned char hmac[20];
|
||||
|
||||
HMAC_CTX_init(&hmac_ctx);
|
||||
HMAC_Init_ex(&hmac_ctx, auth_key, sizeof auth_key, EVP_sha1(), NULL);
|
||||
HMAC_Update(&hmac_ctx, sha1sum, N2_CHECKSUM_SIZE);
|
||||
HMAC_Update(&hmac_ctx, n2_session_salt, N2_CHECKSUM_SIZE);
|
||||
HMAC_Update(&hmac_ctx, nonce, N2_CHECKSUM_SIZE);
|
||||
HMAC_Final(&hmac_ctx, hmac, &outlen);
|
||||
HMAC_CTX_cleanup(&hmac_ctx);
|
||||
|
||||
if (memcmp(hmac, n2_in_buffer + paramSize - N2_AUTH_SIZE, N2_AUTH_SIZE) != 0) {
|
||||
log_error(plf, "HMAC check failed!");
|
||||
result = N2_AUTHFAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == N2_SUCCESS) {
|
||||
n2_command handler = N2_COMMANDS[command & 0xff];
|
||||
if (handler.handler == NULL) {
|
||||
result = N2_BAD_ORDINAL;
|
||||
} else if (handler.tag != tag) {
|
||||
result = N2_BAD_TAG;
|
||||
} else if (handler.paramSize + expectedExtraData != paramSize) {
|
||||
result = N2_BAD_DATASIZE;
|
||||
} else {
|
||||
result = (*handler.handler)(paramSize, n2_in_buffer + N2_HEADER_SIZE,
|
||||
n2_out_buffer + N2_HEADER_SIZE, &bodyLength);
|
||||
}
|
||||
}
|
||||
|
||||
WORD paramSizeOut = bodyLength + expectedExtraData;
|
||||
@ -274,9 +318,6 @@ void do_n2_command(WORD tag, WORD paramSize, WORD command, LPBYTE data) {
|
||||
((PWORD)n2_out_buffer)[1] = fix_endian(paramSizeOut);
|
||||
((PWORD)n2_out_buffer)[2] = fix_endian(result);
|
||||
|
||||
EVP_MD_CTX* ctx;
|
||||
unsigned int outlen;
|
||||
|
||||
WORD fixed_command = fix_endian(command);
|
||||
|
||||
// Calculate a SHA1 of the packet, and append it
|
||||
@ -291,26 +332,16 @@ void do_n2_command(WORD tag, WORD paramSize, WORD command, LPBYTE data) {
|
||||
// At this point: packet = header | data | SHA(header | command | data)
|
||||
|
||||
if (tag == N2_TAG_RQU_AUTH_COMMAND) {
|
||||
BYTE crypto_buffer[N2_CHECKSUM_SIZE];
|
||||
|
||||
// Calculate a new SHA1 of the packet, including the SHA1 we just appeneded
|
||||
// crypto_buffer = SHA1(header | command | data)
|
||||
ctx = EVP_MD_CTX_create();
|
||||
EVP_DigestInit(ctx, EVP_sha1());
|
||||
EVP_DigestUpdate(ctx, n2_out_buffer, N2_HEADER_SIZE);
|
||||
EVP_DigestUpdate(ctx, &fixed_command, 2);
|
||||
EVP_DigestUpdate(ctx, n2_out_buffer + N2_HEADER_SIZE, bodyLength);
|
||||
EVP_DigestFinal_ex(ctx, crypto_buffer, &outlen);
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
// TODO: Further investigation might be needed here.
|
||||
// The following code checks out against mxkeychip, but repeating the
|
||||
// packet sum twice feels wrong.
|
||||
|
||||
// Calculate an HMAC, and append it
|
||||
HMAC_CTX hmac_ctx;
|
||||
HMAC_CTX_init(&hmac_ctx);
|
||||
HMAC_Init_ex(&hmac_ctx, auth_key, sizeof auth_key, EVP_sha1(), NULL);
|
||||
|
||||
// SHA1(header | command | data)
|
||||
HMAC_Update(&hmac_ctx, crypto_buffer, sizeof crypto_buffer);
|
||||
// SHA1(header | auth | data)
|
||||
HMAC_Update(&hmac_ctx, n2_out_buffer + N2_HEADER_SIZE + bodyLength, N2_CHECKSUM_SIZE);
|
||||
HMAC_Update(&hmac_ctx, n2_out_buffer + N2_HEADER_SIZE + bodyLength, N2_CHECKSUM_SIZE);
|
||||
// Request nonce
|
||||
HMAC_Update(&hmac_ctx, n2_in_buffer + paramSize - N2_AUTH_SIZE - N2_CHECKSUM_SIZE,
|
||||
@ -319,6 +350,10 @@ void do_n2_command(WORD tag, WORD paramSize, WORD command, LPBYTE data) {
|
||||
HMAC_Final(&hmac_ctx, n2_out_buffer + N2_HEADER_SIZE + bodyLength + N2_CHECKSUM_SIZE,
|
||||
&outlen);
|
||||
HMAC_CTX_cleanup(&hmac_ctx);
|
||||
|
||||
// Update session salt
|
||||
memcpy_s(n2_session_salt, sizeof n2_session_salt,
|
||||
n2_out_buffer + N2_HEADER_SIZE + bodyLength, N2_CHECKSUM_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,6 +411,7 @@ BOOL smbus_N2_write(ich9_cmd_t cmd, WORD code, BYTE nbytes, LPBYTE data) {
|
||||
}
|
||||
|
||||
BOOL smbus_N2_read(ich9_cmd_t cmd, WORD code, BYTE nbytes, BYTE* data) {
|
||||
// TODO: Unaligned mxk reads poke into this for the final byte!
|
||||
log_error(plf, "Unsupported read mode: %01x (%02x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
FARPROC (*TrueGetProcAddress)(HMODULE hModule, LPCSTR lpProcName);
|
||||
HMODULE (*TrueGetModuleHandleA)(LPCSTR lpModuleName);
|
||||
FARPROC(WINAPI* TrueGetProcAddress)(HMODULE hModule, LPCSTR lpProcName);
|
||||
HMODULE(WINAPI* TrueGetModuleHandleA)(LPCSTR lpModuleName);
|
||||
HMODULE(WINAPI* TrueLoadLibraryA)(LPCSTR lpLibFileName);
|
||||
HMODULE(WINAPI* TrueLoadLibraryW)(LPCWSTR lpLibFileName);
|
||||
|
||||
void hook_system();
|
||||
|
@ -8,6 +8,8 @@ shared_library(
|
||||
name_prefix: '',
|
||||
vs_module_defs: 'mice.def',
|
||||
sources: [
|
||||
'amvStub/amv.c',
|
||||
|
||||
'util/misc.c',
|
||||
'util/hook.c',
|
||||
'util/path.c',
|
||||
|
@ -9,7 +9,9 @@
|
||||
bool debug_wait = false;
|
||||
int boot_delay = 0;
|
||||
char exe_name[MAX_PATH + 1] = "";
|
||||
char commandline[MAX_PATH + 1] = "";
|
||||
|
||||
size_t nCommandLine = 256;
|
||||
char* commandLine = NULL;
|
||||
|
||||
static void print_help(char* exe) {
|
||||
log_info(plfBoot, "Usage: %s [-h] [-t] [-b executable.exe] [-d]", exe);
|
||||
@ -69,10 +71,13 @@ static bool parse_cmdline(int argc, char* argv[]) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (commandline[0] == 0)
|
||||
snprintf(commandline, sizeof commandline, "%s", argv[i]);
|
||||
else
|
||||
snprintf(commandline, sizeof commandline, "%s %s", commandline, argv[i]);
|
||||
size_t newLength = nCommandLine + 1 + strlen(argv[i]) + 1;
|
||||
if (newLength > nCommandLine) {
|
||||
nCommandLine = newLength;
|
||||
commandLine = realloc(commandLine, nCommandLine);
|
||||
}
|
||||
strcat_s(commandLine, nCommandLine, " ");
|
||||
strcat_s(commandLine, nCommandLine, argv[i]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -176,6 +181,13 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
log_info(plfBoot, "Micetools version: %s", MICE_VERSION);
|
||||
|
||||
commandLine = malloc(nCommandLine);
|
||||
if (commandLine == NULL) {
|
||||
log_error(plfBoot, "Fatal: Failed to malloc(commandLine)");
|
||||
return terminate(-1);
|
||||
}
|
||||
commandLine[0] = '\0';
|
||||
|
||||
CHAR workDir[MAX_PATH + 1];
|
||||
GetCurrentDirectory(MAX_PATH, workDir);
|
||||
log_info(plfBoot, "Current directory: %s", workDir);
|
||||
@ -203,7 +215,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
spawn_pcp_processes();
|
||||
|
||||
log_info(plfBoot, "exec: %s %s", exe_name, commandline);
|
||||
log_info(plfBoot, "exec: %s %s", exe_name, commandLine);
|
||||
|
||||
char micepath[MAX_PATH + 1];
|
||||
if (!locate_library(micepath, MAX_PATH + 1)) {
|
||||
@ -216,18 +228,30 @@ int main(int argc, char* argv[]) {
|
||||
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
||||
SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &info, sizeof info);
|
||||
|
||||
size_t nFullCommandLine = nCommandLine + strlen(exe_name) + 1;
|
||||
char* fullCommandLine = malloc(nFullCommandLine);
|
||||
snprintf(fullCommandLine, nFullCommandLine, "%s %s", exe_name, commandLine);
|
||||
free(commandLine);
|
||||
|
||||
char* extra_injections = MiceConfig.launcher.inject;
|
||||
PROCESS_INFORMATION pi;
|
||||
if (!start_and_inject(hJob, exe_name, commandline, micepath, debug_wait, boot_delay,
|
||||
extra_injections, 0, &pi))
|
||||
if (!start_and_inject(hJob, exe_name, fullCommandLine, micepath, debug_wait, boot_delay,
|
||||
extra_injections, 0, &pi)) {
|
||||
free(fullCommandLine);
|
||||
return terminate(-1);
|
||||
}
|
||||
free(fullCommandLine);
|
||||
|
||||
SetConsoleCtrlHandler(MiceHandlerRoutine, TRUE);
|
||||
|
||||
if (FAILED(WaitForSingleObject(pi.hProcess, INFINITE))) {
|
||||
log_error(plfBoot, "Fatal: WaitForSingleObject failed: %03x", GetLastError());
|
||||
} else {
|
||||
log_info(plfBoot, "Shutting down");
|
||||
DWORD exitCode;
|
||||
if (GetExitCodeProcess(pi.hProcess, &exitCode))
|
||||
log_info(plfBoot, "Shutting down (ret:%d)", exitCode);
|
||||
else
|
||||
log_info(plfBoot, "Shutting down (failed to get exit code)");
|
||||
CloseHandle(pi.hProcess);
|
||||
}
|
||||
return terminate(0);
|
||||
|
@ -4,9 +4,9 @@
|
||||
|
||||
AM_LIB_C_HEADER(amiCrc, AMI_CRC)
|
||||
|
||||
void amiCrc32RCreateTable(unsigned int *table) {
|
||||
void amiCrc32RCreateTable(uint32_t *table) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
unsigned int value = (~i & 1) - 1 & CRC32_POLYNOMIAL;
|
||||
uint32_t value = (~i & 1) - 1 & CRC32_POLYNOMIAL;
|
||||
value = ((i >> 1 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
value = ((i >> 2 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
value = ((i >> 3 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
@ -18,13 +18,12 @@ void amiCrc32RCreateTable(unsigned int *table) {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int amiCrc32RGet(unsigned int *table, int length, unsigned char *data,
|
||||
unsigned int initial) {
|
||||
unsigned int value = ~initial;
|
||||
uint32_t amiCrc32RGet(uint32_t *table, int length, void *data, uint32_t initial) {
|
||||
uint32_t value = ~initial;
|
||||
while (length > 0) {
|
||||
value = value >> 8 ^ table[(data[0] ^ value) & 0xff];
|
||||
value = value >> 8 ^ table[(((unsigned char *)data)[0] ^ value) & 0xff];
|
||||
length += -1;
|
||||
data++;
|
||||
((unsigned char *)data)++;
|
||||
}
|
||||
return ~value;
|
||||
}
|
||||
|
@ -1,19 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../_am.h"
|
||||
|
||||
AM_LIB_H_HEADER(amiCrc, AMI_CRC)
|
||||
|
||||
typedef struct _AMI_CRC {
|
||||
unsigned int m_init;
|
||||
unsigned int m_table[256];
|
||||
uint32_t m_init;
|
||||
uint32_t m_table[256];
|
||||
} AMI_CRC;
|
||||
|
||||
void amiCrc32RCreateTable(unsigned int *table);
|
||||
unsigned int amiCrc32RGet(unsigned int *table, int length, unsigned char *data,
|
||||
unsigned int initial);
|
||||
void amiCrc32RCreateTable(uint32_t *table);
|
||||
uint32_t amiCrc32RGet(uint32_t *table, int length, void *data, uint32_t initial);
|
||||
|
||||
#define amiCrc32RInit() \
|
||||
#define amiCrc32RInit() \
|
||||
do { \
|
||||
if (!amiCrc.m_init) { \
|
||||
amiCrc32RCreateTable(amiCrc.m_table); \
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
BOOL start_and_inject(HANDLE hJob, LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL debug_wait,
|
||||
DWORD delay, LPCSTR extra_injections, DWORD flags, LPPROCESS_INFORMATION lpProcessInformation);
|
||||
DWORD delay, LPCSTR extra_injections, DWORD flags,
|
||||
LPPROCESS_INFORMATION lpProcessInformation);
|
||||
|
||||
#define MICELIB "mice.dll"
|
||||
|
@ -177,7 +177,7 @@ BOOL mxkNvramRead(unsigned short addr, unsigned char blocks, unsigned char* data
|
||||
}
|
||||
|
||||
bool mxkValidString(const char* string, unsigned int length) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
for (unsigned int i = 0; i < length; i++) {
|
||||
char c = string[i];
|
||||
if (isalnum(c)) continue;
|
||||
if (c != '.' && c != '_' && c != '-' && c != ':' && c != '@' && c != '%' && c != '/' &&
|
||||
@ -187,7 +187,52 @@ bool mxkValidString(const char* string, unsigned int length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
MXK_STATUS mxkInit() {
|
||||
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_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];
|
||||
appboot_t 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.seed, sizeof appboot.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_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;
|
||||
|
||||
@ -203,7 +248,6 @@ MXK_STATUS mxkInit() {
|
||||
amiDebugLog("Error mxkExchengeAesKey!!");
|
||||
return MXK_STATUS_ERROR;
|
||||
}
|
||||
// TODO: N2
|
||||
if (mxkSmbusInit() != MXK_STATUS_OK) {
|
||||
amiDebugLog("Error mxkSmbusInit!!");
|
||||
return MXK_STATUS_ERROR;
|
||||
@ -226,9 +270,15 @@ MXK_STATUS mxkInit() {
|
||||
// eeprom_playcount();
|
||||
}
|
||||
|
||||
// TODO:
|
||||
mxkN2CmdSetDeviceInfo();
|
||||
mxkN2Authentication();
|
||||
if (mxkN2Init() != 0) {
|
||||
amiDebugLog("Error mxkN2Init!!");
|
||||
return MXK_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (mxkGetKeychipIdFromN2() != 0) {
|
||||
amiDebugLog("Error mxkGetKeychipIdFromN2!!");
|
||||
return MXK_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return MXK_STATUS_OK;
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "mxkCrypt.h"
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/pem.h>
|
||||
|
||||
// These three should be initialised to null, and populated by mxkCryptInit, but we already know
|
||||
// their values and aren't trying to hide them from anyone! mxkCryptInit is still fully implemented,
|
||||
@ -153,8 +153,8 @@ void mxkSwapKeys() {
|
||||
memcpy(KEY_S, temp, 16);
|
||||
}
|
||||
|
||||
MXK_STATUS mxkCryptEncryptAes128CBC(const unsigned char* key, const unsigned char* iv,
|
||||
unsigned char* ct, const unsigned char* pt, size_t nbytes) {
|
||||
MXK_STATUS mxkCryptEncryptAes128CBC(const unsigned char* key, const unsigned char* iv, void* ct,
|
||||
const void* pt, size_t nbytes) {
|
||||
if (key == NULL || iv == NULL || ct == NULL || pt == NULL) {
|
||||
amiDebugLog("Error: Invalid param.");
|
||||
return MXK_STATUS_INVALID_PARAM;
|
||||
@ -173,7 +173,7 @@ MXK_STATUS mxkCryptEncryptAes128CBC(const unsigned char* key, const unsigned cha
|
||||
}
|
||||
|
||||
MXK_STATUS mxkCryptDecryptAes128CBC(const unsigned char* key, const unsigned char* iv,
|
||||
const unsigned char* ct, unsigned char* pt, size_t nbytes) {
|
||||
const void* ct, void* pt, size_t nbytes) {
|
||||
if (key == NULL || iv == NULL || ct == NULL || pt == NULL) {
|
||||
amiDebugLog("Error: Invalid param.");
|
||||
return MXK_STATUS_INVALID_PARAM;
|
||||
|
@ -4,23 +4,34 @@
|
||||
#include "../ami/ami.h"
|
||||
#include "mxkDefs.h"
|
||||
|
||||
#define SHA1_SUM_SIZE 20
|
||||
#define HMAC_SUM_SIZE 20
|
||||
#define HMAC_KEY_SIZE 20
|
||||
|
||||
typedef char Sha1Sum_t[SHA1_SUM_SIZE];
|
||||
typedef char (*PSha1Sum_t)[SHA1_SUM_SIZE];
|
||||
typedef char HmacSum_t[HMAC_SUM_SIZE];
|
||||
typedef char (*PHmacSum_t)[HMAC_SUM_SIZE];
|
||||
typedef char HmacKey_t[HMAC_SUM_SIZE];
|
||||
typedef char (*PHmacKey_t)[HMAC_SUM_SIZE];
|
||||
|
||||
void mxkSetKeyS(unsigned char* key_s);
|
||||
void mxkSetKeyR(unsigned char* key_r);
|
||||
void mxkSwapKeys();
|
||||
|
||||
MXK_STATUS mxkCryptInit(void);
|
||||
|
||||
int mxkCryptCalcHashWithHmacSha1(void* key, unsigned char* md, size_t* nbuffer,
|
||||
int mxkCryptCalcHashWithHmacSha1(PHmacKey_t key, PHmacSum_t md, size_t* nbuffer,
|
||||
unsigned char* buffer, size_t nin);
|
||||
void mxkCryptCalcHashWithSha1(unsigned char* data, size_t nbytes, unsigned char* sum);
|
||||
void mxkCryptCalcHashWithSha1(unsigned char* data, size_t nbytes, PSha1Sum_t sum);
|
||||
|
||||
void mxkCryptCreateDigest(void);
|
||||
void mxkCryptRsaSignVerify(void);
|
||||
|
||||
MXK_STATUS mxkCryptDecryptAes128CBC(const unsigned char* key, const unsigned char* iv,
|
||||
const unsigned char* ct, unsigned char* pt, size_t nbytes);
|
||||
MXK_STATUS mxkCryptEncryptAes128CBC(const unsigned char* key, const unsigned char* iv,
|
||||
unsigned char* pt, const unsigned char* ct, size_t nbytes);
|
||||
const void* ct, void* pt, size_t nbytes);
|
||||
MXK_STATUS mxkCryptEncryptAes128CBC(const unsigned char* key, const unsigned char* iv, void* ct,
|
||||
const void* pt, size_t nbytes);
|
||||
|
||||
MXK_STATUS mxkCryptDecryptData(const unsigned char* ct, unsigned char* pt);
|
||||
MXK_STATUS mxkCryptEncryptData(unsigned char* ct, const unsigned char* pt);
|
||||
|
@ -57,7 +57,7 @@ int mxkDsKeychipComputeMac(unsigned char page, void *challenge, unsigned char *m
|
||||
Sleep(16);
|
||||
status = mxkDsWaitNotBusy(&INT_004ab34c);
|
||||
if (status == 0) {
|
||||
if (!mxkSmbusI2CReadBlock(KC_DS_ADDRESS, DS28CN01_REG_MAC, mac, 20)) {
|
||||
if (mxkSmbusI2CReadBlock(KC_DS_ADDRESS, DS28CN01_REG_MAC, mac, 20) != 0) {
|
||||
amiDebugLog("Error mxkSmbusI2CReadBlock()!!!");
|
||||
error = -8;
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
#include "mxkN2.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
@ -7,30 +9,47 @@
|
||||
#include "mxkCrypt.h"
|
||||
#include "mxkSmbus.h"
|
||||
|
||||
#define N2_ADDR 0x30
|
||||
|
||||
typedef struct {
|
||||
unsigned char m_Key[16];
|
||||
unsigned char m_IV[16];
|
||||
} AESKey_t;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
unsigned short m_Tag;
|
||||
unsigned short m_ParamSize;
|
||||
unsigned short m_Command;
|
||||
unsigned char m_Body[506];
|
||||
unsigned char m_Body[N2_DATA_MAX];
|
||||
} N2Packet_t;
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
Sha1Sum_t m_ShaSum;
|
||||
} rqu;
|
||||
struct {
|
||||
N2Nonce_t m_Nonce;
|
||||
HmacSum_t m_Hmac;
|
||||
} sign;
|
||||
};
|
||||
} N2PacketFooter_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
BOOL MXK_HAS_INIT = FALSE;
|
||||
BOOL MXK_N2_INIT = FALSE;
|
||||
#define CheckN2Init \
|
||||
do { \
|
||||
if (!MXK_N2_INIT) { \
|
||||
amiDebugLog("Error: Uninitialized."); \
|
||||
return -3; \
|
||||
} \
|
||||
} while (0);
|
||||
typedef struct {
|
||||
unsigned char m_Addr;
|
||||
unsigned char m_HmacKey[20];
|
||||
HmacKey_t m_HmacKey;
|
||||
AESKey_t m_AESKey;
|
||||
unsigned char m_AuthKey[20];
|
||||
unsigned char m_EncKey[16];
|
||||
unsigned char Unk[16];
|
||||
unsigned char m_HmacOut[20];
|
||||
N2AuthKey_t m_AuthKey;
|
||||
AESKey_t m_EncKey;
|
||||
HmacSum_t m_HmacSalt;
|
||||
} N2DeviceInfo_t;
|
||||
N2DeviceInfo_t N2DeviceInfo;
|
||||
|
||||
@ -41,14 +60,16 @@ unsigned char N2_KEY_HMAC[2][20] = {
|
||||
0x1d, 0x1e, 0x1f, 0x11, 0xee, 0xb0, 0xf4, 0xd4, 0x20, 0x24 }
|
||||
};
|
||||
|
||||
AESKey_t N2_KEY_AES[2] = { { { 0xd7, 0xf6, 0x86, 0xfb, 0x63, 0x44, 0xff, 0xa5, 0x60, 0x9d, 0x4e,
|
||||
0xf0, 0x18, 0xe9, 0x45, 0xb4 },
|
||||
{ 0x12, 0x6c, 0xb1, 0xdb, 0x9e, 0x00, 0x8c, 0xc6, 0xae, 0xa1, 0x73,
|
||||
0xec, 0xe7, 0x2f, 0x5a, 0xc4 } },
|
||||
{ { 0xa1, 0x1a, 0xc4, 0x4d, 0xcd, 0x48, 0x4f, 0xed, 0x70, 0xcc, 0x3f,
|
||||
0x5d, 0x94, 0x5b, 0xbe, 0xb3 },
|
||||
{ 0x9c, 0x5c, 0xba, 0x7f, 0xb0, 0x15, 0xc7, 0x69, 0xcb, 0xb4, 0x41,
|
||||
0x19, 0x97, 0x2b, 0x45, 0x9f } } };
|
||||
AESKey_t N2_KEY_AES[2] = {
|
||||
{ { 0xd7, 0xf6, 0x86, 0xfb, 0x63, 0x44, 0xff, 0xa5, 0x60, 0x9d, 0x4e, 0xf0, 0x18, 0xe9, 0x45,
|
||||
0xb4 },
|
||||
{ 0x12, 0x6c, 0xb1, 0xdb, 0x9e, 0x00, 0x8c, 0xc6, 0xae, 0xa1, 0x73, 0xec, 0xe7, 0x2f, 0x5a,
|
||||
0xc4 } },
|
||||
{ { 0xa1, 0x1a, 0xc4, 0x4d, 0xcd, 0x48, 0x4f, 0xed, 0x70, 0xcc, 0x3f, 0x5d, 0x94, 0x5b, 0xbe,
|
||||
0xb3 },
|
||||
{ 0x9c, 0x5c, 0xba, 0x7f, 0xb0, 0x15, 0xc7, 0x69, 0xcb, 0xb4, 0x41, 0x19, 0x97, 0x2b, 0x45,
|
||||
0x9f } },
|
||||
};
|
||||
|
||||
int mxkN2CmdInit(void) {
|
||||
if (MXK_N2_INIT) {
|
||||
@ -65,7 +86,7 @@ int mxkN2CmdSetDeviceInfo(void) {
|
||||
|
||||
if (mxkN2CmdInit() != 0) return -5;
|
||||
|
||||
unsigned char hmacKey[20];
|
||||
HmacKey_t hmacKey;
|
||||
AESKey_t aesKey;
|
||||
for (int i = 0; i < sizeof hmacKey; i++) hmacKey[i] = N2_KEY_HMAC[0][i] ^ N2_KEY_HMAC[1][i];
|
||||
for (int i = 0; i < sizeof aesKey.m_Key; i++)
|
||||
@ -88,17 +109,18 @@ int mxkN2CmdSetDeviceInfo(void) {
|
||||
}
|
||||
|
||||
// TODO: Better name
|
||||
void _randomBytes(unsigned char *buf, int nbytes) {
|
||||
void _randomBytes(void *buf, int nbytes) {
|
||||
FILETIME fileTime;
|
||||
amtime_t amTime;
|
||||
|
||||
for (int i = 0; i < nbytes; i++) {
|
||||
amiTimerGet(&amTime);
|
||||
GetSystemTimeAsFileTime(&fileTime);
|
||||
buf[i] = (amTime.microseconds ^ fileTime.dwLowDateTime ^ fileTime.dwHighDateTime) & 0xff;
|
||||
((unsigned char *)buf)[i] =
|
||||
(amTime.microseconds ^ fileTime.dwLowDateTime ^ fileTime.dwHighDateTime) & 0xff;
|
||||
}
|
||||
}
|
||||
void mxkN2GetPacketNonce(unsigned char *nonce) { _randomBytes(nonce, 20); }
|
||||
void mxkN2GetPacketNonce(PN2Nonce_t nonce) { _randomBytes(nonce, 20); }
|
||||
|
||||
int mxkN2UtilVCatenateData(unsigned char *out, size_t *count, unsigned int numStreams,
|
||||
va_list args) {
|
||||
@ -110,10 +132,11 @@ int mxkN2UtilVCatenateData(unsigned char *out, size_t *count, unsigned int numSt
|
||||
size_t offset = 0;
|
||||
size_t max = *count;
|
||||
for (size_t i = 0; i < numStreams && i < max; i++) {
|
||||
size_t n = va_arg(args, size_t);
|
||||
unsigned char *b = va_arg(args, unsigned char *);
|
||||
if (i + n > max) n = max - i;
|
||||
memcpy(out + offset, b, i);
|
||||
size_t n = va_arg(args, size_t);
|
||||
if (offset + n > max) n = max - offset;
|
||||
memcpy(out + offset, b, n);
|
||||
offset += n;
|
||||
}
|
||||
|
||||
*count = offset;
|
||||
@ -129,46 +152,49 @@ void mxkN2UtilCatenateData(unsigned char *concatinated, size_t *count, unsigned
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void mxkN2UtilSha1Many(unsigned char *sum, int numStreams, ...) {
|
||||
void mxkN2UtilSha1Many(PSha1Sum_t sum, int numStreams, ...) {
|
||||
va_list args;
|
||||
va_start(args, numStreams);
|
||||
|
||||
unsigned char sumout[20];
|
||||
Sha1Sum_t sumout;
|
||||
unsigned char concatinated[0x200];
|
||||
size_t size = sizeof concatinated;
|
||||
|
||||
mxkN2UtilVCatenateData(concatinated, &size, numStreams, args);
|
||||
mxkCryptCalcHashWithSha1(concatinated, size, sumout);
|
||||
memcpy_s(sum, 20, sumout, 20);
|
||||
mxkCryptCalcHashWithSha1(concatinated, size, &sumout);
|
||||
memcpy_s(sum, sizeof *sum, sumout, sizeof sumout);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
int mxkN2UtilHmacPacket(void *val1, unsigned char *sha1, void *nonce, void *key,
|
||||
unsigned char *hash_out) {
|
||||
unsigned char hash[20];
|
||||
unsigned char data_in[60];
|
||||
int mxkN2UtilHmacPacket(PSha1Sum_t packetSha, PHmacSum_t hmacSalt, PN2Nonce_t nonce, PHmacKey_t key,
|
||||
PHmacSum_t computedHash) {
|
||||
HmacSum_t hash;
|
||||
unsigned char data_in[sizeof *packetSha + sizeof *hmacSalt + sizeof *nonce];
|
||||
|
||||
size_t count = 60;
|
||||
size_t nout = 20;
|
||||
mxkN2UtilCatenateData(data_in, &count, 3, val1, 20, sha1, 20, nonce, 20);
|
||||
size_t count = sizeof *packetSha + sizeof *hmacSalt + sizeof *nonce;
|
||||
size_t nout = HMAC_SUM_SIZE;
|
||||
mxkN2UtilCatenateData(data_in, &count, 3, packetSha, sizeof *packetSha, hmacSalt,
|
||||
sizeof *hmacSalt, nonce, sizeof *nonce);
|
||||
|
||||
int iVar1 = mxkCryptCalcHashWithHmacSha1(key, hash, &nout, data_in, count);
|
||||
if (iVar1 != -2 && nout == 20) {
|
||||
memcpy(hash_out, hash, 20);
|
||||
return 0;
|
||||
}
|
||||
return -2;
|
||||
int err = mxkCryptCalcHashWithHmacSha1(key, &hash, &nout, data_in, count);
|
||||
if (err == -2 || nout != HMAC_SUM_SIZE) return -2;
|
||||
|
||||
memcpy_s(computedHash, sizeof *computedHash, hash, HMAC_SUM_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mxkN2CmdWriteData(unsigned char addr, unsigned char *data, unsigned short nbytes,
|
||||
int mxkN2CmdWriteData(unsigned char addr, void *data, unsigned short nbytes,
|
||||
unsigned short *nbytesOut) {
|
||||
unsigned int ptr_;
|
||||
unsigned char nstep;
|
||||
int status;
|
||||
unsigned short position;
|
||||
|
||||
if (mxkSmbusRequestMutex() != 0) return -6;
|
||||
if (mxkSmbusRequestMutex() != 0) {
|
||||
amiDebugLog("Error: mxkSmbusRequestMutex");
|
||||
return -6;
|
||||
}
|
||||
|
||||
status = 0;
|
||||
position = 0;
|
||||
@ -178,14 +204,14 @@ int mxkN2CmdWriteData(unsigned char addr, unsigned char *data, unsigned short nb
|
||||
if ((int)(nbytes - ptr_) < 5) {
|
||||
nstep = (byte)(nbytes - ptr_);
|
||||
if (nstep != 1) goto LAB_0040ae51;
|
||||
status = mxkSmbusWriteByte(addr, 0xcc, data[ptr_]);
|
||||
status = mxkSmbusWriteByte(addr, 0xcc, ((unsigned char *)data)[ptr_]);
|
||||
} else {
|
||||
nstep = 4;
|
||||
LAB_0040ae51:
|
||||
status = mxkSmbusI2CWriteBlock(addr, 0xcc, data + ptr_, nstep);
|
||||
status = mxkSmbusI2CWriteBlock(addr, 0xcc, &((unsigned char *)data)[ptr_], nstep);
|
||||
}
|
||||
if (status != 0) {
|
||||
amiDebugLog("Error: Data write failed. Position %d. ErrorCode %d.\n", position,
|
||||
amiDebugLog("Error: Data write failed. Position %d. ErrorCode %d.", position,
|
||||
status);
|
||||
|
||||
break;
|
||||
@ -196,118 +222,410 @@ int mxkN2CmdWriteData(unsigned char addr, unsigned char *data, unsigned short nb
|
||||
}
|
||||
*nbytesOut = position;
|
||||
|
||||
if (!mxkSmbusReleaseMutex()) return -6;
|
||||
if (mxkSmbusReleaseMutex() != 0) {
|
||||
amiDebugLog("Error: mxkSmbusReleaseMutex");
|
||||
return -6;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mxkN2CmdWriteCommand(unsigned char *param_1, unsigned char *packet, unsigned short tag,
|
||||
unsigned short command, unsigned char *auth_key, unsigned char addr,
|
||||
void *data, size_t nbytes) {
|
||||
int iVar1;
|
||||
unsigned short real_tag;
|
||||
unsigned short paramsize;
|
||||
|
||||
N2Packet_t cmd;
|
||||
int mxkN2CmdWriteCommand(PN2Nonce_t requestNonce, PHmacSum_t hmacSalt, N2Tag_t tag,
|
||||
N2Command_t command, PHmacKey_t hmacKey, unsigned char addr,
|
||||
N2Byte_t *data, unsigned short nbytes) {
|
||||
Sha1Sum_t sha1sum;
|
||||
N2Packet_t packet;
|
||||
int ret;
|
||||
|
||||
if (data == NULL && nbytes != 0) return -2;
|
||||
|
||||
memset(&cmd, 0, 0x200);
|
||||
paramsize = (tag == N2_TAG_RQU_COMMAND ? 20 : 0) + 0x14 + (nbytes & 0xffff) + 6;
|
||||
real_tag = (tag != N2_TAG_RQU_COMMAND) + 0xc1;
|
||||
cmd.m_Tag = real_tag * 0x100 | real_tag >> 8;
|
||||
cmd.m_ParamSize = (unsigned short)paramsize << 8 | (unsigned short)paramsize >> 8;
|
||||
cmd.m_Command = command << 8 | command >> 8;
|
||||
if (data != NULL) memcpy_s(cmd.m_Body, sizeof cmd.m_Body, data, nbytes);
|
||||
N2PacketFooter_t *footer = (N2PacketFooter_t *)(packet.m_Body + nbytes);
|
||||
|
||||
// SHA1(header | data)
|
||||
unsigned char packet_sha[20];
|
||||
mxkN2UtilSha1Many(packet_sha, 1, &cmd, nbytes + 6);
|
||||
ZeroMemory(&packet, sizeof packet);
|
||||
unsigned short paramsize =
|
||||
N2_HEADER_SIZE + nbytes +
|
||||
(tag == N2_TAG_RQU_COMMAND ? N2_FOOTER_RQU_SIZE : N2_FOOTER_SIGN_SIZE);
|
||||
|
||||
N2Tag_t realTag = tag == N2_TAG_RQU_COMMAND ? N2_TAG_RQU_COMMAND : N2_TAG_RQU_AUTH_COMMAND;
|
||||
packet.m_Tag = _byteswap_ushort(realTag);
|
||||
packet.m_ParamSize = _byteswap_ushort(paramsize);
|
||||
packet.m_Command = _byteswap_ushort(command);
|
||||
|
||||
if (data != NULL) memcpy_s(packet.m_Body, sizeof packet.m_Body, data, nbytes);
|
||||
|
||||
mxkN2UtilSha1Many(&sha1sum, 1, &packet, nbytes + N2_HEADER_SIZE);
|
||||
|
||||
if (tag == N2_TAG_RQU_COMMAND) {
|
||||
memcpy(cmd.m_Body, packet_sha, 20);
|
||||
memcpy_s(footer->rqu.m_ShaSum, sizeof footer->rqu.m_ShaSum, sha1sum, sizeof sha1sum);
|
||||
} else {
|
||||
unsigned char nonce[20];
|
||||
mxkN2GetPacketNonce(nonce);
|
||||
memcpy(cmd.m_Body + nbytes, nonce, 20);
|
||||
mxkN2UtilHmacPacket(packet_sha, param_1, nonce, auth_key, cmd.m_Body + nbytes + 20);
|
||||
if (requestNonce == NULL || hmacKey == NULL) return -2;
|
||||
|
||||
puts("Dodgy HMAC");
|
||||
exit(1);
|
||||
mxkN2GetPacketNonce(requestNonce);
|
||||
memcpy_s(footer->sign.m_Nonce, sizeof footer->sign.m_Nonce, requestNonce,
|
||||
sizeof *requestNonce);
|
||||
|
||||
mxkN2UtilHmacPacket(&sha1sum, hmacSalt, &footer->sign.m_Nonce, hmacKey,
|
||||
&footer->sign.m_Hmac);
|
||||
}
|
||||
|
||||
unsigned short nWrote;
|
||||
iVar1 = mxkN2CmdWriteData(addr, (unsigned char *)&cmd, paramsize, &nWrote);
|
||||
if (iVar1 == 0) {
|
||||
iVar1 = 0;
|
||||
} else {
|
||||
amiDebugLog("Error: Data write failed. ErrorCode %d.", iVar1);
|
||||
iVar1 = -8;
|
||||
unsigned short nBytesOut;
|
||||
ret = mxkN2CmdWriteData(addr, &packet, paramsize, &nBytesOut);
|
||||
if (ret != 0) {
|
||||
amiDebugLog("Error: Data write failed. ErrorCode %d.", ret);
|
||||
return -8;
|
||||
}
|
||||
return iVar1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mxkN2CmdReadData(unsigned char addr, N2Packet_t *lpPacket, unsigned short nReadSize,
|
||||
unsigned short *lpBytesRead) {
|
||||
int err;
|
||||
*lpBytesRead = 0;
|
||||
|
||||
if (nReadSize < 4 || lpPacket == NULL) {
|
||||
amiDebugLog("Error: Invalid param.");
|
||||
return -2;
|
||||
}
|
||||
if (mxkSmbusRequestMutex() != 0) return -6;
|
||||
|
||||
unsigned char *buffer = (unsigned char *)lpPacket;
|
||||
|
||||
// Read until m_ParamSize
|
||||
err = mxkSmbusI2CReadBlock(addr, 0xc3, buffer, 4);
|
||||
|
||||
unsigned short readPosition = 4;
|
||||
if (err == 0) {
|
||||
unsigned short paramSize = _byteswap_ushort(lpPacket->m_ParamSize);
|
||||
if (nReadSize < paramSize - 4) {
|
||||
amiDebugLog("mxkSmbusI2CReadBlock data : %04X %04X", lpPacket->m_Tag,
|
||||
lpPacket->m_ParamSize);
|
||||
amiDebugLog("Error: Data size is too small.(readSize:%04X, m_paramSize:%04X)",
|
||||
nReadSize, (lpPacket->m_ParamSize << 8 | lpPacket->m_ParamSize >> 8) - 4);
|
||||
return -11;
|
||||
}
|
||||
|
||||
if (4 < paramSize) {
|
||||
while (readPosition < paramSize) {
|
||||
unsigned short blockSize = paramSize - readPosition;
|
||||
if (blockSize > 4) blockSize = 4;
|
||||
|
||||
if (blockSize == 1)
|
||||
err = mxkSmbusReadByte(addr, buffer + readPosition, 0xc3);
|
||||
else
|
||||
err = mxkSmbusI2CReadBlock(addr, 0xc3, buffer + readPosition, blockSize & 0xff);
|
||||
|
||||
if (err != 0) {
|
||||
amiDebugLog("Error: Data read failed. Position %d. ErrorCode %d.", readPosition,
|
||||
err);
|
||||
break;
|
||||
}
|
||||
|
||||
readPosition += blockSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*lpBytesRead = readPosition;
|
||||
if (mxkSmbusReleaseMutex() != 0) {
|
||||
amiDebugLog("Error: ReleaseMutex(). ErrorCode %d.", GetLastError());
|
||||
return -6;
|
||||
}
|
||||
if (err) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool mxkN2CmdIsValidOutParam(N2Packet_t *packet, unsigned tag, unsigned short paramSize) {
|
||||
unsigned short tagPacket = _byteswap_ushort(packet->m_Tag);
|
||||
unsigned short paramSizePacket = _byteswap_ushort(packet->m_ParamSize);
|
||||
unsigned short returnCode = _byteswap_ushort(packet->m_Command);
|
||||
if (tagPacket == tag && paramSizePacket == paramSize && returnCode == 0) return true;
|
||||
|
||||
amiDebugLog("tag: %04x, paramSize: %d, returnCode: %04x", tagPacket, paramSizePacket,
|
||||
returnCode);
|
||||
return false;
|
||||
}
|
||||
|
||||
int mxkN2CmdReadResponce(PN2Nonce_t requestNonce, PHmacSum_t hmacSalt, N2Tag_t tag,
|
||||
N2Command_t command, PHmacKey_t hmacKey, unsigned char addr, void *bufOut,
|
||||
unsigned short nOut) {
|
||||
int ret;
|
||||
unsigned short nBytesRead;
|
||||
Sha1Sum_t sha1sum;
|
||||
N2Packet_t packet;
|
||||
|
||||
ZeroMemory(&packet, sizeof packet);
|
||||
unsigned short footerSize =
|
||||
tag == N2_TAG_RQU_COMMAND ? N2_FOOTER_RQU_SIZE : N2_FOOTER_SIGN_SIZE;
|
||||
ret = mxkN2CmdReadData(addr, &packet, nOut + N2_HEADER_SIZE + footerSize, &nBytesRead);
|
||||
if (ret != 0) {
|
||||
amiDebugLog("Error: Data read failed. ErrorCode %d.", ret);
|
||||
return -7;
|
||||
}
|
||||
|
||||
if (!mxkN2CmdIsValidOutParam(
|
||||
&packet, tag == N2_TAG_RQU_COMMAND ? N2_TAG_RSP_COMMAND : N2_TAG_RSP_AUTH_COMMAND,
|
||||
nBytesRead)) {
|
||||
amiDebugLog("Error: Invalid output parameter.");
|
||||
return -9;
|
||||
}
|
||||
|
||||
unsigned short fixedCommand = _byteswap_ushort(command);
|
||||
|
||||
mxkN2UtilSha1Many(&sha1sum, 3, &packet, N2_HEADER_SIZE, &fixedCommand, sizeof fixedCommand,
|
||||
packet.m_Body, nOut);
|
||||
|
||||
N2PacketFooter_t *footer = (N2PacketFooter_t *)(packet.m_Body + nOut);
|
||||
|
||||
if (tag == N2_TAG_RQU_COMMAND) {
|
||||
if (memcmp(footer->rqu.m_ShaSum, sha1sum, sizeof sha1sum) != 0) {
|
||||
amiDebugLog("Error: Invalid hash value.");
|
||||
return -10;
|
||||
}
|
||||
} else {
|
||||
if (requestNonce == NULL || hmacKey == NULL) return -2;
|
||||
|
||||
HmacSum_t computedHash;
|
||||
mxkN2UtilHmacPacket(&sha1sum, &footer->sign.m_Nonce, requestNonce, hmacKey, &computedHash);
|
||||
if (memcmp(footer->sign.m_Hmac, computedHash, sizeof computedHash) != 0) {
|
||||
amiDebugLog("Error: Invalid hash value.");
|
||||
return -10;
|
||||
}
|
||||
memcpy_s(requestNonce, sizeof *requestNonce, packet.m_Body + nOut, 20);
|
||||
|
||||
if (hmacSalt != NULL)
|
||||
memcpy_s(hmacSalt, sizeof *hmacSalt, &footer->sign.m_Nonce,
|
||||
sizeof footer->sign.m_Nonce);
|
||||
}
|
||||
|
||||
if (bufOut != NULL && nOut != 0) {
|
||||
memcpy_s(bufOut, nOut, packet.m_Body,
|
||||
((nBytesRead - footerSize) - N2_HEADER_SIZE) & 0xffff);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mxkN2CmdEnableSession(void) {
|
||||
int ret;
|
||||
unsigned char local_18[20];
|
||||
N2Nonce_t nonce;
|
||||
|
||||
if (!MXK_N2_INIT) {
|
||||
amiDebugLog("Error: Uninitialized.");
|
||||
return -3;
|
||||
}
|
||||
CheckN2Init;
|
||||
|
||||
ret = mxkN2CmdWriteCommand(NULL, local_18, N2_TAG_RQU_COMMAND, N2_ORD_ENABLE_SESSION, NULL,
|
||||
int err;
|
||||
err = mxkN2CmdWriteCommand(&nonce, NULL, N2_TAG_RQU_COMMAND, N2_ORD_ENABLE_SESSION, NULL,
|
||||
N2DeviceInfo.m_Addr, NULL, 0);
|
||||
if (ret != 0) return ret;
|
||||
if (err != 0) return err;
|
||||
|
||||
Sleep(32);
|
||||
// TODO: ASAP
|
||||
// ret = mxkN2CmdReadResponce(local_18, NULL, N2_TAG_RQU_COMMAND, N2_ORD_ENABLE_SESSION, NULL,
|
||||
// N2DeviceInfo.m_Addr, N2DeviceInfo.m_HmacOut, 20);
|
||||
if (ret != 0) return ret;
|
||||
err = mxkN2CmdReadResponce(&nonce, NULL, N2_TAG_RQU_COMMAND, N2_ORD_ENABLE_SESSION, NULL,
|
||||
N2DeviceInfo.m_Addr, &N2DeviceInfo.m_HmacSalt, 20);
|
||||
if (err != 0) return err;
|
||||
Sleep(16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mxkN2CmdGetErrorCode(unsigned short *errorCode) {
|
||||
N2Nonce_t nonce;
|
||||
|
||||
CheckN2Init;
|
||||
|
||||
int err;
|
||||
err = mxkN2CmdWriteCommand(&nonce, NULL, N2_TAG_RQU_COMMAND, N2_ORD_GET_ERROR_CODE, NULL,
|
||||
N2DeviceInfo.m_Addr, NULL, 0);
|
||||
if (err != 0) return err;
|
||||
|
||||
Sleep(32);
|
||||
unsigned short rawErrorCode;
|
||||
err = mxkN2CmdReadResponce(&nonce, NULL, N2_TAG_RQU_COMMAND, N2_ORD_GET_ERROR_CODE, NULL,
|
||||
N2DeviceInfo.m_Addr, &rawErrorCode, 2);
|
||||
if (err != 0) return err;
|
||||
|
||||
Sleep(16);
|
||||
*errorCode = _byteswap_ushort(rawErrorCode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mxkN2CmdSetAuthKey(PN2AuthKey_t authKey) {
|
||||
CheckN2Init;
|
||||
|
||||
unsigned char authKeyPt[32];
|
||||
ZeroMemory(authKeyPt, sizeof authKeyPt);
|
||||
unsigned char authKeyCt[32];
|
||||
memcpy_s(authKeyPt, sizeof authKeyPt, authKey, sizeof *authKey);
|
||||
mxkCryptEncryptAes128CBC(N2DeviceInfo.m_AESKey.m_Key, N2DeviceInfo.m_AESKey.m_IV, authKeyCt,
|
||||
authKeyPt, sizeof authKeyPt);
|
||||
|
||||
N2Nonce_t nonce;
|
||||
int err;
|
||||
err = mxkN2CmdWriteCommand(&nonce, &N2DeviceInfo.m_HmacSalt, N2_TAG_RQU_AUTH_COMMAND,
|
||||
N2_ORD_SET_AUTH_KEY, &N2DeviceInfo.m_HmacKey, N2DeviceInfo.m_Addr,
|
||||
authKeyCt, sizeof authKeyCt);
|
||||
if (err != 0) return err;
|
||||
|
||||
Sleep(96);
|
||||
err = mxkN2CmdReadResponce(&nonce, &N2DeviceInfo.m_HmacSalt, N2_TAG_RQU_AUTH_COMMAND,
|
||||
N2_ORD_SET_AUTH_KEY, &N2DeviceInfo.m_HmacKey, N2DeviceInfo.m_Addr,
|
||||
NULL, 0);
|
||||
if (err != 0) return err;
|
||||
Sleep(16);
|
||||
memcpy_s(N2DeviceInfo.m_AuthKey, sizeof N2DeviceInfo.m_AuthKey, authKey, sizeof *authKey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mxkN2CmdSetEncKey(AESKey_t *encKey) {
|
||||
CheckN2Init;
|
||||
|
||||
unsigned char encKeyCt[sizeof *encKey];
|
||||
mxkCryptEncryptAes128CBC(N2DeviceInfo.m_AESKey.m_Key, N2DeviceInfo.m_AESKey.m_IV, encKeyCt,
|
||||
encKey, sizeof encKeyCt);
|
||||
|
||||
N2Nonce_t requestNonce;
|
||||
int err;
|
||||
err = mxkN2CmdWriteCommand(&requestNonce, &N2DeviceInfo.m_HmacSalt, N2_TAG_RQU_AUTH_COMMAND,
|
||||
N2_ORD_SET_ENC_KEY, &N2DeviceInfo.m_AuthKey, N2DeviceInfo.m_Addr,
|
||||
encKeyCt, sizeof encKeyCt);
|
||||
if (err != 0) return err;
|
||||
|
||||
Sleep(96);
|
||||
err = mxkN2CmdReadResponce(&requestNonce, &N2DeviceInfo.m_HmacSalt, N2_TAG_RQU_AUTH_COMMAND,
|
||||
N2_ORD_SET_ENC_KEY, &N2DeviceInfo.m_AuthKey, N2DeviceInfo.m_Addr,
|
||||
NULL, 0);
|
||||
if (err != 0) return err;
|
||||
|
||||
Sleep(16);
|
||||
memcpy_s(&N2DeviceInfo.m_EncKey, sizeof N2DeviceInfo.m_EncKey, encKey, sizeof *encKey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mxkN2CmdGetAuthLevel(unsigned char *authLevel) {
|
||||
CheckN2Init;
|
||||
|
||||
unsigned char rawAuthlevel;
|
||||
N2Nonce_t nonce;
|
||||
|
||||
int err;
|
||||
err = mxkN2CmdWriteCommand(&nonce, NULL, N2_TAG_RQU_COMMAND, N2_ORD_GET_AUTH_LEVEL, NULL,
|
||||
N2DeviceInfo.m_Addr, NULL, 0);
|
||||
if (err != 0) return err;
|
||||
Sleep(32);
|
||||
err = mxkN2CmdReadResponce(&nonce, NULL, N2_TAG_RQU_COMMAND, N2_ORD_GET_AUTH_LEVEL, NULL,
|
||||
N2DeviceInfo.m_Addr, &rawAuthlevel, 1);
|
||||
if (err != 0) return err;
|
||||
Sleep(16);
|
||||
err = 0;
|
||||
*authLevel = rawAuthlevel;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mxkN2GetErrorCode(void) {
|
||||
unsigned short errorCode;
|
||||
|
||||
int err = mxkN2CmdGetErrorCode(&errorCode);
|
||||
if (err != 0) {
|
||||
amiDebugLog("Error: mxkN2CmdGetErrorCode(). ErrorCode %d", err);
|
||||
return -5;
|
||||
}
|
||||
|
||||
amiDebugLog("N2 ErrorCode 0x%04X", errorCode);
|
||||
return 0;
|
||||
}
|
||||
int mxkN2CmdReadKeychipID(N2KeychipId_t *lpKeychipId) {
|
||||
CheckN2Init;
|
||||
|
||||
N2Nonce_t nonce;
|
||||
|
||||
unsigned char readData[sizeof *lpKeychipId + 2];
|
||||
|
||||
N2Byte_t request[4];
|
||||
request[0] = 0;
|
||||
request[1] = 0;
|
||||
request[2] = 0;
|
||||
request[3] = sizeof *lpKeychipId;
|
||||
|
||||
int err;
|
||||
err = mxkN2CmdWriteCommand(&nonce, &N2DeviceInfo.m_HmacSalt, N2_TAG_RQU_AUTH_COMMAND,
|
||||
N2_ORD_READ_KEYCHIP_ID, &N2DeviceInfo.m_AuthKey, N2DeviceInfo.m_Addr,
|
||||
request, sizeof request);
|
||||
if (err != 0) return err;
|
||||
Sleep(128);
|
||||
err = mxkN2CmdReadResponce(&nonce, &N2DeviceInfo.m_HmacSalt, N2_TAG_RQU_AUTH_COMMAND,
|
||||
N2_ORD_READ_KEYCHIP_ID, &N2DeviceInfo.m_AuthKey, N2DeviceInfo.m_Addr,
|
||||
readData, sizeof readData);
|
||||
|
||||
if (err != 0) return err;
|
||||
Sleep(16);
|
||||
|
||||
mxkCryptDecryptAes128CBC(N2DeviceInfo.m_EncKey.m_Key, N2DeviceInfo.m_EncKey.m_IV, readData + 2,
|
||||
(unsigned char *)lpKeychipId, sizeof *lpKeychipId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mxkN2Authentication(void) {
|
||||
// TODO: ASAP
|
||||
// unsigned char auth_key[20];
|
||||
// unsigned char enc_key[32];
|
||||
N2AuthKey_t authKey;
|
||||
AESKey_t enc_key;
|
||||
|
||||
if (!MXK_HAS_INIT) {
|
||||
amiDebugLog("No Init Error!!");
|
||||
return -3;
|
||||
}
|
||||
|
||||
int ErrorCode;
|
||||
|
||||
ErrorCode = mxkN2CmdEnableSession();
|
||||
if (ErrorCode != 0) {
|
||||
// mxkN2GetErrorCode();
|
||||
amiDebugLog("Error: mxkN2CmdEnableSession(). ErrorCode %d", ErrorCode);
|
||||
int err;
|
||||
err = mxkN2CmdEnableSession();
|
||||
if (err != 0) {
|
||||
mxkN2GetErrorCode();
|
||||
amiDebugLog("Error: mxkN2CmdEnableSession(). ErrorCode %d", err);
|
||||
return -5;
|
||||
}
|
||||
|
||||
// _randomBytes(auth_key, sizeof auth_key);
|
||||
// ErrorCode = mxkN2CmdSetAuthKey(auth_key);
|
||||
// if (ErrorCode != 0) {
|
||||
// mxkN2GetErrorCode();
|
||||
// amiDebugLog("Error: mxkN2CmdSetAuthKey(). ErrorCode %d", ErrorCode);
|
||||
// return -5;
|
||||
// }
|
||||
unsigned char authLevel;
|
||||
mxkN2CmdGetAuthLevel(&authLevel);
|
||||
printf("Achieved auth level: %d\n", authLevel);
|
||||
|
||||
// _randomBytes(enc_key, sizeof enc_key);
|
||||
// ErrorCode = mxkN2CmdSetEncKey(enc_key);
|
||||
// if (ErrorCode != 0) {
|
||||
// mxkN2GetErrorCode();
|
||||
// amiDebugLog("Error: mxkN2CmdSetEncKey().ErrorCode %d", ErrorCode);
|
||||
// return -5;
|
||||
// }
|
||||
_randomBytes(authKey, sizeof authKey);
|
||||
err = mxkN2CmdSetAuthKey(&authKey);
|
||||
if (err != 0) {
|
||||
mxkN2GetErrorCode();
|
||||
amiDebugLog("Error: mxkN2CmdSetAuthKey(). ErrorCode %d", err);
|
||||
return -5;
|
||||
}
|
||||
|
||||
// unsigned char auth_level;
|
||||
// ErrorCode = mxkN2CmdGetAuthLevel(&auth_level);
|
||||
// if (ErrorCode == 0 && auth_level == 3) return 0;
|
||||
mxkN2CmdGetAuthLevel(&authLevel);
|
||||
printf("Achieved auth level: %d\n", authLevel);
|
||||
|
||||
// mxkN2GetErrorCode();
|
||||
// amiDebugLog("Error: mxkN2CmdGetAuthLevel().ErrorCode %d", ErrorCode);
|
||||
_randomBytes(&enc_key, sizeof enc_key);
|
||||
err = mxkN2CmdSetEncKey(&enc_key);
|
||||
if (err != 0) {
|
||||
mxkN2GetErrorCode();
|
||||
amiDebugLog("Error: mxkN2CmdSetEncKey().ErrorCode %d", err);
|
||||
return -5;
|
||||
}
|
||||
|
||||
mxkN2CmdGetAuthLevel(&authLevel);
|
||||
printf("Achieved auth level: %d\n", authLevel);
|
||||
|
||||
// unsigned char authLevel;
|
||||
err = mxkN2CmdGetAuthLevel(&authLevel);
|
||||
if (err == 0 && authLevel == 3) return 0;
|
||||
|
||||
mxkN2GetErrorCode();
|
||||
amiDebugLog("Error: mxkN2CmdGetAuthLevel().ErrorCode %d", err);
|
||||
return -5;
|
||||
}
|
||||
|
||||
void mxkN2Exit(void) { MXK_N2_INIT = FALSE; }
|
||||
|
||||
int mxkN2Init(void) {
|
||||
int err;
|
||||
err = mxkN2CmdSetDeviceInfo();
|
||||
if (err != 0) return err;
|
||||
|
||||
err = mxkN2Authentication();
|
||||
if (err != 0) {
|
||||
unsigned short errorCode;
|
||||
err = mxkN2CmdGetErrorCode(&errorCode);
|
||||
if (err != 0) {
|
||||
amiDebugLog("Error: mxkN2CmdGetErrorCode(). ErrorCode %d", err);
|
||||
} else {
|
||||
amiDebugLog("N2 ErrorCode 0x%04X", errorCode);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,25 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <varargs.h>
|
||||
|
||||
void _randomBytes(unsigned char *buf, int nbytes);
|
||||
#include "mxkCrypt.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
uint32_t m_Crc;
|
||||
uint8_t m_Unk04[12];
|
||||
uint8_t m_KeyId[16];
|
||||
struct {
|
||||
uint32_t m_Crc;
|
||||
uint32_t m_FormatType;
|
||||
uint8_t m_GameId[4];
|
||||
uint8_t m_Region;
|
||||
uint8_t m_ModelType;
|
||||
uint8_t m_SystemFlags;
|
||||
uint8_t Rsv0f;
|
||||
uint8_t m_PlatformId[3];
|
||||
uint8_t m_DvdFlag;
|
||||
uint8_t m_NetworkAddr[4];
|
||||
uint8_t Unk10[88];
|
||||
uint8_t m_Seed[16];
|
||||
} m_AppBoot;
|
||||
} N2KeychipId_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
#define N2_ADDR 0x30
|
||||
|
||||
#define N2_AUTH_KEY_SIZE 20
|
||||
#define N2_NONCE_SIZE 20
|
||||
#define N2_DATA_MAX 506
|
||||
|
||||
#define N2_FOOTER_RQU_SIZE SHA1_SUM_SIZE
|
||||
#define N2_FOOTER_SIGN_SIZE (N2_NONCE_SIZE + HMAC_SUM_SIZE)
|
||||
|
||||
typedef char N2Nonce_t[N2_NONCE_SIZE];
|
||||
typedef char N2AuthKey_t[N2_AUTH_KEY_SIZE];
|
||||
typedef char (*PN2Nonce_t)[N2_NONCE_SIZE];
|
||||
typedef char (*PN2AuthKey_t)[N2_AUTH_KEY_SIZE];
|
||||
|
||||
typedef unsigned short N2Tag_t;
|
||||
typedef unsigned short N2Command_t;
|
||||
typedef unsigned char N2Byte_t;
|
||||
|
||||
void _randomBytes(void *buf, int nbytes);
|
||||
|
||||
int mxkN2UtilVCatenateData(unsigned char *out, size_t *count, unsigned int numStreams,
|
||||
va_list args);
|
||||
void mxkN2UtilCatenateData(unsigned char *concatinated, size_t *count, unsigned int numStreams,
|
||||
...);
|
||||
|
||||
void mxkN2UtilSha1Many(unsigned char *sum, int numStreams, ...);
|
||||
int mxkN2UtilHmacPacket(void *val1, unsigned char *sha1, void *nonce, void *key,
|
||||
unsigned char *hash_out);
|
||||
void mxkN2UtilSha1Many(PSha1Sum_t sum, int numStreams, ...);
|
||||
int mxkN2UtilHmacPacket(PSha1Sum_t packetSha, PHmacSum_t hmacSalt, PN2Nonce_t nonce, PHmacKey_t key,
|
||||
PHmacSum_t computedHash);
|
||||
|
||||
int mxkN2CmdWriteCommand(unsigned char *param_1, unsigned char *packet, unsigned short tag,
|
||||
unsigned short command, unsigned char *auth_key, unsigned char addr,
|
||||
void *data, size_t nbytes);
|
||||
int mxkN2CmdWriteCommand(PN2Nonce_t nonce, PHmacSum_t hmacSalt, N2Tag_t tag, N2Command_t command,
|
||||
PHmacKey_t hmacKey, unsigned char addr, N2Byte_t *data,
|
||||
unsigned short nbytes);
|
||||
|
||||
int mxkN2CmdEnableSession(void);
|
||||
int mxkN2CmdSetAuthKey(unsigned char* authKey);
|
||||
int mxkN2CmdSetAuthKey(PN2AuthKey_t authKey);
|
||||
|
||||
int mxkN2CmdInit(void);
|
||||
int mxkN2CmdSetDeviceInfo(void);
|
||||
int mxkN2Authentication(void);
|
||||
int mxkN2CmdReadKeychipID(N2KeychipId_t *lpKeychipId);
|
||||
|
||||
int mxkN2Init(void);
|
||||
void mxkN2Exit(void);
|
||||
|
@ -228,7 +228,7 @@ int mxkSmbusI2CWriteCommand(unsigned char command_code, unsigned char *buffer, s
|
||||
return tries == 5 ? -9 : 0;
|
||||
}
|
||||
|
||||
bool mxkSmbusI2CReadBlock(unsigned char smbAddress, unsigned char block, unsigned char *buffer,
|
||||
int mxkSmbusI2CReadBlock(unsigned char smbAddress, unsigned char block, unsigned char *buffer,
|
||||
unsigned char nbytes) {
|
||||
DWORD nBytesReturned;
|
||||
smb_packet packet;
|
||||
@ -244,10 +244,10 @@ bool mxkSmbusI2CReadBlock(unsigned char smbAddress, unsigned char block, unsigne
|
||||
if (!succ || nBytesReturned != sizeof packet) return false;
|
||||
if (packet.status == 0) {
|
||||
memcpy(buffer, packet.data, nbytes);
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
if (packet.status != 24) return false;
|
||||
Sleep(16);
|
||||
}
|
||||
return false;
|
||||
return -8;
|
||||
}
|
||||
|
@ -10,9 +10,9 @@
|
||||
int mxkSmbusI2CWriteCommand(unsigned char command_code, unsigned char *buffer, size_t nbytes);
|
||||
|
||||
int mxkSmbusI2CWriteBlock(unsigned char addr, unsigned char command, unsigned char *buffer,
|
||||
unsigned char nbytes);
|
||||
bool mxkSmbusI2CReadBlock(unsigned char smbAddress, unsigned char block, unsigned char *buffer,
|
||||
unsigned char nbytes);
|
||||
int mxkSmbusI2CReadBlock(unsigned char smbAddress, unsigned char block, unsigned char *buffer,
|
||||
unsigned char nbytes);
|
||||
|
||||
int mxkSmbusWriteByte(unsigned char v_addr, unsigned char command_code, unsigned char data);
|
||||
int mxkSmbusReadByte(unsigned char addr, unsigned char *readByte, unsigned char cmd_code);
|
||||
|
@ -16,7 +16,7 @@ void miceDumpKCPIC() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The following sequence is required to avoid SBTR!
|
||||
* The following sequence is required, within 30 seconds, to avoid SBTR!
|
||||
*
|
||||
* amDongleSetupKeychip:
|
||||
* keychip.appboot.systemflag=?&cache=0
|
||||
|
Loading…
Reference in New Issue
Block a user