[XboxKrnl/Crypt] - Implement XeCrypt & XeKeys Functions (#566)

- Implement XeKeysGetConsoleID, XeKeysGetKeyProperties, XeCryptDesEcb, and XeCryptDesKey.
- Stub XeCryptBnQwBeSigVerify, XeCryptRotSumSha, XeKeysGetKey, and XeKeysConsolePrivateKeySign.
This commit is contained in:
The-Little-Wolf
2026-02-23 00:33:19 -08:00
committed by GitHub
parent 8d5565da8a
commit dd585ca0c8

View File

@@ -14,7 +14,6 @@
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
#include "xenia/xbox.h"
#ifdef XE_PLATFORM_WIN32
#include "xenia/base/platform_win.h" // for bcrypt.h
@@ -38,13 +37,344 @@ namespace xe {
namespace kernel {
namespace xboxkrnl {
typedef struct {
struct XECRYPT_RC4_STATE {
uint8_t S[256]; // 0x0
uint8_t i; // 0x100
uint8_t j; // 0x101
} XECRYPT_RC4_STATE;
};
static_assert_size(XECRYPT_RC4_STATE, 0x102);
struct XECRYPT_SHA_STATE {
xe::be<uint32_t> count; // 0x0
xe::be<uint32_t> state[5]; // 0x4
uint8_t buffer[64]; // 0x18
};
static_assert_size(XECRYPT_SHA_STATE, 0x58);
// TODO: Size of this struct hasn't been confirmed yet.
struct XECRYPT_SHA256_STATE {
xe::be<uint32_t> count; // 0x0
xe::be<uint32_t> state[8]; // 0x4
uint8_t buffer[64]; // 0x24
};
// TODO: Size of this struct hasn't been confirmed yet.
struct XECRYPT_SHA512_STATE {
xe::be<uint64_t> count; // 0x0
xe::be<uint64_t> state[8]; // 0x8
uint8_t buffer[128]; // 0x48
};
struct SHA512_STATE {
uint8_t digest_len;
uint64_t count;
uint8_t buffer[128];
uint64_t state[8];
};
// TODO: Size of this struct hasn't been confirmed yet.
struct XECRYPT_MD5_STATE {
xe::be<uint64_t> count;
xe::be<uint32_t> state[4];
uint8_t buffer[64];
};
struct MD5_STATE {
uint64_t len;
uint8_t block[64];
uint32_t ABCD[4];
};
struct XECRYPT_RSA {
xe::be<uint32_t> size; // size of modulus in 8 byte units
xe::be<uint32_t> public_exponent;
xe::be<uint64_t> pad_8;
// followed by modulus, followed by any private-key data
};
static_assert_size(XECRYPT_RSA, 0x10);
struct XECRYPT_SIG {
xe::be<uint64_t> aqwPad[0x1C];
xe::be<uint8_t> One;
uint8_t Salt[0xA];
uint8_t Hash[0x14];
xe::be<uint8_t> End;
};
static_assert_size(XECRYPT_SIG, 0x100); // size 256
struct XECRYPT_DES_STATE {
uint32_t keytab[16][2];
};
struct XECRYPT_DES3_STATE {
XECRYPT_DES_STATE des_state[3];
};
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);
// Keys
// TODO: Array of keys we need
// Console Serial Number Key - unimplemented
static constexpr uint8_t key14[] = {'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', '1', '0'}; // string
// Retail key 0x19
static constexpr uint8_t key19[] = {0xE1, 0xBC, 0x15, 0x9C, 0x73, 0xB1,
0xEA, 0xE9, 0xAB, 0x31, 0x70, 0xF3,
0xAD, 0x47, 0xEB, 0xF3};
// Pirs Public Key
struct XECRYPT_RSAPUB_2048 {
XECRYPT_RSA Rsa;
xe::be<uint64_t> aqwM[0x20];
};
static_assert_size(XECRYPT_RSAPUB_2048, 0x110);
static constexpr uint8_t key39[] = { // pirs_retail_public
0x00, 0x00, 0x00, 0x20, // cqw
0x00, 0x00, 0x00, 0x03, // dwPubExp
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // qwReserved
// aqwM
0xE6, 0x3B, 0x32, 0xB2, 0x8D, 0x9E, 0x9E, 0xE7, 0x9D, 0xFC, 0x5C, 0x72,
0x41, 0x94, 0x58, 0x47, 0xDE, 0x0D, 0x18, 0x40, 0x72, 0xD6, 0xE3, 0x46,
0x8E, 0xBA, 0x8E, 0xBC, 0x1A, 0x90, 0xAC, 0x20, 0xBA, 0x03, 0x85, 0xB5,
0x1A, 0x3E, 0x25, 0xF9, 0xA6, 0x58, 0xEB, 0xB6, 0xA3, 0xC4, 0xA3, 0xEE,
0xB2, 0xB0, 0xAE, 0x97, 0x69, 0xEB, 0xFE, 0x71, 0xFC, 0x02, 0xAB, 0x77,
0xBA, 0xC8, 0xE6, 0x74, 0xE6, 0x7C, 0x63, 0x0E, 0xAF, 0x4C, 0xF7, 0xE7,
0x11, 0x4A, 0x80, 0x24, 0x72, 0x05, 0x7A, 0x63, 0xD0, 0xF8, 0x91, 0x02,
0xA6, 0xE7, 0x7D, 0x77, 0xC5, 0xA7, 0x9B, 0x08, 0x11, 0x2E, 0xA0, 0x64,
0x45, 0x60, 0x46, 0xBC, 0x36, 0xE1, 0x17, 0x71, 0xBE, 0x66, 0x49, 0x2F,
0xAE, 0x20, 0xA4, 0x76, 0x9C, 0x27, 0x51, 0xCF, 0x4B, 0x34, 0x7A, 0x35,
0xBC, 0xA4, 0xAA, 0x1C, 0x47, 0x4B, 0xF4, 0x97, 0x22, 0x4E, 0x13, 0x24,
0xD3, 0xC1, 0x57, 0xDF, 0x4D, 0x84, 0xB9, 0x18, 0x97, 0x99, 0xAC, 0x00,
0xB3, 0x3D, 0x03, 0x25, 0x60, 0xC8, 0x7A, 0x59, 0xFE, 0x48, 0xFF, 0x28,
0x3D, 0x10, 0xBB, 0x9E, 0x09, 0x06, 0x2A, 0x61, 0x20, 0x2C, 0xF8, 0x72,
0xEB, 0x87, 0xE6, 0xD1, 0xFB, 0xB3, 0x66, 0xFC, 0x4A, 0x02, 0xAE, 0xD4,
0xD8, 0x37, 0xCF, 0xA6, 0x32, 0x25, 0x79, 0x36, 0x0E, 0xF4, 0xED, 0x19,
0xA2, 0x10, 0x27, 0x96, 0x2F, 0x9F, 0xA9, 0x3D, 0xA4, 0x37, 0x30, 0x11,
0x51, 0x83, 0xBD, 0xF7, 0xC7, 0xE5, 0xCE, 0xAA, 0xEC, 0xDE, 0x48, 0xA0,
0x84, 0xF7, 0xB0, 0xF6, 0x4B, 0x8E, 0xF0, 0x89, 0xBD, 0x47, 0x7C, 0x90,
0xDD, 0x88, 0x12, 0x17, 0x40, 0xD2, 0x4E, 0xA6, 0xC6, 0x11, 0x04, 0x1B,
0x57, 0xA8, 0x68, 0xB4, 0x61, 0xF4, 0x1B, 0xC6, 0x8B, 0xE8, 0xD9, 0x20,
0xF2, 0x05, 0xE0, 0x70};
const static std::map<uint16_t, std::span<const uint8_t>> key_vault = {
{0x14, key14},
{0x19, key19},
{0x39, key39},
};
enum X_KEY_INDEX : uint32_t {
MANUFACTURING_MODE = 0x0,
ALTERNATE_KEY_VAULT = 0x1,
RESTRICTED_PRIVILEGES_FLAGS = 0x2,
RESERVED_BYTE3 = 0x3,
ODD_FEATURES = 0x4,
ODD_AUTHTYPE = 0x5,
RESTRICTED_HVEXT_LOADER = 0x6,
POLICY_FLASH_SIZE = 0x7,
POLICY_BUILTIN_USBMU_SIZE = 0x8,
RESERVED_DWORD4 = 0x9,
RESTRICTED_PRIVILEGES = 0xA,
RESERVED_QWORD2 = 0xB,
RESERVED_QWORD3 = 0xC,
RESERVED_QWORD4 = 0xD,
RESERVED_KEY1 = 0xE,
RESERVED_KEY2 = 0xF,
RESERVED_KEY3 = 0x10,
RESERVED_KEY4 = 0x11,
RESERVED_RANDOM_KEY1 = 0x12,
RESERVED_RANDOM_KEY2 = 0x13,
CONSOLE_SERIAL_NUMBER = 0x14,
MOBO_SERIAL_NUMBER = 0x15,
GAME_REGION = 0x16,
CONSOLE_OBFUSCATION_KEY = 0x17,
KEY_OBFUSCATION_KEY = 0x18,
ROAMABLE_OBFUSCATION_KEY = 0x19,
DVD_KEY = 0x1A,
PRIMARY_ACTIVATION_KEY = 0x1B,
SECONDARY_ACTIVATION_KEY = 0x1C,
GLOBAL_DEVICE_2DES_KEY1 = 0x1D,
GLOBAL_DEVICE_2DES_KEY2 = 0x1E,
WIRELESS_CONTROLLER_MS_2DES_KEY1 = 0x1F,
WIRELESS_CONTROLLER_MS_2DES_KEY2 = 0x20,
WIRED_WEBCAM_MS_2DES_KEY1 = 0x21,
WIRED_WEBCAM_MS_2DES_KEY2 = 0x22,
WIRED_CONTROLLER_MS_2DES_KEY1 = 0x23,
WIRED_CONTROLLER_MS_2DES_KEY2 = 0x24,
MEMORY_UNIT_MS_2DES_KEY1 = 0x25,
MEMORY_UNIT_MS_2DES_KEY2 = 0x26,
OTHER_XSM3_DEVICE_MS_2DES_KEY1 = 0x27,
OTHER_XSM3_DEVICE_MS_2DES_KEY2 = 0x28,
WIRELESS_CONTROLLER_3P_2DES_KEY1 = 0x29,
WIRELESS_CONTROLLER_3P_2DES_KEY2 = 0x2A,
WIRED_WEBCAM_3P_2DES_KEY1 = 0x2B,
WIRED_WEBCAM_3P_2DES_KEY2 = 0x2C,
WIRED_CONTROLLER_3P_2DES_KEY1 = 0x2D,
WIRED_CONTROLLER_3P_2DES_KEY2 = 0x2E,
MEMORY_UNIT_3P_2DES_KEY1 = 0x2F,
MEMORY_UNIT_3P_2DES_KEY2 = 0x30,
OTHER_XSM3_DEVICE_3P_2DES_KEY1 = 0x31,
OTHER_XSM3_DEVICE_3P_2DES_KEY2 = 0x32,
CONSOLE_PRIVATE_KEY = 0x33,
XEIKA_PRIVATE_KEY = 0x34,
CARDEA_PRIVATE_KEY = 0x35,
CONSOLE_CERTIFICATE = 0x36,
XEIKA_CERTIFICATE = 0x37,
CARDEA_CERTIFICATE = 0x38,
MAX_KEY_INDEX = 0x39,
// constant keys
CONSTANT_PIRS_KEY = 0x39,
CONSTANT_ALT_MASTER_KEY = 0x3A,
CONSTANT_ALT_LIVE_KEY = 0x3B,
CONSTANT_MASTER_KEY = 0x3C,
CONSTANT_LIVE_KEY = 0x3D,
CONSTANT_XB1_GREEN_KEY = 0x3E,
CONSTANT_SATA_DISK_SECURITY_KEY = 0x3F,
CONSTANT_DEVICE_REVOCATION_KEY = 0x40,
CONSTANT_XMACS_KEY = 0x41,
CONSTANT_REVOCATION_LIST_NONCE = 0x42,
CONSTANT_CROSS_PLATFORM_SYSLINK_KEY = 0x43,
// special keys
SPECIAL_KEY_VAULT_SIGNATURE = 0x44,
SPECIAL_SECROM_DIGEST = 0x45,
SPECIAL_SECDATA = 0x46,
SPECIAL_DVD_FIRMWARE_KEY = 0x47,
SPECIAL_DEBUG_UNLOCK = 0x48,
MAX_CONSTANT_INDEX = 0x49,
// title keys
TITLE_KEYS_BASE = 0xE0,
TITLE_KEYS_LIMIT = 0xE8,
TITLE_KEYS_RESET = 0xF0,
// secured keys
SECURED_DATA_BASE = 0x1000,
SECURED_DATA_LIMIT = 0x2000,
};
// https://github.com/emoose/ExCrypt/blob/master/src/exkeys.cpp#L7
std::map<uint32_t, std::tuple<uint32_t, uint32_t>> X_Key_Properties = {
{MANUFACTURING_MODE, {0x8, 0x1}},
{ALTERNATE_KEY_VAULT, {0x9, 0x1}},
{RESTRICTED_PRIVILEGES_FLAGS, {0xA, 0x1}},
{RESERVED_BYTE3, {0xB, 0x1}},
{ODD_FEATURES, {0xC, 0x2}},
{ODD_AUTHTYPE, {0xE, 0x2}},
{RESTRICTED_HVEXT_LOADER, {0x10, 0x4}},
{POLICY_FLASH_SIZE, {0x14, 0x4}},
{POLICY_BUILTIN_USBMU_SIZE, {0x18, 0x4}},
{RESERVED_DWORD4, {0x1C, 0x4}},
{RESTRICTED_PRIVILEGES, {0x20, 0x8}},
{RESERVED_QWORD2, {0x28, 0x8}},
{RESERVED_QWORD3, {0x30, 0x8}},
{RESERVED_QWORD4, {0x38, 0x8}},
{RESERVED_KEY1, {0x40, 0x10}},
{RESERVED_KEY2, {0x50, 0x10}},
{RESERVED_KEY3, {0x60, 0x10}},
{RESERVED_KEY4, {0x70, 0x10}},
{RESERVED_RANDOM_KEY1, {0x80, 0x10}},
{RESERVED_RANDOM_KEY2, {0x90, 0x10}},
{CONSOLE_SERIAL_NUMBER, {0xA0, 0xC}},
{MOBO_SERIAL_NUMBER, {0xAC, 0xC}},
{GAME_REGION, {0xB8, 0x2}},
// 6 bytes padding
{CONSOLE_OBFUSCATION_KEY, {0xC0, 0x10}},
{KEY_OBFUSCATION_KEY, {0xD0, 0x10}},
{ROAMABLE_OBFUSCATION_KEY, {0xE0, 0x10}},
{DVD_KEY, {0xF0, 0x10}},
{PRIMARY_ACTIVATION_KEY, {0x100, 0x18}},
{SECONDARY_ACTIVATION_KEY, {0x118, 0x10}},
{GLOBAL_DEVICE_2DES_KEY1, {0x128, 0x10}},
{GLOBAL_DEVICE_2DES_KEY2, {0x138, 0x10}},
{WIRELESS_CONTROLLER_MS_2DES_KEY1, {0x148, 0x10}},
{WIRELESS_CONTROLLER_MS_2DES_KEY2, {0x158, 0x10}},
{WIRED_WEBCAM_MS_2DES_KEY1, {0x168, 0x10}},
{WIRED_WEBCAM_MS_2DES_KEY2, {0x178, 0x10}},
{WIRED_CONTROLLER_MS_2DES_KEY1, {0x188, 0x10}},
{WIRED_CONTROLLER_MS_2DES_KEY2, {0x198, 0x10}},
{MEMORY_UNIT_MS_2DES_KEY1, {0x1A8, 0x10}},
{MEMORY_UNIT_MS_2DES_KEY2, {0x1B8, 0x10}},
{OTHER_XSM3_DEVICE_MS_2DES_KEY1, {0x1C8, 0x10}},
{OTHER_XSM3_DEVICE_MS_2DES_KEY2, {0x1D8, 0x10}},
{WIRELESS_CONTROLLER_3P_2DES_KEY1, {0x1E8, 0x10}},
{WIRELESS_CONTROLLER_3P_2DES_KEY2, {0x1F8, 0x10}},
{WIRED_WEBCAM_3P_2DES_KEY1, {0x208, 0x10}},
{WIRED_WEBCAM_3P_2DES_KEY2, {0x218, 0x10}},
{WIRED_CONTROLLER_3P_2DES_KEY1, {0x228, 0x10}},
{WIRED_CONTROLLER_3P_2DES_KEY2, {0x238, 0x10}},
{MEMORY_UNIT_3P_2DES_KEY1, {0x248, 0x10}},
{MEMORY_UNIT_3P_2DES_KEY2, {0x258, 0x10}},
{OTHER_XSM3_DEVICE_3P_2DES_KEY1, {0x268, 0x10}},
{OTHER_XSM3_DEVICE_3P_2DES_KEY2, {0x278, 0x10}},
{CONSOLE_PRIVATE_KEY, {0x288, 0x1D0}},
{XEIKA_PRIVATE_KEY, {0x458, 0x390}},
{CARDEA_PRIVATE_KEY, {0x7E8, 0x1D0}},
{CONSOLE_CERTIFICATE, {0x9B8, 0x1A8}},
{XEIKA_CERTIFICATE, {0xB60, 0x1288}},
{SPECIAL_KEY_VAULT_SIGNATURE, {0x1DF8, 0x100}},
{CARDEA_CERTIFICATE, {0x1EE8, 0x2108}},
};
static const uint8_t xe_key_obfuscation_key[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#pragma pack(push, 1)
struct XE_CONSOLE_ID {
union {
struct {
uint8_t RefurbBits : 4;
uint8_t ManufactureMonth : 4;
uint32_t ManufactureYear : 4;
uint32_t MacIndex3 : 8;
uint32_t MacIndex4 : 8;
uint32_t MacIndex5 : 8;
uint32_t Crc : 4;
};
uint8_t Data[5];
};
};
#pragma pack(pop)
struct X_CONSOLE_PUBLIC_KEY {
uint8_t public_exponent[0x4]; // 0x0 sz:0x4
uint8_t modulus[0x80]; // 0x4 sz:0x80
}; // size 132
static_assert_size(X_CONSOLE_PUBLIC_KEY, 0x84);
enum XConsoleType : uint32_t {
Invalid = 0,
Devkit = 1,
Retail = 2,
Testkit = 0x40000001,
RecoveredDevkit = 0x80000001,
Pre1888Devkit = 0x80000002
};
struct XE_CONSOLE_CERTIFICATE {
xe::be<uint16_t> cert_size; // 0x0 sz:0x2
XE_CONSOLE_ID console_id; // 0x2 sz:0x5
uint8_t console_part_number[11]; // 0x7 sz:0xB
uint8_t reserved[4]; // 0x12 sz:0x4
xe::be<uint16_t> privileges; // 0x16 sz:0x2
xe::be<XConsoleType> console_type; // 0x18 sz:0x4
uint8_t manufacture_date[8]; // 0x1C sz:0x8
X_CONSOLE_PUBLIC_KEY console_public_key; // 0x24 sz:0x84
XECRYPT_SIG signature; // 0xA8 sz:0x100
}; // size 424
static_assert_size(XE_CONSOLE_CERTIFICATE, 0x1A8);
struct XE_CONSOLE_SIGNATURE {
XE_CONSOLE_CERTIFICATE console_certificate;
uint8_t signature[0x80];
};
static_assert_size(XE_CONSOLE_SIGNATURE, 0x228);
void XeCryptRc4Key_entry(pointer_t<XECRYPT_RC4_STATE> rc4_ctx, lpvoid_t key,
dword_t key_size) {
// Setup RC4 state
@@ -89,13 +419,6 @@ void XeCryptRc4_entry(lpvoid_t key, dword_t key_size, lpvoid_t data,
}
DECLARE_XBOXKRNL_EXPORT1(XeCryptRc4, kNone, kImplemented);
typedef struct {
xe::be<uint32_t> count; // 0x0
xe::be<uint32_t> 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];
std::copy(std::begin(state->state), std::end(state->state), digest);
@@ -196,13 +519,6 @@ void XeCryptMd5_entry(lpvoid_t input_1, dword_t input_1_size, lpvoid_t input_2,
}
DECLARE_XBOXKRNL_EXPORT1(XeCryptMd5, kNone, kImplemented);
// TODO: Size of this struct hasn't been confirmed yet.
typedef struct {
xe::be<uint32_t> count; // 0x0
xe::be<uint32_t> state[8]; // 0x4
uint8_t buffer[64]; // 0x24
} XECRYPT_SHA256_STATE;
void XeCryptSha256Init_entry(pointer_t<XECRYPT_SHA256_STATE> sha_state) {
sha_state.Zero();
@@ -254,13 +570,6 @@ void XeCryptSha256Final_entry(pointer_t<XECRYPT_SHA256_STATE> sha_state,
}
DECLARE_XBOXKRNL_EXPORT1(XeCryptSha256Final, kNone, kImplemented);
// TODO: Size of this struct hasn't been confirmed yet.
typedef struct {
xe::be<uint64_t> count; // 0x0
xe::be<uint64_t> state[8]; // 0x8
uint8_t buffer[128]; // 0x48
} XECRYPT_SHA512_STATE;
void XeCryptSha512Init_entry(pointer_t<XECRYPT_SHA512_STATE> sha_state) {
sha_state.Zero();
@@ -275,13 +584,6 @@ void XeCryptSha512Init_entry(pointer_t<XECRYPT_SHA512_STATE> sha_state) {
}
DECLARE_XBOXKRNL_EXPORT1(XeCryptSha512Init, kNone, kImplemented);
struct SHA512_STATE {
uint8_t digest_len;
uint64_t count;
uint8_t buffer[128];
uint64_t state[8];
};
void XeCryptSha512Update_entry(pointer_t<XECRYPT_SHA512_STATE> sha_state,
lpvoid_t input, dword_t input_size) {
AVSHA512* sha = av_sha512_alloc();
@@ -327,13 +629,6 @@ void XeCryptSha512Final_entry(pointer_t<XECRYPT_SHA256_STATE> sha_state,
}
DECLARE_XBOXKRNL_EXPORT1(XeCryptSha512Final, kNone, kImplemented);
// TODO: Size of this struct hasn't been confirmed yet.
typedef struct {
xe::be<uint64_t> count;
xe::be<uint32_t> state[4];
uint8_t buffer[64];
} XECRYPT_MD5_STATE;
void XeCryptMd5Init_entry(pointer_t<XECRYPT_MD5_STATE> md5_state) {
md5_state.Zero();
@@ -345,12 +640,6 @@ void XeCryptMd5Init_entry(pointer_t<XECRYPT_MD5_STATE> md5_state) {
}
DECLARE_XBOXKRNL_EXPORT1(XeCryptMd5Init, kNone, kImplemented);
struct MD5_STATE {
uint64_t len;
uint8_t block[64];
uint32_t ABCD[4];
};
void XeCryptMd5Update_entry(pointer_t<XECRYPT_MD5_STATE> md5_state,
lpvoid_t input, dword_t input_size) {
AVMD5* md5 = av_md5_alloc();
@@ -405,15 +694,6 @@ void XeCryptBnQw_SwapDwQwLeBe_entry(pointer_t<uint64_t> qw_inp,
}
DECLARE_XBOXKRNL_EXPORT1(XeCryptBnQw_SwapDwQwLeBe, kNone, kImplemented);
typedef struct {
xe::be<uint32_t> size; // size of modulus in 8 byte units
xe::be<uint32_t> public_exponent;
xe::be<uint64_t> pad_8;
// followed by modulus, followed by any private-key data
} XECRYPT_RSA;
static_assert_size(XECRYPT_RSA, 0x10);
dword_result_t XeCryptBnQwNeRsaPubCrypt_entry(pointer_t<uint64_t> qw_a,
pointer_t<uint64_t> qw_b,
pointer_t<XECRYPT_RSA> rsa) {
@@ -517,6 +797,15 @@ DECLARE_XBOXKRNL_EXPORT1(XeCryptBnQwNeRsaPubCrypt, kNone, kImplemented);
DECLARE_XBOXKRNL_EXPORT1(XeCryptBnQwNeRsaPubCrypt, kNone, kStub);
#endif
dword_result_t XeCryptBnQwBeSigVerify_entry(pointer_t<XECRYPT_SIG> sig,
lpvoid_t hash, lpstring_t salt,
pointer_t<XECRYPT_RSA> rsa) {
// hash from XeCryptRotSumSha
// known salts are "XBOX360SVC", "XBOX360XTT", "TDBXBOX36O"
return true;
}
DECLARE_XBOXKRNL_EXPORT1(XeCryptBnQwBeSigVerify, kNone, kStub);
dword_result_t XeCryptBnDwLePkcs1Verify_entry(lpvoid_t hash, lpvoid_t sig,
dword_t size) {
// BOOL return value
@@ -529,9 +818,24 @@ void XeCryptRandom_entry(lpvoid_t buf, dword_t buf_size) {
}
DECLARE_XBOXKRNL_EXPORT1(XeCryptRandom, kNone, kStub);
struct XECRYPT_DES_STATE {
uint32_t keytab[16][2];
};
void XeCryptDesKey_entry(pointer_t<XECRYPT_DES_STATE> state_ptr,
lpqword_t key) {
DES des(key[0]);
std::memcpy(state_ptr->keytab, des.get_sub_key(), 128);
}
DECLARE_XBOXKRNL_EXPORT1(XeCryptDesKey, kNone, kImplemented);
void XeCryptDesEcb_entry(pointer_t<XECRYPT_DES_STATE> state_ptr, lpqword_t inp,
lpqword_t out, dword_t encrypt) {
DES des(reinterpret_cast<uint64_t*>(state_ptr->keytab));
if (encrypt) {
*out = des.encrypt(*inp);
} else {
*out = des.decrypt(*inp);
}
}
DECLARE_XBOXKRNL_EXPORT1(XeCryptDesEcb, kNone, kImplemented);
// Sets bit 0 to make the parity odd
void XeCryptDesParity_entry(lpvoid_t inp, dword_t inp_size, lpvoid_t out_ptr) {
@@ -539,10 +843,6 @@ void XeCryptDesParity_entry(lpvoid_t inp, dword_t inp_size, lpvoid_t out_ptr) {
}
DECLARE_XBOXKRNL_EXPORT1(XeCryptDesParity, kNone, kImplemented);
struct XECRYPT_DES3_STATE {
XECRYPT_DES_STATE des_state[3];
};
void XeCryptDes3Key_entry(pointer_t<XECRYPT_DES3_STATE> state_ptr,
lpqword_t key) {
DES3 des3(key[0], key[1], key[2]);
@@ -595,12 +895,6 @@ void XeCryptDes3Cbc_entry(pointer_t<XECRYPT_DES3_STATE> state_ptr,
}
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);
}
@@ -774,13 +1068,28 @@ void XeCryptHmacSha_entry(lpvoid_t key, dword_t key_size_in, lpvoid_t inp_1,
}
DECLARE_XBOXKRNL_EXPORT1(XeCryptHmacSha, kNone, kImplemented);
// Keys
// TODO: Array of keys we need
dword_result_t XeKeysGetKeyProperties_entry(dword_t key) {
if (X_Key_Properties.contains(key)) {
auto& key_info = X_Key_Properties.at(key);
return std::get<1>(key_info);
}
XELOGW("Key 0x{:04X} not implemented", static_cast<uint16_t>(key));
return 0;
}
DECLARE_XBOXKRNL_EXPORT1(XeKeysGetKeyProperties, kNone, kImplemented);
// Retail key 0x19
static constexpr uint8_t key19[] = {0xE1, 0xBC, 0x15, 0x9C, 0x73, 0xB1,
0xEA, 0xE9, 0xAB, 0x31, 0x70, 0xF3,
0xAD, 0x47, 0xEB, 0xF3};
dword_result_t XeKeysGetKey_entry(word_t key, lpvoid_t key_buffer,
lpdword_t key_length) {
if (key_vault.contains(key)) {
std::span<const uint8_t> key_needed = key_vault.at(key);
std::memcpy(key_buffer, key_needed.data(), *key_length);
} else {
XELOGW("Key 0x{:04X} not implemented", static_cast<uint16_t>(key));
}
return X_STATUS_SUCCESS;
}
DECLARE_XBOXKRNL_EXPORT1(XeKeysGetKey, kNone, kSketchy);
dword_result_t XeKeysHmacSha_entry(dword_t key_num, lpvoid_t inp_1,
dword_t inp_1_size, lpvoid_t inp_2,
@@ -803,9 +1112,12 @@ dword_result_t XeKeysHmacSha_entry(dword_t key_num, lpvoid_t inp_1,
}
DECLARE_XBOXKRNL_EXPORT1(XeKeysHmacSha, kNone, kImplemented);
static const uint8_t xe_key_obfuscation_key[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
void XeCryptRotSumSha_entry(lpvoid_t inp_1, dword_t inp_1_size, lpvoid_t inp_2,
dword_t inp_2_size, lpvoid_t out,
dword_t out_size) {
// out used by XeCryptBnQwBeSigVerify
}
DECLARE_XBOXKRNL_EXPORT1(XeCryptRotSumSha, kNone, kStub);
dword_result_t XeKeysAesCbcUsingKey_entry(lpvoid_t obscured_key,
lpvoid_t inp_ptr, dword_t inp_size,
@@ -860,16 +1172,64 @@ dword_result_t XeKeysHmacShaUsingKey_entry(lpvoid_t obscured_key,
}
DECLARE_XBOXKRNL_EXPORT1(XeKeysHmacShaUsingKey, kNone, kImplemented);
// going off of usage in some hbrew xex
// 0 and 1 appear to be devkit, 2 is retail
// we default to saying we're retail
dword_result_t XeKeysGetConsoleType_entry(lpdword_t type_out) {
*type_out = 2;
*type_out = Retail;
return 0;
}
DECLARE_XBOXKRNL_EXPORT1(XeKeysGetConsoleType, kNone, kImplemented);
dword_result_t XeKeysGetConsoleID_entry(pointer_t<XE_CONSOLE_ID> raw_bytes,
lpstring_t hex_string) {
// We dont care about KV or using official keys
if (raw_bytes) {
raw_bytes.Zero();
raw_bytes->RefurbBits = 0b0011;
raw_bytes->ManufactureMonth = 0b1001;
raw_bytes->ManufactureYear = 0b0001;
raw_bytes->MacIndex3 = 0b01000000;
raw_bytes->MacIndex4 = 0b01100110;
raw_bytes->MacIndex5 = 0b01111110;
raw_bytes->Crc = 0b0000;
}
if (hex_string) {
std::string key = "245149100000";
std::memcpy(hex_string, key.c_str(), 0xC);
}
return X_STATUS_SUCCESS;
}
DECLARE_XBOXKRNL_EXPORT1(XeKeysGetConsoleID, kNone, kImplemented);
dword_result_t XeKeysConsolePrivateKeySign_entry(
lpvoid_t hash, pointer_t<XE_CONSOLE_CERTIFICATE> output) {
if (!hash) {
return false;
}
if (!output) {
return false;
}
output.Zero();
output->console_id.RefurbBits = 0b0011;
output->console_id.ManufactureMonth = 0b1001;
output->console_id.ManufactureYear = 0b0001;
output->console_id.MacIndex3 = 0b01000000;
output->console_id.MacIndex4 = 0b01100110;
output->console_id.MacIndex5 = 0b01111110;
output->console_id.Crc = 0b0000;
output->console_type = Retail;
output->manufacture_date[0] = 2;
output->manufacture_date[1] = 0;
output->manufacture_date[2] = 0;
output->manufacture_date[3] = 5;
output->manufacture_date[4] = 1;
output->manufacture_date[5] = 1;
output->manufacture_date[6] = 2;
output->manufacture_date[7] = 2;
return true;
}
DECLARE_XBOXKRNL_EXPORT1(XeKeysConsolePrivateKeySign, kNone, kSketchy);
} // namespace xboxkrnl
} // namespace kernel
} // namespace xe