[Kernel] Move HmacSha function to seperate file, add RC4
This commit is contained in:
parent
fa61106984
commit
981eff5902
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
#include <algorithm>
|
||||
|
||||
#include "xenia/kernel/util/crypto_utils.h"
|
||||
#include "xenia/xbox.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
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace util {
|
||||
|
||||
const uint8_t* GetXeKey(uint32_t idx, bool devkit = false);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
} // namespace util
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/util/crypto_utils.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
@ -428,75 +429,17 @@ 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,
|
||||
dword_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));
|
||||
util::HmacSha(key, key_size_in, inp_1, inp_1_size, inp_2, inp_2_size, inp_3,
|
||||
inp_3_size, out, out_size);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(XeCryptHmacSha, kNone, kImplemented);
|
||||
|
||||
// Keys
|
||||
// TODO: Array of keys we need
|
||||
|
||||
// Retail key 0x19
|
||||
static const uint8_t key19[] = {0xE1, 0xBC, 0x15, 0x9C, 0x73, 0xB1, 0xEA, 0xE9,
|
||||
0xAB, 0x31, 0x70, 0xF3, 0xAD, 0x47, 0xEB, 0xF3};
|
||||
|
||||
dword_result_t XeKeysHmacSha(dword_t key_num, 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,
|
||||
dword_t out_size) {
|
||||
const uint8_t* key = nullptr;
|
||||
if (key_num == 0x19) {
|
||||
key = key19;
|
||||
}
|
||||
const uint8_t* key = util::GetXeKey(key_num);
|
||||
|
||||
if (key) {
|
||||
XeCryptHmacSha((void*)key, 0x10, inp_1, inp_1_size, inp_2, inp_2_size,
|
||||
|
|
Loading…
Reference in New Issue