Compare commits

..

No commits in common. "09bd2e4792bd0346991d37da13f7a3e667a8e3c0" and "800b6f28e1ac252edfc1e6b3ae21d71f552e7652" have entirely different histories.

19 changed files with 217 additions and 790 deletions

View File

@ -1,62 +0,0 @@
#include <Windows.h>
DWORD NvidiaDebugLevel = 0;
__declspec(dllexport) int amvFinalize_Nvidia() { return 0; }
__declspec(dllexport) int amvGetAvailableDriverEx_Nvidia(LPVOID pGpuHandle, DWORD dwGpuHandleSize) {
return 0;
}
__declspec(dllexport) int amvGetAvailableDriver_Nvidia() {
return amvGetAvailableDriverEx_Nvidia(NULL, 4);
}
__declspec(dllexport) int amvGetConnectedDisplaysEx_Nvidia(LPVOID pGpuHandle, DWORD dwGpuHandleSize,
LPBYTE displayType) {
// TODO: Find a use of this to figure out what we should spoof!
if (displayType) *displayType = 0;
return 0;
}
__declspec(dllexport) int amvGetConnectedDisplays_Nvidia(LPBYTE displayType) {
return amvGetConnectedDisplays_Nvidia(NULL, 4, displayType);
}
__declspec(dllexport) int amvGetCurrentPstateEx_Nvidia(LPVOID pGpuHandle, DWORD dwGpuHandleSize,
DWORD* pPstate) {
// TODO: Find a use of this to figure out what we should spoof!
if (pPstate) *pPstate = 0;
return 0;
}
__declspec(dllexport) int amvGetCurrentPstate_Nvidia(DWORD* pPstate) {
return amvGetCurrentPstateEx_Nvidia(NULL, 4, pPstate);
}
__declspec(dllexport) int amvGetamvNvidiaDebugLevel() { return NvidiaDebugLevel; }
__declspec(dllexport) char* amvGetamvNvidiaVersion() {
return "\namv_nvidia Ver.1.05 Build:Jul 22 2011 13:53:26\n";
}
__declspec(dllexport) int amvInitialize_Nvidia(LPVOID pGpuHandle, DWORD dwGpuHandleSize) {
return 0;
}
__declspec(dllexport) int amvSetCustomDisplaySetting2ndEx_Nvidia(
LPVOID pGpuHandle, DWORD dwGpuHandleSize, LPWORD NV_SetCustomDisplaySetting) {
return 0;
}
__declspec(dllexport) int amvSetCustomDisplaySetting2nd_Nvidia(LPVOID pGpuHandle) {
return amvSetCustomDisplaySetting2ndEx_Nvidia(NULL, 4, pGpuHandle);
}
__declspec(dllexport) int amvSetCustomDisplaySettingEx_Nvidia(LPVOID pGpuHandle,
DWORD dwGpuHandleSize,
LPWORD NV_SetCustomDisplaySetting) {
return 0;
}
__declspec(dllexport) int amvSetCustomDisplaySetting_Nvidia(LPVOID pGpuHandle) {
return amvSetCustomDisplaySettingEx_Nvidia(NULL, 4, pGpuHandle);
}
__declspec(dllexport) int amvSetDisplayModeEx_Nvidia(LPVOID pGpuHandle, DWORD dwGpuHandleSize,
BYTE displayMode) {
return 0;
}
__declspec(dllexport) int amvSetDisplayMode_Nvidia(BYTE displayMode) {
return amvSetDisplayModeEx_Nvidia(NULL, 4, displayMode);
}
__declspec(dllexport) int amvSetamvNvidiaDebugLevel(DWORD debugLevel) {
NvidiaDebugLevel = debugLevel;
return NvidiaDebugLevel;
}

View File

@ -115,8 +115,6 @@ 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[4], USER_EEPROM[page], DS28CN01_EEPROM_PAGE_SIZE);
memcpy(&MAC_INPUT_BUFFER[36], &data[0], 4); memcpy(&MAC_INPUT_BUFFER[36], &data[0], 4);
MAC_INPUT_BUFFER[40] = 0x40 | page; 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[41], UNIQUE_NUMBER, 7);
memcpy(&MAC_INPUT_BUFFER[48], &SECRET[4], 4); memcpy(&MAC_INPUT_BUFFER[48], &SECRET[4], 4);
memcpy(&MAC_INPUT_BUFFER[52], &data[4], 3); memcpy(&MAC_INPUT_BUFFER[52], &data[4], 3);

View File

@ -13,9 +13,8 @@ LOG_FACILITY _lf = {
}; };
PLOG_FACILITY plf = &_lf; PLOG_FACILITY plf = &_lf;
#define N2_IO_BUFFER 512 #define N2_IO_BUFFER 0x1000
BYTE n2_auth_level = 1;
BYTE n2_in_buffer[N2_IO_BUFFER]; BYTE n2_in_buffer[N2_IO_BUFFER];
WORD n2_in_pointer = 0; WORD n2_in_pointer = 0;
BYTE n2_out_buffer[N2_IO_BUFFER]; BYTE n2_out_buffer[N2_IO_BUFFER];
@ -26,7 +25,7 @@ WORD n2_error_code = 0;
BYTE n2_auth_key[20] = { 0x96, 0xed, 0x31, 0xb2, 0x28, 0x71, 0x05, 0xa5, 0xa3, 0x30, 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 }; 0x54, 0x0f, 0x25, 0xbe, 0xd8, 0x51, 0xa5, 0xc8, 0x36, 0x21 };
BYTE n2_session_salt[20]; BYTE n2_session_nonce[20];
struct { struct {
BYTE key[16]; BYTE key[16];
BYTE iv[16]; BYTE iv[16];
@ -68,8 +67,7 @@ typedef struct {
} N2_KEYCHIP_INFO, *PN2_KEYCHIP_INFO; } N2_KEYCHIP_INFO, *PN2_KEYCHIP_INFO;
#pragma pack(pop) #pragma pack(pop)
N2_KEYCHIP_INFO n2_keychip_info = { N2_KEYCHIP_INFO n2_keychip_info = { .m_KeyId = KEY_ID,
.m_KeyId = KEY_ID,
.m_Appboot = { .m_Appboot = {
.m_Format = 1, .m_Format = 1,
.m_GameId = GAME_ID, .m_GameId = GAME_ID,
@ -80,14 +78,13 @@ N2_KEYCHIP_INFO n2_keychip_info = {
.m_DvdFlag = 1, .m_DvdFlag = 1,
.m_NetworkAddr = .m_NetworkAddr =
(192 << 0) | (168 << 8) | (103 << 16) | (0 << 24), (192 << 0) | (168 << 8) | (103 << 16) | (0 << 24),
}, } };
};
WORD n2_enable_session(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) { WORD n2_enable_session(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
*nOut = 20; *nOut = 20;
RAND_bytes(n2_session_salt, sizeof n2_session_salt); RAND_bytes(n2_session_nonce, sizeof n2_session_nonce);
memcpy(dataOut, n2_session_salt, sizeof n2_session_salt); memcpy(dataOut, n2_session_nonce, sizeof n2_session_nonce);
log_misc(plf, "Session open"); log_misc(plf, "Session open");
return N2_SUCCESS; return N2_SUCCESS;
@ -100,8 +97,6 @@ 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); mxkCryptDecryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataIn, pt, sizeof pt);
memcpy(n2_auth_key, pt, sizeof n2_auth_key); memcpy(n2_auth_key, pt, sizeof n2_auth_key);
n2_auth_level = 2;
return N2_SUCCESS; return N2_SUCCESS;
} }
WORD n2_set_enc_key(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) { WORD n2_set_enc_key(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
@ -113,13 +108,11 @@ 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.key, pt, sizeof n2_enc_key.key);
memcpy(n2_enc_key.iv, pt + sizeof n2_enc_key.key, sizeof n2_enc_key.iv); memcpy(n2_enc_key.iv, pt + sizeof n2_enc_key.key, sizeof n2_enc_key.iv);
n2_auth_level = 3;
return N2_SUCCESS; return N2_SUCCESS;
} }
WORD n2_get_auth_level(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) { WORD n2_get_auth_level(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
*nOut = 1; *nOut = 1;
dataOut[0] = n2_auth_level; dataOut[0] = 3; // TODO: ?
log_misc(plf, "Auth level get"); log_misc(plf, "Auth level get");
return N2_SUCCESS; return N2_SUCCESS;
} }
@ -248,9 +241,6 @@ void n2_install_commands() {
} }
void do_n2_command(WORD tag, WORD paramSize, WORD command, LPBYTE data) { void do_n2_command(WORD tag, WORD paramSize, WORD command, LPBYTE data) {
EVP_MD_CTX* ctx;
unsigned int outlen;
n2_install_commands(); n2_install_commands();
log_info(plf, "Processing command: %04x/%04x (%d bytes)", tag, command, paramSize); log_info(plf, "Processing command: %04x/%04x (%d bytes)", tag, command, paramSize);
@ -267,39 +257,6 @@ void do_n2_command(WORD tag, WORD paramSize, WORD command, LPBYTE data) {
WORD expectedExtraData = N2_CHECKSUM_SIZE + N2_HEADER_SIZE; WORD expectedExtraData = N2_CHECKSUM_SIZE + N2_HEADER_SIZE;
if (tag == N2_TAG_RQU_AUTH_COMMAND) expectedExtraData += N2_AUTH_SIZE; if (tag == N2_TAG_RQU_AUTH_COMMAND) expectedExtraData += N2_AUTH_SIZE;
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 {
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]; n2_command handler = N2_COMMANDS[command & 0xff];
if (handler.handler == NULL) { if (handler.handler == NULL) {
result = N2_BAD_ORDINAL; result = N2_BAD_ORDINAL;
@ -311,13 +268,15 @@ void do_n2_command(WORD tag, WORD paramSize, WORD command, LPBYTE data) {
result = (*handler.handler)(paramSize, n2_in_buffer + N2_HEADER_SIZE, result = (*handler.handler)(paramSize, n2_in_buffer + N2_HEADER_SIZE,
n2_out_buffer + N2_HEADER_SIZE, &bodyLength); n2_out_buffer + N2_HEADER_SIZE, &bodyLength);
} }
}
WORD paramSizeOut = bodyLength + expectedExtraData; WORD paramSizeOut = bodyLength + expectedExtraData;
((PWORD)n2_out_buffer)[0] = fix_endian(tag + 2); ((PWORD)n2_out_buffer)[0] = fix_endian(tag + 2);
((PWORD)n2_out_buffer)[1] = fix_endian(paramSizeOut); ((PWORD)n2_out_buffer)[1] = fix_endian(paramSizeOut);
((PWORD)n2_out_buffer)[2] = fix_endian(result); ((PWORD)n2_out_buffer)[2] = fix_endian(result);
EVP_MD_CTX* ctx;
unsigned int outlen;
WORD fixed_command = fix_endian(command); WORD fixed_command = fix_endian(command);
// Calculate a SHA1 of the packet, and append it // Calculate a SHA1 of the packet, and append it
@ -332,16 +291,26 @@ void do_n2_command(WORD tag, WORD paramSize, WORD command, LPBYTE data) {
// At this point: packet = header | data | SHA(header | command | data) // At this point: packet = header | data | SHA(header | command | data)
if (tag == N2_TAG_RQU_AUTH_COMMAND) { if (tag == N2_TAG_RQU_AUTH_COMMAND) {
// TODO: Further investigation might be needed here. BYTE crypto_buffer[N2_CHECKSUM_SIZE];
// The following code checks out against mxkeychip, but repeating the
// packet sum twice feels wrong. // 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);
// Calculate an HMAC, and append it // Calculate an HMAC, and append it
HMAC_CTX hmac_ctx;
HMAC_CTX_init(&hmac_ctx); HMAC_CTX_init(&hmac_ctx);
HMAC_Init_ex(&hmac_ctx, auth_key, sizeof auth_key, EVP_sha1(), NULL); HMAC_Init_ex(&hmac_ctx, auth_key, sizeof auth_key, EVP_sha1(), NULL);
// SHA1(header | command | data) // SHA1(header | command | data)
HMAC_Update(&hmac_ctx, n2_out_buffer + N2_HEADER_SIZE + bodyLength, N2_CHECKSUM_SIZE); 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 // Request nonce
HMAC_Update(&hmac_ctx, n2_in_buffer + paramSize - N2_AUTH_SIZE - N2_CHECKSUM_SIZE, HMAC_Update(&hmac_ctx, n2_in_buffer + paramSize - N2_AUTH_SIZE - N2_CHECKSUM_SIZE,
@ -350,10 +319,6 @@ 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, HMAC_Final(&hmac_ctx, n2_out_buffer + N2_HEADER_SIZE + bodyLength + N2_CHECKSUM_SIZE,
&outlen); &outlen);
HMAC_CTX_cleanup(&hmac_ctx); 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);
} }
} }
@ -411,7 +376,6 @@ 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) { 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); log_error(plf, "Unsupported read mode: %01x (%02x)", cmd, code);
return FALSE; return FALSE;
} }

View File

@ -64,22 +64,6 @@ LONG WINAPI FakeRtlGetVersion(PRTL_OSVERSIONINFOW lpVersionInformation) {
return 0; return 0;
} }
// TODO: We should probably handle libamv_amd.dll at some point too
HMODULE WINAPI FakeLoadLibraryA(LPCSTR lpLibFileName) {
if (strcmp(lpLibFileName, "libamv_nvidia.dll") == 0) {
return TrueLoadLibraryA(MICELIB);
}
return TrueLoadLibraryA(lpLibFileName);
}
#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
HMODULE WINAPI FakeLoadLibraryW(LPCWSTR lpLibFileName) {
if (wcscmp(lpLibFileName, L"libamv_nvidia.dll") == 0) {
return TrueLoadLibraryW(WIDEN(MICELIB));
}
return TrueLoadLibraryW(lpLibFileName);
}
void hook_system() { void hook_system() {
// TODO: This should be part of drives/hooks.c // TODO: This should be part of drives/hooks.c
hook("Kernel32.dll", "GetVolumeInformationW", FakeGetVolumeInformationW, NULL); hook("Kernel32.dll", "GetVolumeInformationW", FakeGetVolumeInformationW, NULL);
@ -87,8 +71,6 @@ void hook_system() {
// hook("Kernel32.dll", "GetVersionExA", FakeGetVersionExA, NULL); // hook("Kernel32.dll", "GetVersionExA", FakeGetVersionExA, NULL);
// hook("Kernel32.dll", "GetProcAddress", FakeGetProcAddress, (void*)&TrueGetProcAddress); // hook("Kernel32.dll", "GetProcAddress", FakeGetProcAddress, (void*)&TrueGetProcAddress);
// hook("Kernel32.dll", "GetModuleHandleA", FakeGetModuleHandleA, (void*)&TrueGetModuleHandleA); // hook("Kernel32.dll", "GetModuleHandleA", FakeGetModuleHandleA, (void*)&TrueGetModuleHandleA);
hook("Kernel32.dll", "LoadLibraryA", FakeLoadLibraryA, (void*)&TrueLoadLibraryA);
hook("Kernel32.dll", "LoadLibraryW", FakeLoadLibraryW, (void*)&TrueLoadLibraryW);
// hook("ntdll.dll", "RtlGetVersion", FakeRtlGetVersion, NULL); // hook("ntdll.dll", "RtlGetVersion", FakeRtlGetVersion, NULL);

View File

@ -2,9 +2,7 @@
#include "../common.h" #include "../common.h"
FARPROC(WINAPI* TrueGetProcAddress)(HMODULE hModule, LPCSTR lpProcName); FARPROC (*TrueGetProcAddress)(HMODULE hModule, LPCSTR lpProcName);
HMODULE(WINAPI* TrueGetModuleHandleA)(LPCSTR lpModuleName); HMODULE (*TrueGetModuleHandleA)(LPCSTR lpModuleName);
HMODULE(WINAPI* TrueLoadLibraryA)(LPCSTR lpLibFileName);
HMODULE(WINAPI* TrueLoadLibraryW)(LPCWSTR lpLibFileName);
void hook_system(); void hook_system();

View File

@ -8,8 +8,6 @@ shared_library(
name_prefix: '', name_prefix: '',
vs_module_defs: 'mice.def', vs_module_defs: 'mice.def',
sources: [ sources: [
'amvStub/amv.c',
'util/misc.c', 'util/misc.c',
'util/hook.c', 'util/hook.c',
'util/path.c', 'util/path.c',

View File

@ -9,9 +9,7 @@
bool debug_wait = false; bool debug_wait = false;
int boot_delay = 0; int boot_delay = 0;
char exe_name[MAX_PATH + 1] = ""; char exe_name[MAX_PATH + 1] = "";
char commandline[MAX_PATH + 1] = "";
size_t nCommandLine = 256;
char* commandLine = NULL;
static void print_help(char* exe) { static void print_help(char* exe) {
log_info(plfBoot, "Usage: %s [-h] [-t] [-b executable.exe] [-d]", exe); log_info(plfBoot, "Usage: %s [-h] [-t] [-b executable.exe] [-d]", exe);
@ -71,13 +69,10 @@ static bool parse_cmdline(int argc, char* argv[]) {
return false; return false;
} }
} else { } else {
size_t newLength = nCommandLine + 1 + strlen(argv[i]) + 1; if (commandline[0] == 0)
if (newLength > nCommandLine) { snprintf(commandline, sizeof commandline, "%s", argv[i]);
nCommandLine = newLength; else
commandLine = realloc(commandLine, nCommandLine); snprintf(commandline, sizeof commandline, "%s %s", commandline, argv[i]);
}
strcat_s(commandLine, nCommandLine, " ");
strcat_s(commandLine, nCommandLine, argv[i]);
} }
} }
return true; return true;
@ -181,13 +176,6 @@ int main(int argc, char* argv[]) {
log_info(plfBoot, "Micetools version: %s", MICE_VERSION); 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]; CHAR workDir[MAX_PATH + 1];
GetCurrentDirectory(MAX_PATH, workDir); GetCurrentDirectory(MAX_PATH, workDir);
log_info(plfBoot, "Current directory: %s", workDir); log_info(plfBoot, "Current directory: %s", workDir);
@ -215,7 +203,7 @@ int main(int argc, char* argv[]) {
spawn_pcp_processes(); 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]; char micepath[MAX_PATH + 1];
if (!locate_library(micepath, MAX_PATH + 1)) { if (!locate_library(micepath, MAX_PATH + 1)) {
@ -228,30 +216,18 @@ int main(int argc, char* argv[]) {
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &info, sizeof info); 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; char* extra_injections = MiceConfig.launcher.inject;
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
if (!start_and_inject(hJob, exe_name, fullCommandLine, micepath, debug_wait, boot_delay, if (!start_and_inject(hJob, exe_name, commandline, micepath, debug_wait, boot_delay,
extra_injections, 0, &pi)) { extra_injections, 0, &pi))
free(fullCommandLine);
return terminate(-1); return terminate(-1);
}
free(fullCommandLine);
SetConsoleCtrlHandler(MiceHandlerRoutine, TRUE); SetConsoleCtrlHandler(MiceHandlerRoutine, TRUE);
if (FAILED(WaitForSingleObject(pi.hProcess, INFINITE))) { if (FAILED(WaitForSingleObject(pi.hProcess, INFINITE))) {
log_error(plfBoot, "Fatal: WaitForSingleObject failed: %03x", GetLastError()); log_error(plfBoot, "Fatal: WaitForSingleObject failed: %03x", GetLastError());
} else { } else {
DWORD exitCode; log_info(plfBoot, "Shutting down");
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); CloseHandle(pi.hProcess);
} }
return terminate(0); return terminate(0);

View File

@ -4,9 +4,9 @@
AM_LIB_C_HEADER(amiCrc, AMI_CRC) AM_LIB_C_HEADER(amiCrc, AMI_CRC)
void amiCrc32RCreateTable(uint32_t *table) { void amiCrc32RCreateTable(unsigned int *table) {
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
uint32_t value = (~i & 1) - 1 & CRC32_POLYNOMIAL; unsigned int value = (~i & 1) - 1 & CRC32_POLYNOMIAL;
value = ((i >> 1 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1; value = ((i >> 1 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
value = ((i >> 2 ^ ~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; value = ((i >> 3 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
@ -18,12 +18,13 @@ void amiCrc32RCreateTable(uint32_t *table) {
} }
} }
uint32_t amiCrc32RGet(uint32_t *table, int length, void *data, uint32_t initial) { unsigned int amiCrc32RGet(unsigned int *table, int length, unsigned char *data,
uint32_t value = ~initial; unsigned int initial) {
unsigned int value = ~initial;
while (length > 0) { while (length > 0) {
value = value >> 8 ^ table[(((unsigned char *)data)[0] ^ value) & 0xff]; value = value >> 8 ^ table[(data[0] ^ value) & 0xff];
length += -1; length += -1;
((unsigned char *)data)++; data++;
} }
return ~value; return ~value;
} }

View File

@ -1,18 +1,17 @@
#pragma once #pragma once
#include <stdint.h>
#include "../_am.h" #include "../_am.h"
AM_LIB_H_HEADER(amiCrc, AMI_CRC) AM_LIB_H_HEADER(amiCrc, AMI_CRC)
typedef struct _AMI_CRC { typedef struct _AMI_CRC {
uint32_t m_init; unsigned int m_init;
uint32_t m_table[256]; unsigned int m_table[256];
} AMI_CRC; } AMI_CRC;
void amiCrc32RCreateTable(uint32_t *table); void amiCrc32RCreateTable(unsigned int *table);
uint32_t amiCrc32RGet(uint32_t *table, int length, void *data, uint32_t initial); unsigned int amiCrc32RGet(unsigned int *table, int length, unsigned char *data,
unsigned int initial);
#define amiCrc32RInit() \ #define amiCrc32RInit() \
do { \ do { \

View File

@ -3,7 +3,6 @@
#include <stdio.h> #include <stdio.h>
BOOL start_and_inject(HANDLE hJob, LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL debug_wait, BOOL start_and_inject(HANDLE hJob, LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL debug_wait,
DWORD delay, LPCSTR extra_injections, DWORD flags, DWORD delay, LPCSTR extra_injections, DWORD flags, LPPROCESS_INFORMATION lpProcessInformation);
LPPROCESS_INFORMATION lpProcessInformation);
#define MICELIB "mice.dll" #define MICELIB "mice.dll"

View File

@ -177,7 +177,7 @@ BOOL mxkNvramRead(unsigned short addr, unsigned char blocks, unsigned char* data
} }
bool mxkValidString(const char* string, unsigned int length) { bool mxkValidString(const char* string, unsigned int length) {
for (unsigned int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
char c = string[i]; char c = string[i];
if (isalnum(c)) continue; if (isalnum(c)) continue;
if (c != '.' && c != '_' && c != '-' && c != ':' && c != '@' && c != '%' && c != '/' && if (c != '.' && c != '_' && c != '-' && c != ':' && c != '@' && c != '%' && c != '/' &&
@ -187,52 +187,7 @@ bool mxkValidString(const char* string, unsigned int length) {
return true; return true;
} }
MXK_STATUS mxkGetKeychipIdFromN2(void) { MXK_STATUS mxkInit() {
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; mxkVersionDirty = true;
AppBoot.m_cacheDirty = true; AppBoot.m_cacheDirty = true;
@ -248,6 +203,7 @@ MXK_STATUS mxkInit(void) {
amiDebugLog("Error mxkExchengeAesKey!!"); amiDebugLog("Error mxkExchengeAesKey!!");
return MXK_STATUS_ERROR; return MXK_STATUS_ERROR;
} }
// TODO: N2
if (mxkSmbusInit() != MXK_STATUS_OK) { if (mxkSmbusInit() != MXK_STATUS_OK) {
amiDebugLog("Error mxkSmbusInit!!"); amiDebugLog("Error mxkSmbusInit!!");
return MXK_STATUS_ERROR; return MXK_STATUS_ERROR;
@ -270,15 +226,9 @@ MXK_STATUS mxkInit(void) {
// eeprom_playcount(); // eeprom_playcount();
} }
if (mxkN2Init() != 0) { // TODO:
amiDebugLog("Error mxkN2Init!!"); mxkN2CmdSetDeviceInfo();
return MXK_STATUS_ERROR; mxkN2Authentication();
}
if (mxkGetKeychipIdFromN2() != 0) {
amiDebugLog("Error mxkGetKeychipIdFromN2!!");
return MXK_STATUS_ERROR;
}
return MXK_STATUS_OK; return MXK_STATUS_OK;
} }

View File

@ -1,8 +1,8 @@
#include "mxkCrypt.h" #include "mxkCrypt.h"
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/hmac.h>
// These three should be initialised to null, and populated by mxkCryptInit, but we already know // 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, // 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); memcpy(KEY_S, temp, 16);
} }
MXK_STATUS mxkCryptEncryptAes128CBC(const unsigned char* key, const unsigned char* iv, void* ct, MXK_STATUS mxkCryptEncryptAes128CBC(const unsigned char* key, const unsigned char* iv,
const void* pt, size_t nbytes) { unsigned char* ct, const unsigned char* pt, size_t nbytes) {
if (key == NULL || iv == NULL || ct == NULL || pt == NULL) { if (key == NULL || iv == NULL || ct == NULL || pt == NULL) {
amiDebugLog("Error: Invalid param."); amiDebugLog("Error: Invalid param.");
return MXK_STATUS_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, MXK_STATUS mxkCryptDecryptAes128CBC(const unsigned char* key, const unsigned char* iv,
const void* ct, void* pt, size_t nbytes) { const unsigned char* ct, unsigned char* pt, size_t nbytes) {
if (key == NULL || iv == NULL || ct == NULL || pt == NULL) { if (key == NULL || iv == NULL || ct == NULL || pt == NULL) {
amiDebugLog("Error: Invalid param."); amiDebugLog("Error: Invalid param.");
return MXK_STATUS_INVALID_PARAM; return MXK_STATUS_INVALID_PARAM;

View File

@ -4,34 +4,23 @@
#include "../ami/ami.h" #include "../ami/ami.h"
#include "mxkDefs.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 mxkSetKeyS(unsigned char* key_s);
void mxkSetKeyR(unsigned char* key_r); void mxkSetKeyR(unsigned char* key_r);
void mxkSwapKeys(); void mxkSwapKeys();
MXK_STATUS mxkCryptInit(void); MXK_STATUS mxkCryptInit(void);
int mxkCryptCalcHashWithHmacSha1(PHmacKey_t key, PHmacSum_t md, size_t* nbuffer, int mxkCryptCalcHashWithHmacSha1(void* key, unsigned char* md, size_t* nbuffer,
unsigned char* buffer, size_t nin); unsigned char* buffer, size_t nin);
void mxkCryptCalcHashWithSha1(unsigned char* data, size_t nbytes, PSha1Sum_t sum); void mxkCryptCalcHashWithSha1(unsigned char* data, size_t nbytes, unsigned char* sum);
void mxkCryptCreateDigest(void); void mxkCryptCreateDigest(void);
void mxkCryptRsaSignVerify(void); void mxkCryptRsaSignVerify(void);
MXK_STATUS mxkCryptDecryptAes128CBC(const unsigned char* key, const unsigned char* iv, MXK_STATUS mxkCryptDecryptAes128CBC(const unsigned char* key, const unsigned char* iv,
const void* ct, void* pt, size_t nbytes); const unsigned char* ct, unsigned char* pt, size_t nbytes);
MXK_STATUS mxkCryptEncryptAes128CBC(const unsigned char* key, const unsigned char* iv, void* ct, MXK_STATUS mxkCryptEncryptAes128CBC(const unsigned char* key, const unsigned char* iv,
const void* pt, size_t nbytes); unsigned char* pt, const unsigned char* ct, size_t nbytes);
MXK_STATUS mxkCryptDecryptData(const unsigned char* ct, unsigned char* pt); MXK_STATUS mxkCryptDecryptData(const unsigned char* ct, unsigned char* pt);
MXK_STATUS mxkCryptEncryptData(unsigned char* ct, const unsigned char* pt); MXK_STATUS mxkCryptEncryptData(unsigned char* ct, const unsigned char* pt);

View File

@ -57,7 +57,7 @@ int mxkDsKeychipComputeMac(unsigned char page, void *challenge, unsigned char *m
Sleep(16); Sleep(16);
status = mxkDsWaitNotBusy(&INT_004ab34c); status = mxkDsWaitNotBusy(&INT_004ab34c);
if (status == 0) { if (status == 0) {
if (mxkSmbusI2CReadBlock(KC_DS_ADDRESS, DS28CN01_REG_MAC, mac, 20) != 0) { if (!mxkSmbusI2CReadBlock(KC_DS_ADDRESS, DS28CN01_REG_MAC, mac, 20)) {
amiDebugLog("Error mxkSmbusI2CReadBlock()!!!"); amiDebugLog("Error mxkSmbusI2CReadBlock()!!!");
error = -8; error = -8;
} }

View File

@ -1,5 +1,3 @@
#include "mxkN2.h"
#include <Windows.h> #include <Windows.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/hmac.h> #include <openssl/hmac.h>
@ -9,47 +7,30 @@
#include "mxkCrypt.h" #include "mxkCrypt.h"
#include "mxkSmbus.h" #include "mxkSmbus.h"
#define N2_ADDR 0x30
typedef struct { typedef struct {
unsigned char m_Key[16]; unsigned char m_Key[16];
unsigned char m_IV[16]; unsigned char m_IV[16];
} AESKey_t; } AESKey_t;
#pragma pack(push, 1)
typedef struct { typedef struct {
unsigned short m_Tag; unsigned short m_Tag;
unsigned short m_ParamSize; unsigned short m_ParamSize;
unsigned short m_Command; unsigned short m_Command;
unsigned char m_Body[N2_DATA_MAX]; unsigned char m_Body[506];
} N2Packet_t; } 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_HAS_INIT = FALSE;
BOOL MXK_N2_INIT = FALSE; BOOL MXK_N2_INIT = FALSE;
#define CheckN2Init \
do { \
if (!MXK_N2_INIT) { \
amiDebugLog("Error: Uninitialized."); \
return -3; \
} \
} while (0);
typedef struct { typedef struct {
unsigned char m_Addr; unsigned char m_Addr;
HmacKey_t m_HmacKey; unsigned char m_HmacKey[20];
AESKey_t m_AESKey; AESKey_t m_AESKey;
N2AuthKey_t m_AuthKey; unsigned char m_AuthKey[20];
AESKey_t m_EncKey; unsigned char m_EncKey[16];
HmacSum_t m_HmacSalt; unsigned char Unk[16];
unsigned char m_HmacOut[20];
} N2DeviceInfo_t; } N2DeviceInfo_t;
N2DeviceInfo_t N2DeviceInfo; N2DeviceInfo_t N2DeviceInfo;
@ -60,16 +41,14 @@ unsigned char N2_KEY_HMAC[2][20] = {
0x1d, 0x1e, 0x1f, 0x11, 0xee, 0xb0, 0xf4, 0xd4, 0x20, 0x24 } 0x1d, 0x1e, 0x1f, 0x11, 0xee, 0xb0, 0xf4, 0xd4, 0x20, 0x24 }
}; };
AESKey_t N2_KEY_AES[2] = { AESKey_t N2_KEY_AES[2] = { { { 0xd7, 0xf6, 0x86, 0xfb, 0x63, 0x44, 0xff, 0xa5, 0x60, 0x9d, 0x4e,
{ { 0xd7, 0xf6, 0x86, 0xfb, 0x63, 0x44, 0xff, 0xa5, 0x60, 0x9d, 0x4e, 0xf0, 0x18, 0xe9, 0x45, 0xf0, 0x18, 0xe9, 0x45, 0xb4 },
0xb4 }, { 0x12, 0x6c, 0xb1, 0xdb, 0x9e, 0x00, 0x8c, 0xc6, 0xae, 0xa1, 0x73,
{ 0x12, 0x6c, 0xb1, 0xdb, 0x9e, 0x00, 0x8c, 0xc6, 0xae, 0xa1, 0x73, 0xec, 0xe7, 0x2f, 0x5a, 0xec, 0xe7, 0x2f, 0x5a, 0xc4 } },
0xc4 } }, { { 0xa1, 0x1a, 0xc4, 0x4d, 0xcd, 0x48, 0x4f, 0xed, 0x70, 0xcc, 0x3f,
{ { 0xa1, 0x1a, 0xc4, 0x4d, 0xcd, 0x48, 0x4f, 0xed, 0x70, 0xcc, 0x3f, 0x5d, 0x94, 0x5b, 0xbe, 0x5d, 0x94, 0x5b, 0xbe, 0xb3 },
0xb3 }, { 0x9c, 0x5c, 0xba, 0x7f, 0xb0, 0x15, 0xc7, 0x69, 0xcb, 0xb4, 0x41,
{ 0x9c, 0x5c, 0xba, 0x7f, 0xb0, 0x15, 0xc7, 0x69, 0xcb, 0xb4, 0x41, 0x19, 0x97, 0x2b, 0x45, 0x19, 0x97, 0x2b, 0x45, 0x9f } } };
0x9f } },
};
int mxkN2CmdInit(void) { int mxkN2CmdInit(void) {
if (MXK_N2_INIT) { if (MXK_N2_INIT) {
@ -86,7 +65,7 @@ int mxkN2CmdSetDeviceInfo(void) {
if (mxkN2CmdInit() != 0) return -5; if (mxkN2CmdInit() != 0) return -5;
HmacKey_t hmacKey; unsigned char hmacKey[20];
AESKey_t aesKey; 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 hmacKey; i++) hmacKey[i] = N2_KEY_HMAC[0][i] ^ N2_KEY_HMAC[1][i];
for (int i = 0; i < sizeof aesKey.m_Key; i++) for (int i = 0; i < sizeof aesKey.m_Key; i++)
@ -109,18 +88,17 @@ int mxkN2CmdSetDeviceInfo(void) {
} }
// TODO: Better name // TODO: Better name
void _randomBytes(void *buf, int nbytes) { void _randomBytes(unsigned char *buf, int nbytes) {
FILETIME fileTime; FILETIME fileTime;
amtime_t amTime; amtime_t amTime;
for (int i = 0; i < nbytes; i++) { for (int i = 0; i < nbytes; i++) {
amiTimerGet(&amTime); amiTimerGet(&amTime);
GetSystemTimeAsFileTime(&fileTime); GetSystemTimeAsFileTime(&fileTime);
((unsigned char *)buf)[i] = buf[i] = (amTime.microseconds ^ fileTime.dwLowDateTime ^ fileTime.dwHighDateTime) & 0xff;
(amTime.microseconds ^ fileTime.dwLowDateTime ^ fileTime.dwHighDateTime) & 0xff;
} }
} }
void mxkN2GetPacketNonce(PN2Nonce_t nonce) { _randomBytes(nonce, 20); } void mxkN2GetPacketNonce(unsigned char *nonce) { _randomBytes(nonce, 20); }
int mxkN2UtilVCatenateData(unsigned char *out, size_t *count, unsigned int numStreams, int mxkN2UtilVCatenateData(unsigned char *out, size_t *count, unsigned int numStreams,
va_list args) { va_list args) {
@ -132,11 +110,10 @@ int mxkN2UtilVCatenateData(unsigned char *out, size_t *count, unsigned int numSt
size_t offset = 0; size_t offset = 0;
size_t max = *count; size_t max = *count;
for (size_t i = 0; i < numStreams && i < max; i++) { for (size_t i = 0; i < numStreams && i < max; i++) {
unsigned char *b = va_arg(args, unsigned char *);
size_t n = va_arg(args, size_t); size_t n = va_arg(args, size_t);
if (offset + n > max) n = max - offset; unsigned char *b = va_arg(args, unsigned char *);
memcpy(out + offset, b, n); if (i + n > max) n = max - i;
offset += n; memcpy(out + offset, b, i);
} }
*count = offset; *count = offset;
@ -152,49 +129,46 @@ void mxkN2UtilCatenateData(unsigned char *concatinated, size_t *count, unsigned
va_end(args); va_end(args);
} }
void mxkN2UtilSha1Many(PSha1Sum_t sum, int numStreams, ...) { void mxkN2UtilSha1Many(unsigned char *sum, int numStreams, ...) {
va_list args; va_list args;
va_start(args, numStreams); va_start(args, numStreams);
Sha1Sum_t sumout; unsigned char sumout[20];
unsigned char concatinated[0x200]; unsigned char concatinated[0x200];
size_t size = sizeof concatinated; size_t size = sizeof concatinated;
mxkN2UtilVCatenateData(concatinated, &size, numStreams, args); mxkN2UtilVCatenateData(concatinated, &size, numStreams, args);
mxkCryptCalcHashWithSha1(concatinated, size, &sumout); mxkCryptCalcHashWithSha1(concatinated, size, sumout);
memcpy_s(sum, sizeof *sum, sumout, sizeof sumout); memcpy_s(sum, 20, sumout, 20);
va_end(args); va_end(args);
} }
int mxkN2UtilHmacPacket(PSha1Sum_t packetSha, PHmacSum_t hmacSalt, PN2Nonce_t nonce, PHmacKey_t key, int mxkN2UtilHmacPacket(void *val1, unsigned char *sha1, void *nonce, void *key,
PHmacSum_t computedHash) { unsigned char *hash_out) {
HmacSum_t hash; unsigned char hash[20];
unsigned char data_in[sizeof *packetSha + sizeof *hmacSalt + sizeof *nonce]; unsigned char data_in[60];
size_t count = sizeof *packetSha + sizeof *hmacSalt + sizeof *nonce; size_t count = 60;
size_t nout = HMAC_SUM_SIZE; size_t nout = 20;
mxkN2UtilCatenateData(data_in, &count, 3, packetSha, sizeof *packetSha, hmacSalt, mxkN2UtilCatenateData(data_in, &count, 3, val1, 20, sha1, 20, nonce, 20);
sizeof *hmacSalt, nonce, sizeof *nonce);
int err = mxkCryptCalcHashWithHmacSha1(key, &hash, &nout, data_in, count); int iVar1 = mxkCryptCalcHashWithHmacSha1(key, hash, &nout, data_in, count);
if (err == -2 || nout != HMAC_SUM_SIZE) return -2; if (iVar1 != -2 && nout == 20) {
memcpy(hash_out, hash, 20);
memcpy_s(computedHash, sizeof *computedHash, hash, HMAC_SUM_SIZE);
return 0; return 0;
} }
return -2;
}
int mxkN2CmdWriteData(unsigned char addr, void *data, unsigned short nbytes, int mxkN2CmdWriteData(unsigned char addr, unsigned char *data, unsigned short nbytes,
unsigned short *nbytesOut) { unsigned short *nbytesOut) {
unsigned int ptr_; unsigned int ptr_;
unsigned char nstep; unsigned char nstep;
int status; int status;
unsigned short position; unsigned short position;
if (mxkSmbusRequestMutex() != 0) { if (mxkSmbusRequestMutex() != 0) return -6;
amiDebugLog("Error: mxkSmbusRequestMutex");
return -6;
}
status = 0; status = 0;
position = 0; position = 0;
@ -204,14 +178,14 @@ int mxkN2CmdWriteData(unsigned char addr, void *data, unsigned short nbytes,
if ((int)(nbytes - ptr_) < 5) { if ((int)(nbytes - ptr_) < 5) {
nstep = (byte)(nbytes - ptr_); nstep = (byte)(nbytes - ptr_);
if (nstep != 1) goto LAB_0040ae51; if (nstep != 1) goto LAB_0040ae51;
status = mxkSmbusWriteByte(addr, 0xcc, ((unsigned char *)data)[ptr_]); status = mxkSmbusWriteByte(addr, 0xcc, data[ptr_]);
} else { } else {
nstep = 4; nstep = 4;
LAB_0040ae51: LAB_0040ae51:
status = mxkSmbusI2CWriteBlock(addr, 0xcc, &((unsigned char *)data)[ptr_], nstep); status = mxkSmbusI2CWriteBlock(addr, 0xcc, data + ptr_, nstep);
} }
if (status != 0) { if (status != 0) {
amiDebugLog("Error: Data write failed. Position %d. ErrorCode %d.", position, amiDebugLog("Error: Data write failed. Position %d. ErrorCode %d.\n", position,
status); status);
break; break;
@ -222,410 +196,118 @@ int mxkN2CmdWriteData(unsigned char addr, void *data, unsigned short nbytes,
} }
*nbytesOut = position; *nbytesOut = position;
if (mxkSmbusReleaseMutex() != 0) { if (!mxkSmbusReleaseMutex()) return -6;
amiDebugLog("Error: mxkSmbusReleaseMutex");
return -6;
}
return 0; return 0;
} }
int mxkN2CmdWriteCommand(PN2Nonce_t requestNonce, PHmacSum_t hmacSalt, N2Tag_t tag, int mxkN2CmdWriteCommand(unsigned char *param_1, unsigned char *packet, unsigned short tag,
N2Command_t command, PHmacKey_t hmacKey, unsigned char addr, unsigned short command, unsigned char *auth_key, unsigned char addr,
N2Byte_t *data, unsigned short nbytes) { void *data, size_t nbytes) {
Sha1Sum_t sha1sum; int iVar1;
N2Packet_t packet; unsigned short real_tag;
int ret; unsigned short paramsize;
N2Packet_t cmd;
if (data == NULL && nbytes != 0) return -2; if (data == NULL && nbytes != 0) return -2;
N2PacketFooter_t *footer = (N2PacketFooter_t *)(packet.m_Body + nbytes); 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);
ZeroMemory(&packet, sizeof packet); // SHA1(header | data)
unsigned short paramsize = unsigned char packet_sha[20];
N2_HEADER_SIZE + nbytes + mxkN2UtilSha1Many(packet_sha, 1, &cmd, nbytes + 6);
(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) { if (tag == N2_TAG_RQU_COMMAND) {
memcpy_s(footer->rqu.m_ShaSum, sizeof footer->rqu.m_ShaSum, sha1sum, sizeof sha1sum); memcpy(cmd.m_Body, packet_sha, 20);
} else { } else {
if (requestNonce == NULL || hmacKey == NULL) return -2; 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);
mxkN2GetPacketNonce(requestNonce); puts("Dodgy HMAC");
memcpy_s(footer->sign.m_Nonce, sizeof footer->sign.m_Nonce, requestNonce, exit(1);
sizeof *requestNonce);
mxkN2UtilHmacPacket(&sha1sum, hmacSalt, &footer->sign.m_Nonce, hmacKey,
&footer->sign.m_Hmac);
} }
unsigned short nBytesOut; unsigned short nWrote;
ret = mxkN2CmdWriteData(addr, &packet, paramsize, &nBytesOut); iVar1 = mxkN2CmdWriteData(addr, (unsigned char *)&cmd, paramsize, &nWrote);
if (ret != 0) { if (iVar1 == 0) {
amiDebugLog("Error: Data write failed. ErrorCode %d.", ret); iVar1 = 0;
return -8;
}
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 { } else {
if (requestNonce == NULL || hmacKey == NULL) return -2; amiDebugLog("Error: Data write failed. ErrorCode %d.", iVar1);
iVar1 = -8;
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); return iVar1;
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 mxkN2CmdEnableSession(void) {
N2Nonce_t nonce; int ret;
unsigned char local_18[20];
CheckN2Init; if (!MXK_N2_INIT) {
amiDebugLog("Error: Uninitialized.");
return -3;
}
int err; ret = mxkN2CmdWriteCommand(NULL, local_18, N2_TAG_RQU_COMMAND, N2_ORD_ENABLE_SESSION, NULL,
err = mxkN2CmdWriteCommand(&nonce, NULL, N2_TAG_RQU_COMMAND, N2_ORD_ENABLE_SESSION, NULL,
N2DeviceInfo.m_Addr, NULL, 0); N2DeviceInfo.m_Addr, NULL, 0);
if (err != 0) return err; if (ret != 0) return ret;
Sleep(32); Sleep(32);
err = mxkN2CmdReadResponce(&nonce, NULL, N2_TAG_RQU_COMMAND, N2_ORD_ENABLE_SESSION, NULL, // TODO: ASAP
N2DeviceInfo.m_Addr, &N2DeviceInfo.m_HmacSalt, 20); // ret = mxkN2CmdReadResponce(local_18, NULL, N2_TAG_RQU_COMMAND, N2_ORD_ENABLE_SESSION, NULL,
if (err != 0) return err; // N2DeviceInfo.m_Addr, N2DeviceInfo.m_HmacOut, 20);
if (ret != 0) return ret;
Sleep(16); Sleep(16);
return 0; 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) { int mxkN2Authentication(void) {
N2AuthKey_t authKey; // TODO: ASAP
AESKey_t enc_key; // unsigned char auth_key[20];
// unsigned char enc_key[32];
if (!MXK_HAS_INIT) { if (!MXK_HAS_INIT) {
amiDebugLog("No Init Error!!"); amiDebugLog("No Init Error!!");
return -3; return -3;
} }
int err; int ErrorCode;
err = mxkN2CmdEnableSession();
if (err != 0) { ErrorCode = mxkN2CmdEnableSession();
mxkN2GetErrorCode(); if (ErrorCode != 0) {
amiDebugLog("Error: mxkN2CmdEnableSession(). ErrorCode %d", err); // mxkN2GetErrorCode();
amiDebugLog("Error: mxkN2CmdEnableSession(). ErrorCode %d", ErrorCode);
return -5; return -5;
} }
unsigned char authLevel; // _randomBytes(auth_key, sizeof auth_key);
mxkN2CmdGetAuthLevel(&authLevel); // ErrorCode = mxkN2CmdSetAuthKey(auth_key);
printf("Achieved auth level: %d\n", authLevel); // if (ErrorCode != 0) {
// mxkN2GetErrorCode();
// amiDebugLog("Error: mxkN2CmdSetAuthKey(). ErrorCode %d", ErrorCode);
// return -5;
// }
_randomBytes(authKey, sizeof authKey); // _randomBytes(enc_key, sizeof enc_key);
err = mxkN2CmdSetAuthKey(&authKey); // ErrorCode = mxkN2CmdSetEncKey(enc_key);
if (err != 0) { // if (ErrorCode != 0) {
mxkN2GetErrorCode(); // mxkN2GetErrorCode();
amiDebugLog("Error: mxkN2CmdSetAuthKey(). ErrorCode %d", err); // amiDebugLog("Error: mxkN2CmdSetEncKey().ErrorCode %d", ErrorCode);
// return -5;
// }
// unsigned char auth_level;
// ErrorCode = mxkN2CmdGetAuthLevel(&auth_level);
// if (ErrorCode == 0 && auth_level == 3) return 0;
// mxkN2GetErrorCode();
// amiDebugLog("Error: mxkN2CmdGetAuthLevel().ErrorCode %d", ErrorCode);
return -5; return -5;
} }
mxkN2CmdGetAuthLevel(&authLevel);
printf("Achieved auth level: %d\n", authLevel);
_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;
}

View File

@ -1,72 +1,25 @@
#pragma once #pragma once
#include <stdint.h>
#include <varargs.h> #include <varargs.h>
#include "mxkCrypt.h" void _randomBytes(unsigned char *buf, int nbytes);
#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, int mxkN2UtilVCatenateData(unsigned char *out, size_t *count, unsigned int numStreams,
va_list args); va_list args);
void mxkN2UtilCatenateData(unsigned char *concatinated, size_t *count, unsigned int numStreams, void mxkN2UtilCatenateData(unsigned char *concatinated, size_t *count, unsigned int numStreams,
...); ...);
void mxkN2UtilSha1Many(PSha1Sum_t sum, int numStreams, ...); void mxkN2UtilSha1Many(unsigned char *sum, int numStreams, ...);
int mxkN2UtilHmacPacket(PSha1Sum_t packetSha, PHmacSum_t hmacSalt, PN2Nonce_t nonce, PHmacKey_t key, int mxkN2UtilHmacPacket(void *val1, unsigned char *sha1, void *nonce, void *key,
PHmacSum_t computedHash); unsigned char *hash_out);
int mxkN2CmdWriteCommand(PN2Nonce_t nonce, PHmacSum_t hmacSalt, N2Tag_t tag, N2Command_t command, int mxkN2CmdWriteCommand(unsigned char *param_1, unsigned char *packet, unsigned short tag,
PHmacKey_t hmacKey, unsigned char addr, N2Byte_t *data, unsigned short command, unsigned char *auth_key, unsigned char addr,
unsigned short nbytes); void *data, size_t nbytes);
int mxkN2CmdEnableSession(void); int mxkN2CmdEnableSession(void);
int mxkN2CmdSetAuthKey(PN2AuthKey_t authKey); int mxkN2CmdSetAuthKey(unsigned char* authKey);
int mxkN2CmdInit(void); int mxkN2CmdInit(void);
int mxkN2CmdSetDeviceInfo(void); int mxkN2CmdSetDeviceInfo(void);
int mxkN2Authentication(void); int mxkN2Authentication(void);
int mxkN2CmdReadKeychipID(N2KeychipId_t *lpKeychipId);
int mxkN2Init(void);
void mxkN2Exit(void);

View File

@ -228,7 +228,7 @@ int mxkSmbusI2CWriteCommand(unsigned char command_code, unsigned char *buffer, s
return tries == 5 ? -9 : 0; return tries == 5 ? -9 : 0;
} }
int mxkSmbusI2CReadBlock(unsigned char smbAddress, unsigned char block, unsigned char *buffer, bool mxkSmbusI2CReadBlock(unsigned char smbAddress, unsigned char block, unsigned char *buffer,
unsigned char nbytes) { unsigned char nbytes) {
DWORD nBytesReturned; DWORD nBytesReturned;
smb_packet packet; smb_packet packet;
@ -244,10 +244,10 @@ int mxkSmbusI2CReadBlock(unsigned char smbAddress, unsigned char block, unsigned
if (!succ || nBytesReturned != sizeof packet) return false; if (!succ || nBytesReturned != sizeof packet) return false;
if (packet.status == 0) { if (packet.status == 0) {
memcpy(buffer, packet.data, nbytes); memcpy(buffer, packet.data, nbytes);
return 0; return true;
} }
if (packet.status != 24) return false; if (packet.status != 24) return false;
Sleep(16); Sleep(16);
} }
return -8; return false;
} }

View File

@ -11,7 +11,7 @@ int mxkSmbusI2CWriteCommand(unsigned char command_code, unsigned char *buffer, s
int mxkSmbusI2CWriteBlock(unsigned char addr, unsigned char command, unsigned char *buffer, int mxkSmbusI2CWriteBlock(unsigned char addr, unsigned char command, unsigned char *buffer,
unsigned char nbytes); unsigned char nbytes);
int mxkSmbusI2CReadBlock(unsigned char smbAddress, unsigned char block, unsigned char *buffer, bool mxkSmbusI2CReadBlock(unsigned char smbAddress, unsigned char block, unsigned char *buffer,
unsigned char nbytes); unsigned char nbytes);
int mxkSmbusWriteByte(unsigned char v_addr, unsigned char command_code, unsigned char data); int mxkSmbusWriteByte(unsigned char v_addr, unsigned char command_code, unsigned char data);

View File

@ -16,7 +16,7 @@ void miceDumpKCPIC() {
} }
/** /**
* The following sequence is required, within 30 seconds, to avoid SBTR! * The following sequence is required to avoid SBTR!
* *
* amDongleSetupKeychip: * amDongleSetupKeychip:
* keychip.appboot.systemflag=?&cache=0 * keychip.appboot.systemflag=?&cache=0