diff --git a/.gitmodules b/.gitmodules index 3a3621c2d..8edb719bf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -40,3 +40,6 @@ [submodule "third_party/volk"] path = third_party/volk url = https://github.com/zeux/volk.git +[submodule "third_party/aes_128"] + path = third_party/aes_128 + url = https://github.com/openluopworld/aes_128.git diff --git a/premake5.lua b/premake5.lua index 87c481292..4660867f5 100644 --- a/premake5.lua +++ b/premake5.lua @@ -228,6 +228,7 @@ solution("xenia") configurations({"Checked", "Debug", "Release"}) -- Include third party files first so they don't have to deal with gflags. + include("third_party/aes_128.lua") include("third_party/capstone.lua") include("third_party/gflags.lua") include("third_party/glew.lua") diff --git a/src/xenia/kernel/premake5.lua b/src/xenia/kernel/premake5.lua index 772e2730a..0aba1a30e 100644 --- a/src/xenia/kernel/premake5.lua +++ b/src/xenia/kernel/premake5.lua @@ -7,6 +7,7 @@ project("xenia-kernel") kind("StaticLib") language("C++") links({ + "aes_128", "xenia-apu", "xenia-base", "xenia-cpu", diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc index 8f83b3e29..3d78e5b48 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc @@ -21,6 +21,10 @@ #include "third_party/crypto/sha256.cpp" #include "third_party/crypto/sha256.h" +extern "C" { +#include "third_party/aes_128/aes.h" +} + namespace xe { namespace kernel { namespace xboxkrnl { @@ -298,6 +302,128 @@ void XeCryptDes3Cbc(pointer_t state_ptr, lpqword_t inp, } DECLARE_XBOXKRNL_EXPORT1(XeCryptDes3Cbc, kNone, kImplemented); +struct XECRYPT_AES_STATE { + uint8_t keytabenc[11][4][4]; // 0x0 + uint8_t keytabdec[11][4][4]; // 0xB0 +}; +static_assert_size(XECRYPT_AES_STATE, 0x160); + +static inline uint8_t xeXeCryptAesMul2(uint8_t a) { + return (a & 0x80) ? ((a << 1) ^ 0x1B) : (a << 1); +} + +void XeCryptAesKey(pointer_t state_ptr, lpvoid_t key) { + aes_key_schedule_128(key, reinterpret_cast(state_ptr->keytabenc)); + // Decryption key schedule not needed by openluopworld/aes_128, but generated + // to fill the context structure properly. + std::memcpy(state_ptr->keytabdec[0], state_ptr->keytabenc[10], 16); + // Inverse MixColumns. + for (uint32_t i = 1; i < 10; ++i) { + const uint8_t* enc = + reinterpret_cast(state_ptr->keytabenc[10 - i]); + uint8_t* dec = reinterpret_cast(state_ptr->keytabdec[i]); + uint8_t t, u, v; + t = enc[0] ^ enc[1] ^ enc[2] ^ enc[3]; + dec[0] = t ^ enc[0] ^ xeXeCryptAesMul2(enc[0] ^ enc[1]); + dec[1] = t ^ enc[1] ^ xeXeCryptAesMul2(enc[1] ^ enc[2]); + dec[2] = t ^ enc[2] ^ xeXeCryptAesMul2(enc[2] ^ enc[3]); + dec[3] = t ^ enc[3] ^ xeXeCryptAesMul2(enc[3] ^ enc[0]); + u = xeXeCryptAesMul2(xeXeCryptAesMul2(enc[0] ^ enc[2])); + v = xeXeCryptAesMul2(xeXeCryptAesMul2(enc[1] ^ enc[3])); + t = xeXeCryptAesMul2(u ^ v); + dec[0] ^= t ^ u; + dec[1] ^= t ^ v; + dec[2] ^= t ^ u; + dec[3] ^= t ^ v; + t = enc[4] ^ enc[5] ^ enc[6] ^ enc[7]; + dec[4] = t ^ enc[4] ^ xeXeCryptAesMul2(enc[4] ^ enc[5]); + dec[5] = t ^ enc[5] ^ xeXeCryptAesMul2(enc[5] ^ enc[6]); + dec[6] = t ^ enc[6] ^ xeXeCryptAesMul2(enc[6] ^ enc[7]); + dec[7] = t ^ enc[7] ^ xeXeCryptAesMul2(enc[7] ^ enc[4]); + u = xeXeCryptAesMul2(xeXeCryptAesMul2(enc[4] ^ enc[6])); + v = xeXeCryptAesMul2(xeXeCryptAesMul2(enc[5] ^ enc[7])); + t = xeXeCryptAesMul2(u ^ v); + dec[4] ^= t ^ u; + dec[5] ^= t ^ v; + dec[6] ^= t ^ u; + dec[7] ^= t ^ v; + t = enc[8] ^ enc[9] ^ enc[10] ^ enc[11]; + dec[8] = t ^ enc[8] ^ xeXeCryptAesMul2(enc[8] ^ enc[9]); + dec[9] = t ^ enc[9] ^ xeXeCryptAesMul2(enc[9] ^ enc[10]); + dec[10] = t ^ enc[10] ^ xeXeCryptAesMul2(enc[10] ^ enc[11]); + dec[11] = t ^ enc[11] ^ xeXeCryptAesMul2(enc[11] ^ enc[8]); + u = xeXeCryptAesMul2(xeXeCryptAesMul2(enc[8] ^ enc[10])); + v = xeXeCryptAesMul2(xeXeCryptAesMul2(enc[9] ^ enc[11])); + t = xeXeCryptAesMul2(u ^ v); + dec[8] ^= t ^ u; + dec[9] ^= t ^ v; + dec[10] ^= t ^ u; + dec[11] ^= t ^ v; + t = enc[12] ^ enc[13] ^ enc[14] ^ enc[15]; + dec[12] = t ^ enc[12] ^ xeXeCryptAesMul2(enc[12] ^ enc[13]); + dec[13] = t ^ enc[13] ^ xeXeCryptAesMul2(enc[13] ^ enc[14]); + dec[14] = t ^ enc[14] ^ xeXeCryptAesMul2(enc[14] ^ enc[15]); + dec[15] = t ^ enc[15] ^ xeXeCryptAesMul2(enc[15] ^ enc[12]); + u = xeXeCryptAesMul2(xeXeCryptAesMul2(enc[12] ^ enc[14])); + v = xeXeCryptAesMul2(xeXeCryptAesMul2(enc[13] ^ enc[15])); + t = xeXeCryptAesMul2(u ^ v); + dec[12] ^= t ^ u; + dec[13] ^= t ^ v; + dec[14] ^= t ^ u; + dec[15] ^= t ^ v; + } + std::memcpy(state_ptr->keytabdec[10], state_ptr->keytabenc[0], 16); + // TODO(Triang3l): Verify the order in keytabenc and everything in keytabdec. +} +DECLARE_XBOXKRNL_EXPORT1(XeCryptAesKey, kNone, kImplemented); + +void XeCryptAesEcb(pointer_t state_ptr, lpvoid_t inp_ptr, + lpvoid_t out_ptr, dword_t encrypt) { + const uint8_t* keytab = + reinterpret_cast(state_ptr->keytabenc); + if (encrypt) { + aes_encrypt_128(keytab, inp_ptr, out_ptr); + } else { + aes_decrypt_128(keytab, inp_ptr, out_ptr); + } +} +DECLARE_XBOXKRNL_EXPORT1(XeCryptAesEcb, kNone, kImplemented); + +void XeCryptAesCbc(pointer_t state_ptr, lpvoid_t inp_ptr, + dword_t inp_size, lpvoid_t out_ptr, lpvoid_t feed_ptr, + dword_t encrypt) { + const uint8_t* keytab = + reinterpret_cast(state_ptr->keytabenc); + const uint8_t* inp = inp_ptr.as(); + uint8_t* out = out_ptr.as(); + uint8_t* feed = feed_ptr.as(); + if (encrypt) { + for (uint32_t i = 0; i < inp_size; i += 16) { + for (uint32_t j = 0; j < 16; ++j) { + feed[j] ^= inp[j]; + } + aes_encrypt_128(keytab, feed, feed); + std::memcpy(out, feed, 16); + inp += 16; + out += 16; + } + } else { + for (uint32_t i = 0; i < inp_size; i += 16) { + // In case inp == out. + uint8_t tmp[16]; + std::memcpy(tmp, inp, 16); + aes_decrypt_128(keytab, inp, out); + for (uint32_t j = 0; j < 16; ++j) { + out[j] ^= feed[j]; + } + std::memcpy(feed, tmp, 16); + inp += 16; + out += 16; + } + } +} +DECLARE_XBOXKRNL_EXPORT1(XeCryptAesCbc, kNone, kImplemented); + void XeCryptHmacSha(lpvoid_t key, dword_t key_size_in, lpvoid_t inp_1, dword_t inp_1_size, lpvoid_t inp_2, dword_t inp_2_size, lpvoid_t inp_3, dword_t inp_3_size, lpvoid_t out, diff --git a/third_party/aes_128 b/third_party/aes_128 new file mode 160000 index 000000000..b5b7f559c --- /dev/null +++ b/third_party/aes_128 @@ -0,0 +1 @@ +Subproject commit b5b7f559cf4b1acbb506a7a8752bbe4adfdc3274 diff --git a/third_party/aes_128.lua b/third_party/aes_128.lua new file mode 100644 index 000000000..6f7a00e5f --- /dev/null +++ b/third_party/aes_128.lua @@ -0,0 +1,15 @@ +group("third_party") +project("aes_128") + uuid("b50458bf-dd83-4c1a-8cad-61f5fbbfd720") + kind("StaticLib") + language("C") + defines({ + "_LIB", + }) + includedirs({ + "aes_128", + }) + files({ + "aes_128/aes.h", + "aes_128/unroll/aes.c", + })