diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc index 410a9ea23..8f83b3e29 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc @@ -25,11 +25,62 @@ namespace xe { namespace kernel { namespace xboxkrnl { +typedef struct { + uint8_t S[256]; // 0x0 + uint8_t i; // 0x100 + uint8_t j; // 0x101 +} XECRYPT_RC4_STATE; +static_assert_size(XECRYPT_RC4_STATE, 0x102); + +void XeCryptRc4Key(pointer_t rc4_ctx, lpvoid_t key, + dword_t key_size) { + // Setup RC4 state + rc4_ctx->i = rc4_ctx->j = 0; + for (uint32_t x = 0; x < 0x100; x++) { + rc4_ctx->S[x] = (uint8_t)x; + } + + uint32_t idx = 0; + for (uint32_t x = 0; x < 0x100; x++) { + idx = (idx + rc4_ctx->S[x] + key[x % 0x10]) % 0x100; + uint8_t temp = rc4_ctx->S[idx]; + rc4_ctx->S[idx] = rc4_ctx->S[x]; + rc4_ctx->S[x] = temp; + } +} +DECLARE_XBOXKRNL_EXPORT1(XeCryptRc4Key, kNone, kImplemented); + +void XeCryptRc4Ecb(pointer_t rc4_ctx, lpvoid_t data, + dword_t size) { + // Crypt data + for (uint32_t idx = 0; idx < size; idx++) { + rc4_ctx->i = (rc4_ctx->i + 1) % 0x100; + rc4_ctx->j = (rc4_ctx->j + rc4_ctx->S[rc4_ctx->i]) % 0x100; + uint8_t temp = rc4_ctx->S[rc4_ctx->i]; + rc4_ctx->S[rc4_ctx->i] = rc4_ctx->S[rc4_ctx->j]; + rc4_ctx->S[rc4_ctx->j] = temp; + + uint8_t a = data[idx]; + uint8_t b = + rc4_ctx->S[(rc4_ctx->S[rc4_ctx->i] + rc4_ctx->S[rc4_ctx->j]) % 0x100]; + data[idx] = (uint8_t)(a ^ b); + } +} +DECLARE_XBOXKRNL_EXPORT1(XeCryptRc4Ecb, kNone, kImplemented); + +void XeCryptRc4(lpvoid_t key, dword_t key_size, lpvoid_t data, dword_t size) { + XECRYPT_RC4_STATE rc4_ctx; + XeCryptRc4Key(&rc4_ctx, key, key_size); + XeCryptRc4Ecb(&rc4_ctx, data, size); +} +DECLARE_XBOXKRNL_EXPORT1(XeCryptRc4, kNone, kImplemented); + typedef struct { xe::be count; // 0x0 xe::be state[5]; // 0x4 uint8_t buffer[64]; // 0x18 } XECRYPT_SHA_STATE; +static_assert_size(XECRYPT_SHA_STATE, 0x58); void InitSha1(sha1::SHA1* sha, const XECRYPT_SHA_STATE* state) { uint32_t digest[5];