diff --git a/build/win32/CxbxKrnl.vcxproj b/build/win32/CxbxKrnl.vcxproj
index 060787db3..14ba599ec 100644
--- a/build/win32/CxbxKrnl.vcxproj
+++ b/build/win32/CxbxKrnl.vcxproj
@@ -226,6 +226,7 @@
+
@@ -609,6 +610,7 @@
%(AdditionalIncludeDirectories)
%(PreprocessorDefinitions)
+
%(AdditionalIncludeDirectories)
%(PreprocessorDefinitions)
diff --git a/import/OpenXDK/include/xboxkrnl/xbox.h b/import/OpenXDK/include/xboxkrnl/xbox.h
index adccdda33..f06387847 100644
--- a/import/OpenXDK/include/xboxkrnl/xbox.h
+++ b/import/OpenXDK/include/xboxkrnl/xbox.h
@@ -185,8 +185,19 @@ XBSYSAPI EXPORTNUM(336) VOID NTAPI XcSHAUpdate(UCHAR *pbSHAContext, UCHAR *pbInp
// ******************************************************************
XBSYSAPI EXPORTNUM(337) VOID NTAPI XcSHAFinal(UCHAR *pbSHAContext, UCHAR *pbDigest);
-XBSYSAPI EXPORTNUM(338) VOID *XcRC4Key;
-XBSYSAPI EXPORTNUM(339) VOID *XcRC4Crypt;
+XBSYSAPI EXPORTNUM(338) VOID XcRC4Key
+(
+ IN PUCHAR pbKeyStruct,
+ IN ULONG dwKeyLength,
+ IN PUCHAR pbKey
+);
+
+XBSYSAPI EXPORTNUM(339) VOID XcRC4Crypt
+(
+ IN PUCHAR pbKeyStruct,
+ IN ULONG dwInputLength,
+ IN PUCHAR pbInput
+);
XBSYSAPI EXPORTNUM(340) VOID NTAPI XcHMAC
(
diff --git a/src/CxbxKrnl/EmuKrnl.cpp b/src/CxbxKrnl/EmuKrnl.cpp
index 099997c21..464c06b6a 100644
--- a/src/CxbxKrnl/EmuKrnl.cpp
+++ b/src/CxbxKrnl/EmuKrnl.cpp
@@ -55,6 +55,12 @@ namespace NtDll
#include "EmuNtDll.h"
};
+// ******************************************************************
+// * Declaring this in a header causes errors with xboxkrnl
+// * namespace, so we must declare it within any file that uses it
+// ******************************************************************
+xboxkrnl::KPCR* KeGetPcr();
+
// ******************************************************************
// * 0x0033 - InterlockedCompareExchange()
// ******************************************************************
@@ -200,15 +206,8 @@ XBSYSAPI EXPORTNUM(160) xboxkrnl::UCHAR FASTCALL xboxkrnl::KfRaiseIrql
LOG_FUNC_ONE_ARG(NewIrql);
UCHAR OldIrql;
- KPCR* Pcr = nullptr;
- // Fetch KPCR data structure
- __asm {
- push eax
- mov eax, fs:[0x14]
- mov Pcr, eax
- pop eax
- }
+ KPCR* Pcr = KeGetPcr();
if (NewIrql < Pcr->Irql) {
// TODO: Enable this after KeBugCheck is implemented
diff --git a/src/CxbxKrnl/EmuKrnlKe.cpp b/src/CxbxKrnl/EmuKrnlKe.cpp
index 2e789f66c..2aa96cbfc 100644
--- a/src/CxbxKrnl/EmuKrnlKe.cpp
+++ b/src/CxbxKrnl/EmuKrnlKe.cpp
@@ -57,6 +57,26 @@ namespace NtDll
#include
#include
+// ******************************************************************
+// * KeGetPcr()
+// * NOTE: This is a macro on the Xbox, however we implement it
+// * as a function so it can suit our emulated KPCR structure
+// ******************************************************************
+xboxkrnl::KPCR* KeGetPcr()
+{
+ xboxkrnl::KPCR* Pcr = nullptr;
+
+ __asm {
+ push eax
+ mov eax, fs:[0x14]
+ mov Pcr, eax
+ pop eax
+ }
+
+ return Pcr;
+}
+
+
// ******************************************************************
// * 0x005C - KeAlertResumeThread()
// ******************************************************************
@@ -222,12 +242,7 @@ XBSYSAPI EXPORTNUM(103) xboxkrnl::KIRQL NTAPI xboxkrnl::KeGetCurrentIrql(void)
KIRQL Irql;
- // TODO : Untested :
- __asm
- {
- mov al, byte ptr fs : [24h]
- mov Irql, al
- }
+ Irql = KeGetPcr()->Irql;
RETURN(Irql);
}
@@ -439,13 +454,7 @@ XBSYSAPI EXPORTNUM(129) xboxkrnl::UCHAR NTAPI xboxkrnl::KeRaiseIrqlToDpcLevel()
CxbxKrnlCleanup("Bugcheck: Caller of KeRaiseIrqlToDpcLevel is higher than DISPATCH_LEVEL!");
KIRQL kRet = NULL;
- __asm
- {
- mov al, byte ptr fs:[24h]
- mov kRet, al
- mov al, DISPATCH_LEVEL
- mov byte ptr fs:[24h], al
- }
+ KeGetPcr()->Irql = DISPATCH_LEVEL;
#ifdef _DEBUG_TRACE
DbgPrintf("Raised IRQL to DISPATCH_LEVEL (2).\n");
diff --git a/src/CxbxKrnl/EmuKrnlXc.cpp b/src/CxbxKrnl/EmuKrnlXc.cpp
index a0b7033aa..6294b9d6b 100644
--- a/src/CxbxKrnl/EmuKrnlXc.cpp
+++ b/src/CxbxKrnl/EmuKrnlXc.cpp
@@ -44,6 +44,7 @@ namespace xboxkrnl
#include "Logging.h" // For LOG_FUNC()
#include "EmuKrnlLogging.h"
#include "EmuSha.h" // For A_SHAInit, etc.
+#include "LibRc4.h" // For RC4 Functions
// prevent name collisions
namespace NtDll
@@ -100,6 +101,44 @@ XBSYSAPI EXPORTNUM(337) xboxkrnl::VOID NTAPI xboxkrnl::XcSHAFinal
A_SHAFinal((SHA_CTX*)pbSHAContext, pbDigest);
}
+// ******************************************************************
+// * 0x0152 - XcRC4Key()
+// ******************************************************************
+XBSYSAPI EXPORTNUM(338) xboxkrnl::VOID xboxkrnl::XcRC4Key
+(
+ IN PUCHAR pbKeyStruct,
+ IN ULONG dwKeyLength,
+ IN PUCHAR pbKey
+)
+{
+ LOG_FUNC_BEGIN
+ LOG_FUNC_ARG_OUT(pbKeyStruct)
+ LOG_FUNC_ARG(dwKeyLength)
+ LOG_FUNC_ARG_OUT(pbKey)
+ LOG_FUNC_END;
+
+ Rc4Initialise((Rc4Context*)pbKeyStruct, pbKey, dwKeyLength, 0);
+}
+
+// ******************************************************************
+// * 0x0153 - XcRC4Crypt
+// ******************************************************************
+XBSYSAPI EXPORTNUM(339) xboxkrnl::VOID xboxkrnl::XcRC4Crypt
+(
+ IN PUCHAR pbKeyStruct,
+ IN ULONG dwInputLength,
+ IN PUCHAR pbInput
+)
+{
+ LOG_FUNC_BEGIN
+ LOG_FUNC_ARG_OUT(pbKeyStruct)
+ LOG_FUNC_ARG(dwInputLength)
+ LOG_FUNC_ARG_OUT(pbInput)
+ LOG_FUNC_END;
+
+ Rc4Xor((Rc4Context*)pbKeyStruct, pbInput, pbInput, dwInputLength);
+}
+
// ******************************************************************
// * 0x0154 - XcHMAC()
// ******************************************************************
diff --git a/src/CxbxKrnl/KernelThunk.cpp b/src/CxbxKrnl/KernelThunk.cpp
index aaad5f985..54a075da3 100644
--- a/src/CxbxKrnl/KernelThunk.cpp
+++ b/src/CxbxKrnl/KernelThunk.cpp
@@ -403,8 +403,8 @@ extern "C" CXBXKRNL_API uint32 CxbxKrnl_KernelThunkTable[379] =
(uint32)FUNC(&xboxkrnl::XcSHAInit), // 0x014F (335)
(uint32)FUNC(&xboxkrnl::XcSHAUpdate), // 0x0150 (336)
(uint32)FUNC(&xboxkrnl::XcSHAFinal), // 0x0151 (337)
- (uint32)PANIC(0x0152), // 0x0152 (338) XcRC4Key
- (uint32)PANIC(0x0153), // 0x0153 (339) XcRC4Crypt
+ (uint32)FUNC(&xboxkrnl::XcRC4Key), // 0x0152 (338)
+ (uint32)FUNC(&xboxkrnl::XcRC4Crypt), // 0x0153 (339)
(uint32)FUNC(&xboxkrnl::XcHMAC), // 0x0154 (340)
(uint32)PANIC(0x0155), // 0x0155 (341) XcPKEncPublic
(uint32)PANIC(0x0156), // 0x0156 (342) XcPKDecPrivate
diff --git a/src/CxbxKrnl/LibRc4.cpp b/src/CxbxKrnl/LibRc4.cpp
new file mode 100644
index 000000000..6e3c1f53e
--- /dev/null
+++ b/src/CxbxKrnl/LibRc4.cpp
@@ -0,0 +1,129 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// LibRC4
+//
+// An implementation of RC4 stream cipher
+//
+// This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// IMPORTS
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "LibRc4.h"
+#include
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// INTERNAL FUNCTIONS
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define SwapBytes( Value1, Value2 ) \
+{ \
+ uint8_t temp = Value1; \
+ Value1 = Value2; \
+ Value2 = temp; \
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC FUNCTIONS
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Rc4Initialise
+//
+// Initialises an RC4 cipher and discards the specified number of first bytes.
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+ Rc4Initialise
+ (
+ Rc4Context* Context,
+ void* Key,
+ uint32_t KeySize,
+ uint32_t DropN
+ )
+{
+ uint32_t i;
+ uint32_t j;
+ uint32_t n;
+
+ // Setup key schedule
+ for( i=0; i<256; i++ )
+ {
+ Context->S[i] = (uint8_t)i;
+ }
+
+ j = 0;
+ for( i=0; i<256; i++ )
+ {
+ j = ( j + Context->S[i] + ((uint8_t*)Key)[i % KeySize] ) % 256;
+ SwapBytes( Context->S[i], Context->S[j] );
+ }
+
+ i = 0;
+ j = 0;
+
+ // Drop first bytes (if requested)
+ for( n=0; nS[i] ) % 256;
+ SwapBytes( Context->S[i], Context->S[j] );
+ }
+
+ Context->i = i;
+ Context->j = j;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Rc4Output
+//
+// Outputs the requested number of bytes from the RC4 stream
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+ Rc4Output
+ (
+ Rc4Context* Context,
+ void* Buffer,
+ uint32_t Size
+ )
+{
+ uint32_t n;
+
+ for( n=0; ni = ( Context->i + 1 ) % 256;
+ Context->j = ( Context->j + Context->S[Context->i] ) % 256;
+ SwapBytes( Context->S[Context->i], Context->S[Context->j] );
+
+ ((uint8_t*)Buffer)[n] = Context->S[ (Context->S[Context->i] + Context->S[Context->j]) % 256 ];
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Rc4Xor
+//
+// XORs the RC4 stream with an input buffer and puts the results in an output buffer. This is used for encrypting
+// and decrypting data. InBuffer and OutBuffer can point to the same location for inplace encrypting/decrypting
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+ Rc4Xor
+ (
+ Rc4Context* Context,
+ void* InBuffer,
+ void* OutBuffer,
+ uint32_t Size
+ )
+{
+ uint32_t n;
+
+ for( n=0; ni = ( Context->i + 1 ) % 256;
+ Context->j = ( Context->j + Context->S[Context->i] ) % 256;
+ SwapBytes( Context->S[Context->i], Context->S[Context->j] );
+
+ ((uint8_t*)OutBuffer)[n] = ((uint8_t*)InBuffer)[n]
+ ^ ( Context->S[ (Context->S[Context->i] + Context->S[Context->j]) % 256 ] );
+ }
+}
+
diff --git a/src/CxbxKrnl/LibRc4.h b/src/CxbxKrnl/LibRc4.h
new file mode 100644
index 000000000..79f4c22ab
--- /dev/null
+++ b/src/CxbxKrnl/LibRc4.h
@@ -0,0 +1,78 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// LibRC4
+//
+// An implementation of RC4 stream cipher
+//
+// This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifndef _LibRc4_h_
+#define _LibRc4_h_
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// IMPORTS
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// TYPES
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Rc4Context - This must be initialised using Rc4Initialised. Do not modify the contents of this structure directly.
+typedef struct
+{
+ uint8_t S[256];
+ uint32_t i;
+ uint32_t j;
+} Rc4Context;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC FUNCTIONS
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Rc4Initialise
+//
+// Initialises an RC4 cipher and discards the specified number of first bytes.
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+ Rc4Initialise
+ (
+ Rc4Context* Context,
+ void* Key,
+ uint32_t KeySize,
+ uint32_t DropN
+ );
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Rc4Output
+//
+// Outputs the requested number of bytes from the RC4 stream
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+ Rc4Output
+ (
+ Rc4Context* Context,
+ void* Buffer,
+ uint32_t Size
+ );
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Rc4Xor
+//
+// XORs the RC4 stream with an input buffer and puts the results in an output buffer. This is used for encrypting
+// and decrypting data. InBuffer and OutBuffer can point to the same location for inplace encrypting/decrypting
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+ Rc4Xor
+ (
+ Rc4Context* Context,
+ void* InBuffer,
+ void* OutBuffer,
+ uint32_t Size
+ );
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#endif //_LibRc4_h_
+