/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2024 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include #include "xenia/kernel/util/crypto_utils.h" #include "third_party/crypto/TinySHA1.hpp" namespace xe { namespace kernel { namespace util { uint8_t xekey_0x19[] = {0xE1, 0xBC, 0x15, 0x9C, 0x73, 0xB1, 0xEA, 0xE9, 0xAB, 0x31, 0x70, 0xF3, 0xAD, 0x47, 0xEB, 0xF3}; uint8_t xekey_0x19_devkit[] = {0xDA, 0xB6, 0x9A, 0xD9, 0x8E, 0x28, 0x76, 0x4F, 0x97, 0x7E, 0xE2, 0x48, 0x7E, 0x4F, 0x3F, 0x68}; const uint8_t* GetXeKey(uint32_t idx, bool devkit) { if (idx != 0x19) { return nullptr; } return devkit ? xekey_0x19_devkit : xekey_0x19; } void HmacSha(const uint8_t* key, uint32_t key_size_in, const uint8_t* inp_1, uint32_t inp_1_size, const uint8_t* inp_2, uint32_t inp_2_size, const uint8_t* inp_3, uint32_t inp_3_size, uint8_t* out, uint32_t out_size) { uint32_t key_size = key_size_in; sha1::SHA1 sha; uint8_t kpad_i[0x40]; uint8_t kpad_o[0x40]; uint8_t tmp_key[0x40]; std::memset(kpad_i, 0x36, 0x40); std::memset(kpad_o, 0x5C, 0x40); // Setup HMAC key // If > block size, use its hash if (key_size > 0x40) { sha1::SHA1 sha_key; sha_key.processBytes(key, key_size); sha_key.finalize((uint8_t*)tmp_key); key_size = 0x14u; } else { std::memcpy(tmp_key, key, key_size); } for (uint32_t i = 0; i < key_size; i++) { kpad_i[i] = tmp_key[i] ^ 0x36; kpad_o[i] = tmp_key[i] ^ 0x5C; } // Inner sha.processBytes(kpad_i, 0x40); if (inp_1_size) { sha.processBytes(inp_1, inp_1_size); } if (inp_2_size) { sha.processBytes(inp_2, inp_2_size); } if (inp_3_size) { sha.processBytes(inp_3, inp_3_size); } uint8_t digest[0x14]; sha.finalize(digest); sha.reset(); // Outer sha.processBytes(kpad_o, 0x40); sha.processBytes(digest, 0x14); sha.finalize(digest); std::memcpy(out, digest, std::min((uint32_t)out_size, 0x14u)); } void RC4(const uint8_t* key, uint32_t key_size_in, const uint8_t* data, uint32_t data_size, uint8_t* out, uint32_t out_size) { uint8_t tmp_key[0x10]; uint32_t sbox_size; uint8_t sbox[0x100]; uint32_t i; uint32_t j; // Setup RC4 session... std::memcpy(tmp_key, key, 0x10); i = j = 0; sbox_size = 0x100; for (uint32_t x = 0; x < sbox_size; x++) { sbox[x] = (uint8_t)x; } uint32_t idx = 0; for (uint32_t x = 0; x < sbox_size; x++) { idx = (idx + sbox[x] + key[x % 0x10]) % sbox_size; uint8_t temp = sbox[idx]; sbox[idx] = sbox[x]; sbox[x] = temp; } // Crypt data for (uint32_t idx = 0; idx < data_size; idx++) { i = (i + 1) % sbox_size; j = (j + sbox[i]) % sbox_size; uint8_t temp = sbox[i]; sbox[i] = sbox[j]; sbox[j] = temp; uint8_t a = data[idx]; uint8_t b = sbox[(sbox[i] + sbox[j]) % sbox_size]; out[idx] = (uint8_t)(a ^ b); } } } // namespace util } // namespace kernel } // namespace xe