From dd585ca0c8fd0df7395c9f735106d04a666a3dc3 Mon Sep 17 00:00:00 2001 From: The-Little-Wolf <116989599+The-Little-Wolf@users.noreply.github.com> Date: Mon, 23 Feb 2026 00:33:19 -0800 Subject: [PATCH] [XboxKrnl/Crypt] - Implement XeCrypt & XeKeys Functions (#566) - Implement XeKeysGetConsoleID, XeKeysGetKeyProperties, XeCryptDesEcb, and XeCryptDesKey. - Stub XeCryptBnQwBeSigVerify, XeCryptRotSumSha, XeKeysGetKey, and XeKeysConsolePrivateKeySign. --- src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc | 520 +++++++++++++++++--- 1 file changed, 440 insertions(+), 80 deletions(-) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc index 9a3621cde..3c920dc70 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc @@ -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 count; // 0x0 + xe::be 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 count; // 0x0 + xe::be state[8]; // 0x4 + uint8_t buffer[64]; // 0x24 +}; + +// TODO: Size of this struct hasn't been confirmed yet. +struct XECRYPT_SHA512_STATE { + xe::be count; // 0x0 + xe::be 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 count; + xe::be 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 size; // size of modulus in 8 byte units + xe::be public_exponent; + xe::be pad_8; + + // followed by modulus, followed by any private-key data +}; +static_assert_size(XECRYPT_RSA, 0x10); + +struct XECRYPT_SIG { + xe::be aqwPad[0x1C]; + xe::be One; + uint8_t Salt[0xA]; + uint8_t Hash[0x14]; + xe::be 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 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> 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> 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 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 privileges; // 0x16 sz:0x2 + xe::be 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 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 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]; 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 count; // 0x0 - xe::be state[8]; // 0x4 - uint8_t buffer[64]; // 0x24 -} XECRYPT_SHA256_STATE; - void XeCryptSha256Init_entry(pointer_t sha_state) { sha_state.Zero(); @@ -254,13 +570,6 @@ void XeCryptSha256Final_entry(pointer_t sha_state, } DECLARE_XBOXKRNL_EXPORT1(XeCryptSha256Final, kNone, kImplemented); -// TODO: Size of this struct hasn't been confirmed yet. -typedef struct { - xe::be count; // 0x0 - xe::be state[8]; // 0x8 - uint8_t buffer[128]; // 0x48 -} XECRYPT_SHA512_STATE; - void XeCryptSha512Init_entry(pointer_t sha_state) { sha_state.Zero(); @@ -275,13 +584,6 @@ void XeCryptSha512Init_entry(pointer_t 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 sha_state, lpvoid_t input, dword_t input_size) { AVSHA512* sha = av_sha512_alloc(); @@ -327,13 +629,6 @@ void XeCryptSha512Final_entry(pointer_t sha_state, } DECLARE_XBOXKRNL_EXPORT1(XeCryptSha512Final, kNone, kImplemented); -// TODO: Size of this struct hasn't been confirmed yet. -typedef struct { - xe::be count; - xe::be state[4]; - uint8_t buffer[64]; -} XECRYPT_MD5_STATE; - void XeCryptMd5Init_entry(pointer_t md5_state) { md5_state.Zero(); @@ -345,12 +640,6 @@ void XeCryptMd5Init_entry(pointer_t 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 md5_state, lpvoid_t input, dword_t input_size) { AVMD5* md5 = av_md5_alloc(); @@ -405,15 +694,6 @@ void XeCryptBnQw_SwapDwQwLeBe_entry(pointer_t qw_inp, } DECLARE_XBOXKRNL_EXPORT1(XeCryptBnQw_SwapDwQwLeBe, kNone, kImplemented); -typedef struct { - xe::be size; // size of modulus in 8 byte units - xe::be public_exponent; - xe::be 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 qw_a, pointer_t qw_b, pointer_t 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 sig, + lpvoid_t hash, lpstring_t salt, + pointer_t 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 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 state_ptr, lpqword_t inp, + lpqword_t out, dword_t encrypt) { + DES des(reinterpret_cast(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 state_ptr, lpqword_t key) { DES3 des3(key[0], key[1], key[2]); @@ -595,12 +895,6 @@ void XeCryptDes3Cbc_entry(pointer_t 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(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 key_needed = key_vault.at(key); + std::memcpy(key_buffer, key_needed.data(), *key_length); + } else { + XELOGW("Key 0x{:04X} not implemented", static_cast(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 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 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