Xbox 360 - No Dongle Authentication (#1426)
* Solid connection? * Add a small wait after we reset the port * Moving up to latest as this fixes a lot of reset logic * Moving libraries over to jfedor's set, standard does not work for SDK 2.1.1 * Switching Pico and TinyUSB to specific versions via hid-remapper * Working? * Move TX to PIO0:2 Move NeoPico to PIO0:1 * Moving state machines back to 0.7.11 alignment * And a pause/wait for core1 to be ready before running it solves my last issue * Removing core1 reset entirely, remove i2c hangup if display is not present during web config * Reverting / clean some code, restore tusb to our old config, update aux and remove comments for PR * Xbox 360 authentication - Santroller + XSM3 * Adding the missing files to the make * ANd the missing XSM3 files
This commit is contained in:
@@ -172,6 +172,11 @@ src/addonmanager.cpp
|
||||
src/playerleds.cpp
|
||||
src/drivers/shared/xinput_host.cpp
|
||||
src/drivers/shared/xgip_protocol.cpp
|
||||
src/drivers/shared/xsm3/excrypt_des.c
|
||||
src/drivers/shared/xsm3/excrypt_parve.c
|
||||
src/drivers/shared/xsm3/excrypt_sha.c
|
||||
src/drivers/shared/xsm3/usbdsec.c
|
||||
src/drivers/shared/xsm3/xsm3.c
|
||||
src/drivers/astro/AstroDriver.cpp
|
||||
src/drivers/egret/EgretDriver.cpp
|
||||
src/drivers/hid/HIDDriver.cpp
|
||||
@@ -301,6 +306,7 @@ headers
|
||||
headers/addons
|
||||
headers/configs
|
||||
headers/drivers
|
||||
headers/drivers/shared
|
||||
headers/events
|
||||
headers/interfaces
|
||||
headers/interfaces/i2c
|
||||
|
||||
39
headers/drivers/shared/xsm3/excrypt.h
Normal file
39
headers/drivers/shared/xsm3/excrypt.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef EXCRYPT_H_
|
||||
#define EXCRYPT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#if(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
#define SWAP16(i) i
|
||||
#define SWAP32(i) i
|
||||
#define SWAP64(i) i
|
||||
#else
|
||||
#define SWAP16(i) ((((i) & 0xFF) << 8 | ((i) >> 8) & 0xFF) & 0xFFFF)
|
||||
#define SWAP32(i) ((((i) & 0xff) << 24) | (((i) & 0xff00) << 8) | (((i) & 0xff0000) >> 8) | (((i) >> 24) & 0xff))
|
||||
#define SWAP64(i) ((SWAP32((i) & 0xFFFFFFFF) << 32) | (SWAP32(((i) >> 32) & 0xFFFFFFFF)))
|
||||
#endif
|
||||
|
||||
#define U8V(data) ((uint8_t)(data) & 0xFF)
|
||||
#define ROTL8(data, bits) (U8V((data) << (bits)) | ((data) >> (8 - (bits))))
|
||||
|
||||
#define U16V(data) ((uint16_t)(data) & 0xFFFF)
|
||||
#define ROTL16(data, bits) (U16V((data) << (bits)) | ((data) >> (16 - (bits))))
|
||||
|
||||
#define U32V(data) ((uint32_t)(data) & 0xFFFFFFFF)
|
||||
#define ROTL32(data, bits) (U32V((data) << (bits)) | ((data) >> (32 - (bits))))
|
||||
|
||||
#define ROTL64(data, bits) (((data) << (bits)) | ((data) >> (64 - (bits))))
|
||||
|
||||
typedef int BOOL;
|
||||
|
||||
#include "excrypt_des.h"
|
||||
#include "excrypt_sha.h"
|
||||
#include "excrypt_parve.h"
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EXCRYPT_H_
|
||||
24
headers/drivers/shared/xsm3/excrypt_des.h
Normal file
24
headers/drivers/shared/xsm3/excrypt_des.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef EXCRYPT_DES_H_
|
||||
#define EXCRYPT_DES_H_
|
||||
// DES & 3DES functions
|
||||
|
||||
typedef struct _EXCRYPT_DES_STATE
|
||||
{
|
||||
uint64_t keytab[16];
|
||||
} EXCRYPT_DES_STATE;
|
||||
|
||||
void ExCryptDesParity(const uint8_t* input, uint32_t input_size, uint8_t* output);
|
||||
|
||||
void ExCryptDesKey(EXCRYPT_DES_STATE* state, const uint8_t* key);
|
||||
void ExCryptDesEcb(const EXCRYPT_DES_STATE* state, const uint8_t* input, uint8_t* output, uint8_t encrypt);
|
||||
|
||||
typedef struct _EXCRYPT_DES3_STATE
|
||||
{
|
||||
EXCRYPT_DES_STATE des_state[3];
|
||||
} EXCRYPT_DES3_STATE;
|
||||
|
||||
void ExCryptDes3Key(EXCRYPT_DES3_STATE* state, const uint64_t* keys);
|
||||
void ExCryptDes3Ecb(const EXCRYPT_DES3_STATE* state, const uint8_t* input, uint8_t* output, uint8_t encrypt);
|
||||
void ExCryptDes3Cbc(const EXCRYPT_DES3_STATE* state, const uint8_t* input, uint32_t input_size, uint8_t* output, uint8_t* feed, uint8_t encrypt);
|
||||
|
||||
#endif // EXCRYPT_DES_H_
|
||||
157
headers/drivers/shared/xsm3/excrypt_des_data.h
Normal file
157
headers/drivers/shared/xsm3/excrypt_des_data.h
Normal file
@@ -0,0 +1,157 @@
|
||||
#ifndef EXCRYPT_DES_DATA_H_
|
||||
#define EXCRYPT_DES_DATA_H_
|
||||
// Data needed by DES/3DES functions
|
||||
// (only included by excrypt_des.c - no headers should include this!)
|
||||
|
||||
#define LB32_MASK 0x00000001
|
||||
#define LB64_MASK 0x0000000000000001
|
||||
#define L64_MASK 0x00000000ffffffff
|
||||
|
||||
// Initial Permutation Table [8*8]
|
||||
static const char IP[] =
|
||||
{
|
||||
58, 50, 42, 34, 26, 18, 10, 2,
|
||||
60, 52, 44, 36, 28, 20, 12, 4,
|
||||
62, 54, 46, 38, 30, 22, 14, 6,
|
||||
64, 56, 48, 40, 32, 24, 16, 8,
|
||||
57, 49, 41, 33, 25, 17, 9, 1,
|
||||
59, 51, 43, 35, 27, 19, 11, 3,
|
||||
61, 53, 45, 37, 29, 21, 13, 5,
|
||||
63, 55, 47, 39, 31, 23, 15, 7
|
||||
};
|
||||
|
||||
// Inverse Initial Permutation Table [8*8]
|
||||
static const char FP[] =
|
||||
{
|
||||
40, 8, 48, 16, 56, 24, 64, 32,
|
||||
39, 7, 47, 15, 55, 23, 63, 31,
|
||||
38, 6, 46, 14, 54, 22, 62, 30,
|
||||
37, 5, 45, 13, 53, 21, 61, 29,
|
||||
36, 4, 44, 12, 52, 20, 60, 28,
|
||||
35, 3, 43, 11, 51, 19, 59, 27,
|
||||
34, 2, 42, 10, 50, 18, 58, 26,
|
||||
33, 1, 41, 9, 49, 17, 57, 25
|
||||
};
|
||||
|
||||
// Expansion table [6*8]
|
||||
static const char EXPANSION[] =
|
||||
{
|
||||
32, 1, 2, 3, 4, 5,
|
||||
4, 5, 6, 7, 8, 9,
|
||||
8, 9, 10, 11, 12, 13,
|
||||
12, 13, 14, 15, 16, 17,
|
||||
16, 17, 18, 19, 20, 21,
|
||||
20, 21, 22, 23, 24, 25,
|
||||
24, 25, 26, 27, 28, 29,
|
||||
28, 29, 30, 31, 32, 1
|
||||
};
|
||||
|
||||
// The S-Box tables [8*16*4]
|
||||
static const char SBOX[8][64] =
|
||||
{
|
||||
{
|
||||
// S1
|
||||
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
|
||||
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
|
||||
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
|
||||
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
|
||||
},
|
||||
{
|
||||
// S2
|
||||
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
|
||||
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
|
||||
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
|
||||
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
|
||||
},
|
||||
{
|
||||
// S3
|
||||
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
|
||||
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
|
||||
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
|
||||
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
|
||||
},
|
||||
{
|
||||
// S4
|
||||
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
|
||||
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
|
||||
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
|
||||
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
|
||||
},
|
||||
{
|
||||
// S5
|
||||
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
|
||||
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
|
||||
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
|
||||
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
|
||||
},
|
||||
{
|
||||
// S6
|
||||
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
|
||||
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
|
||||
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
|
||||
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
|
||||
},
|
||||
{
|
||||
// S7
|
||||
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
|
||||
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
|
||||
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
|
||||
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
|
||||
},
|
||||
{
|
||||
// S8
|
||||
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
|
||||
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
|
||||
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
|
||||
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
|
||||
}
|
||||
};
|
||||
|
||||
// Post S-Box permutation [4*8]
|
||||
static const char PBOX[] =
|
||||
{
|
||||
16, 7, 20, 21,
|
||||
29, 12, 28, 17,
|
||||
1, 15, 23, 26,
|
||||
5, 18, 31, 10,
|
||||
2, 8, 24, 14,
|
||||
32, 27, 3, 9,
|
||||
19, 13, 30, 6,
|
||||
22, 11, 4, 25
|
||||
};
|
||||
|
||||
// Permuted Choice 1 Table [7*8]
|
||||
static const char PC1[] =
|
||||
{
|
||||
57, 49, 41, 33, 25, 17, 9,
|
||||
1, 58, 50, 42, 34, 26, 18,
|
||||
10, 2, 59, 51, 43, 35, 27,
|
||||
19, 11, 3, 60, 52, 44, 36,
|
||||
|
||||
63, 55, 47, 39, 31, 23, 15,
|
||||
7, 62, 54, 46, 38, 30, 22,
|
||||
14, 6, 61, 53, 45, 37, 29,
|
||||
21, 13, 5, 28, 20, 12, 4
|
||||
};
|
||||
|
||||
// Permuted Choice 2 Table [6*8]
|
||||
static const char PC2[] =
|
||||
{
|
||||
14, 17, 11, 24, 1, 5,
|
||||
3, 28, 15, 6, 21, 10,
|
||||
23, 19, 12, 4, 26, 8,
|
||||
16, 7, 27, 20, 13, 2,
|
||||
41, 52, 31, 37, 47, 55,
|
||||
30, 40, 51, 45, 33, 48,
|
||||
44, 49, 39, 56, 34, 53,
|
||||
46, 42, 50, 36, 29, 32
|
||||
};
|
||||
|
||||
// Iteration Shift Array
|
||||
static const char ITERATION_SHIFT[] =
|
||||
{
|
||||
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
||||
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
|
||||
};
|
||||
|
||||
#endif // EXCRYPT_DES_DATA_H_
|
||||
9
headers/drivers/shared/xsm3/excrypt_parve.h
Normal file
9
headers/drivers/shared/xsm3/excrypt_parve.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef EXCRYPT_PARVE_H_
|
||||
#define EXCRYPT_PARVE_H_
|
||||
// "Parve" functions, seem to be used during controller auth
|
||||
|
||||
void ExCryptParveEcb(const uint8_t* key, const uint8_t* sbox, const uint8_t* input, uint8_t* output);
|
||||
void ExCryptParveCbcMac(const uint8_t* key, const uint8_t* sbox, const uint8_t* iv, const uint8_t* input, uint32_t input_size, uint8_t* output);
|
||||
void ExCryptChainAndSumMac(const uint32_t* cd, const uint32_t* ab, const uint32_t* input, uint32_t input_dwords, uint32_t* output);
|
||||
|
||||
#endif // EXCRYPT_PARVE_H_
|
||||
18
headers/drivers/shared/xsm3/excrypt_sha.h
Normal file
18
headers/drivers/shared/xsm3/excrypt_sha.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef EXCRYPT_SHA_H_
|
||||
#define EXCRYPT_SHA_H_
|
||||
// SHA1 hash & HMAC algorithm
|
||||
|
||||
typedef struct _EXCRYPT_SHA_STATE
|
||||
{
|
||||
uint32_t count;
|
||||
uint32_t state[5];
|
||||
uint8_t buffer[64];
|
||||
} EXCRYPT_SHA_STATE;
|
||||
|
||||
void ExCryptShaInit(EXCRYPT_SHA_STATE* state);
|
||||
void ExCryptShaUpdate(EXCRYPT_SHA_STATE* state, const uint8_t* input, uint32_t input_size);
|
||||
void ExCryptShaFinal(EXCRYPT_SHA_STATE* state, uint8_t* output, uint32_t output_size);
|
||||
void ExCryptSha(const uint8_t* input1, uint32_t input1_size, const uint8_t* input2, uint32_t input2_size,
|
||||
const uint8_t* input3, uint32_t input3_size, uint8_t* output, uint32_t output_size);
|
||||
|
||||
#endif // EXCRYPT_SHA_H_
|
||||
29
headers/drivers/shared/xsm3/usbdsec.h
Normal file
29
headers/drivers/shared/xsm3/usbdsec.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
usbdsec.h - part of libxsm3
|
||||
Copyright (C) 2022 InvoxiPlayGames
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef USBDSEC_H_
|
||||
#define USBDSEC_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void UsbdSecXSM3AuthenticationCrypt(const uint8_t *key, const uint8_t *input, size_t length, uint8_t *output, uint8_t encrypt);
|
||||
void UsbdSecXSM3AuthenticationMac(const uint8_t *key, const uint8_t *salt, uint8_t *input, size_t length, uint8_t *output);
|
||||
void UsbdSecXSMAuthenticationAcr(const uint8_t *console_id, const uint8_t *input, const uint8_t *key, uint8_t *output);
|
||||
|
||||
#endif // USBDSEC_H_
|
||||
54
headers/drivers/shared/xsm3/xsm3.h
Normal file
54
headers/drivers/shared/xsm3/xsm3.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
xsm3.h - part of libxsm3
|
||||
Copyright (C) 2022 InvoxiPlayGames
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef XSM3_H_
|
||||
#define XSM3_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
// Identification data taken from an official wired controller. (Serial number is static.)
|
||||
extern uint8_t xsm3_id_data_ms_controller[0x1D];
|
||||
|
||||
// The response data from the previously completed challenge.
|
||||
extern uint8_t xsm3_challenge_response[0x30];
|
||||
|
||||
// The console ID fetched from the console after request 0x82.
|
||||
extern uint8_t xsm3_console_id[0x8];
|
||||
|
||||
// Clears the state of the XSM3 internal variables.
|
||||
void xsm3_initialise_state();
|
||||
|
||||
// Sets the identification data to use.
|
||||
void xsm3_set_identification_data(const uint8_t id_data[0x1D]);
|
||||
|
||||
// Initialises the XSM3 state using information from the challenge init packet (0x82) and places a response in xsm3_challenge_response.
|
||||
void xsm3_do_challenge_init(uint8_t challenge_packet[0x22]);
|
||||
|
||||
// Completes a verify challenge passed from request 0x87 and places the response data in xsm3_challenge_response.
|
||||
void xsm3_do_challenge_verify(uint8_t challenge_packet[0x16]);
|
||||
|
||||
void xsm3_set_vid_pid(const uint8_t serial[0x0C], uint16_t vid, uint16_t pid);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // XSM3_H_
|
||||
@@ -56,6 +56,7 @@ typedef struct {
|
||||
|
||||
class XInputAuth : public GPAuthDriver {
|
||||
public:
|
||||
XInputAuth(InputModeAuthType inType) { authType = inType; }
|
||||
virtual void initialize();
|
||||
virtual bool available();
|
||||
void process();
|
||||
|
||||
@@ -30,13 +30,14 @@ public:
|
||||
virtual const uint8_t * get_descriptor_device_qualifier_cb();
|
||||
virtual uint16_t GetJoystickMidValue();
|
||||
virtual USBListener * get_usb_auth_listener();
|
||||
bool getAuthEnabled();
|
||||
bool getAuthSent();
|
||||
private:
|
||||
uint8_t last_report[CFG_TUD_ENDPOINT0_SIZE] = { };
|
||||
XInputReport xinputReport;
|
||||
XInputAuth * xAuthDriver;
|
||||
uint8_t featureBuffer[XINPUT_OUT_SIZE];
|
||||
uint8_t tud_buffer[64];
|
||||
bool xAuthSent;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -197,7 +197,7 @@ void ButtonLayoutScreen::generateHeader() {
|
||||
break;
|
||||
case INPUT_MODE_XINPUT:
|
||||
statusBar += "X";
|
||||
if(((XInputDriver*)DriverManager::getInstance().getDriver())->getAuthEnabled() == true )
|
||||
if(((XInputDriver*)DriverManager::getInstance().getDriver())->getAuthSent() == true )
|
||||
statusBar += "B360";
|
||||
else
|
||||
statusBar += "INPUT";
|
||||
|
||||
198
src/drivers/shared/xsm3/excrypt_des.c
Normal file
198
src/drivers/shared/xsm3/excrypt_des.c
Normal file
@@ -0,0 +1,198 @@
|
||||
#include "xsm3/excrypt.h"
|
||||
#include "xsm3/excrypt_des_data.h"
|
||||
#include <string.h>
|
||||
|
||||
#define LODWORD(_qw) ((uint32_t)(_qw))
|
||||
#define HIDWORD(_qw) ((uint32_t)(((_qw) >> 32) & 0xffffffff))
|
||||
|
||||
// DES code based on https://github.com/fffaraz/cppDES
|
||||
|
||||
void ExCryptDesParity(const uint8_t* input, uint32_t input_size, uint8_t* output)
|
||||
{
|
||||
for (uint32_t i = 0; i < input_size; i++)
|
||||
{
|
||||
uint8_t parity = input[i];
|
||||
|
||||
parity ^= parity >> 4;
|
||||
parity ^= parity >> 2;
|
||||
parity ^= parity >> 1;
|
||||
|
||||
output[i] = (input[i] & 0xFE) | (~parity & 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ExCryptDesKey(EXCRYPT_DES_STATE* state, const uint8_t* key)
|
||||
{
|
||||
uint64_t qkey = SWAP64(*(const uint64_t*)key);
|
||||
|
||||
// initial key schedule calculation
|
||||
uint64_t permuted_choice_1 = 0; // 56 bits
|
||||
for (int i = 0; i < 56; i++)
|
||||
{
|
||||
permuted_choice_1 <<= 1;
|
||||
permuted_choice_1 |= (qkey >> (64 - PC1[i])) & LB64_MASK;
|
||||
}
|
||||
|
||||
// 28 bits
|
||||
uint32_t C = (uint32_t)((permuted_choice_1 >> 28) & 0x000000000fffffff);
|
||||
uint32_t D = (uint32_t)(permuted_choice_1 & 0x000000000fffffff);
|
||||
|
||||
// Calculation of the 16 keys
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
// key schedule, shifting Ci and Di
|
||||
for (int j = 0; j < ITERATION_SHIFT[i]; j++)
|
||||
{
|
||||
C = (0x0fffffff & (C << 1)) | (0x00000001 & (C >> 27));
|
||||
D = (0x0fffffff & (D << 1)) | (0x00000001 & (D >> 27));
|
||||
}
|
||||
|
||||
uint64_t permuted_choice_2 = (((uint64_t)C) << 28) | (uint64_t)D;
|
||||
|
||||
uint64_t sub_key = 0; // 48 bits (2*24)
|
||||
for (int j = 0; j < 48; j++)
|
||||
{
|
||||
sub_key <<= 1;
|
||||
sub_key |= (permuted_choice_2 >> (56 - PC2[j])) & LB64_MASK;
|
||||
}
|
||||
state->keytab[i] = sub_key;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t f(uint32_t R, uint64_t k)
|
||||
{
|
||||
// applying expansion permutation and returning 48-bit data
|
||||
uint64_t s_input = 0;
|
||||
for (int i = 0; i < 48; i++)
|
||||
{
|
||||
s_input <<= 1;
|
||||
s_input |= (uint64_t)((R >> (32 - EXPANSION[i])) & LB32_MASK);
|
||||
}
|
||||
|
||||
// XORing expanded Ri with Ki, the round key
|
||||
s_input = s_input ^ k;
|
||||
|
||||
// applying S-Boxes function and returning 32-bit data
|
||||
uint32_t s_output = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
// Outer bits
|
||||
char row = (char)((s_input & (0x0000840000000000 >> 6 * i)) >> (42 - 6 * i));
|
||||
row = (row >> 4) | (row & 0x01);
|
||||
|
||||
// Middle 4 bits of input
|
||||
char column = (char)((s_input & (0x0000780000000000 >> 6 * i)) >> (43 - 6 * i));
|
||||
|
||||
s_output <<= 4;
|
||||
s_output |= (uint32_t)(SBOX[i][16 * row + column] & 0x0f);
|
||||
}
|
||||
|
||||
// applying the round permutation
|
||||
uint32_t f_result = 0;
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
f_result <<= 1;
|
||||
f_result |= (s_output >> (32 - PBOX[i])) & LB32_MASK;
|
||||
}
|
||||
|
||||
return f_result;
|
||||
}
|
||||
|
||||
void feistel(uint32_t* L, uint32_t* R, uint32_t F)
|
||||
{
|
||||
uint32_t temp = *R;
|
||||
*R = *L ^ F;
|
||||
*L = temp;
|
||||
}
|
||||
|
||||
void ExCryptDesEcb(const EXCRYPT_DES_STATE* state, const uint8_t* input, uint8_t* output, uint8_t encrypt)
|
||||
{
|
||||
uint64_t block;
|
||||
memcpy(&block, input, sizeof(uint64_t));
|
||||
block = SWAP64(block);
|
||||
//uint64_t block = SWAP64(*(uint64_t*)input)
|
||||
|
||||
|
||||
// initial permutation
|
||||
uint64_t result = 0;
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
result <<= 1;
|
||||
result |= (block >> (64 - IP[i])) & LB64_MASK;
|
||||
}
|
||||
|
||||
// dividing T' into two 32-bit parts
|
||||
uint32_t L = HIDWORD(result);
|
||||
uint32_t R = LODWORD(result);
|
||||
|
||||
// 16 rounds
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
uint32_t F = !encrypt ? f(R, state->keytab[15 - i]) : f(R, state->keytab[i]);
|
||||
feistel(&L, &R, F);
|
||||
}
|
||||
|
||||
// swapping the two parts
|
||||
block = (((uint64_t)R) << 32) | (uint64_t)L;
|
||||
|
||||
// inverse initial permutation
|
||||
result = 0;
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
result <<= 1;
|
||||
result |= (block >> (64 - FP[i])) & LB64_MASK;
|
||||
}
|
||||
result = SWAP64(result);
|
||||
memcpy(output, &result, sizeof(result));
|
||||
}
|
||||
|
||||
void ExCryptDes3Key(EXCRYPT_DES3_STATE* state, const uint64_t* keys)
|
||||
{
|
||||
ExCryptDesKey(&state->des_state[0], (const uint8_t*)& keys[0]);
|
||||
ExCryptDesKey(&state->des_state[1], (const uint8_t*)& keys[1]);
|
||||
ExCryptDesKey(&state->des_state[2], (const uint8_t*)& keys[2]);
|
||||
}
|
||||
|
||||
void ExCryptDes3Ecb(const EXCRYPT_DES3_STATE* state, const uint8_t* input, uint8_t* output, uint8_t encrypt)
|
||||
{
|
||||
if (encrypt)
|
||||
{
|
||||
ExCryptDesEcb(&state->des_state[0], input, output, encrypt);
|
||||
ExCryptDesEcb(&state->des_state[1], output, output, !encrypt);
|
||||
ExCryptDesEcb(&state->des_state[2], output, output, encrypt);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExCryptDesEcb(&state->des_state[2], input, output, encrypt);
|
||||
ExCryptDesEcb(&state->des_state[1], output, output, !encrypt);
|
||||
ExCryptDesEcb(&state->des_state[0], output, output, encrypt);
|
||||
}
|
||||
}
|
||||
|
||||
void ExCryptDes3Cbc(const EXCRYPT_DES3_STATE* state, const uint8_t* input, uint32_t input_size, uint8_t* output, uint8_t* feed, uint8_t encrypt)
|
||||
{
|
||||
uint64_t last_block = *(uint64_t*)feed;
|
||||
for (uint32_t i = 0; i < input_size / 8; i++)
|
||||
{
|
||||
if (encrypt) {
|
||||
uint64_t temp;
|
||||
memcpy(&temp, input, sizeof(temp));
|
||||
temp = temp ^ last_block;
|
||||
memcpy(output, &temp, sizeof(temp));
|
||||
ExCryptDes3Ecb(state, output, output, encrypt);
|
||||
memcpy(&last_block, output, sizeof(last_block));
|
||||
}
|
||||
else
|
||||
{
|
||||
ExCryptDes3Ecb(state, input, output, encrypt);
|
||||
uint64_t temp;
|
||||
memcpy(&temp, output, sizeof(temp));
|
||||
temp = temp ^ last_block;
|
||||
memcpy(output, &temp, sizeof(temp));
|
||||
memcpy(&last_block, input, sizeof(last_block));
|
||||
}
|
||||
input += 8;
|
||||
output += 8;
|
||||
}
|
||||
*(uint64_t*)feed = last_block;
|
||||
}
|
||||
80
src/drivers/shared/xsm3/excrypt_parve.c
Normal file
80
src/drivers/shared/xsm3/excrypt_parve.c
Normal file
@@ -0,0 +1,80 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xsm3/excrypt.h"
|
||||
|
||||
void ExCryptParveEcb(const uint8_t* key, const uint8_t* sbox, const uint8_t* input, uint8_t* output)
|
||||
{
|
||||
uint8_t block[9];
|
||||
|
||||
memcpy(block, input, 8);
|
||||
block[8] = block[0];
|
||||
|
||||
for (int i = 8; i > 0; i--)
|
||||
{
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
uint8_t x = key[j] + block[j] + i;
|
||||
uint8_t y = sbox[x] + block[j + 1];
|
||||
block[j + 1] = ROTL8(y, 1);
|
||||
}
|
||||
|
||||
block[0] = block[8];
|
||||
}
|
||||
|
||||
memcpy(output, block, 8);
|
||||
}
|
||||
|
||||
void ExCryptParveCbcMac(const uint8_t* key, const uint8_t* sbox, const uint8_t* iv, const uint8_t* input, uint32_t input_size, uint8_t* output)
|
||||
{
|
||||
uint64_t block;
|
||||
uint64_t temp;
|
||||
memcpy(&block, iv, 8);
|
||||
|
||||
if (input_size >= 8)
|
||||
{
|
||||
for (uint32_t i = 0; i < input_size / 8; i++)
|
||||
{
|
||||
memcpy(&temp, input + (i * 8), sizeof(temp));
|
||||
block ^= temp;
|
||||
ExCryptParveEcb(key, sbox, (uint8_t*)&block, (uint8_t*)&block);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(output, &block, 8);
|
||||
}
|
||||
|
||||
void ExCryptChainAndSumMac(const uint32_t* cd, const uint32_t* ab, const uint32_t* input, uint32_t input_dwords, uint32_t* output)
|
||||
{
|
||||
uint64_t out0 = 0;
|
||||
uint64_t out1 = 0;
|
||||
|
||||
uint32_t ab0 = SWAP32(ab[0]) % 0x7FFFFFFF;
|
||||
uint32_t ab1 = SWAP32(ab[1]) % 0x7FFFFFFF;
|
||||
uint32_t cd0 = SWAP32(cd[0]) % 0x7FFFFFFF;
|
||||
uint32_t cd1 = SWAP32(cd[1]) % 0x7FFFFFFF;
|
||||
|
||||
for (uint32_t i = 0; i < input_dwords / 2; i++)
|
||||
{
|
||||
out0 += (uint64_t)SWAP32(input[0]) * 0xE79A9C1;
|
||||
out0 = (out0 % 0x7FFFFFFF) * ab0;
|
||||
out0 += ab1;
|
||||
out0 = out0 % 0x7FFFFFFF;
|
||||
|
||||
out1 += out0;
|
||||
|
||||
out0 = (uint64_t)(SWAP32(input[1]) + out0) * cd0;
|
||||
out0 = (out0 % 0x7FFFFFFF) + cd1;
|
||||
out0 = out0 % 0x7FFFFFFF;
|
||||
|
||||
out1 += out0;
|
||||
|
||||
input += 2;
|
||||
}
|
||||
out0 = SWAP32((out0 + ab1) % 0x7FFFFFFF);
|
||||
out1 = SWAP32((out1 + cd1) % 0x7FFFFFFF);
|
||||
memcpy(output, &out0, sizeof(uint32_t));
|
||||
memcpy(output+1, &out1, sizeof(uint32_t));
|
||||
// output[0] = SWAP32((out0 + ab1) % 0x7FFFFFFF);
|
||||
// output[1] = SWAP32((out1 + cd1) % 0x7FFFFFFF);
|
||||
}
|
||||
155
src/drivers/shared/xsm3/excrypt_sha.c
Normal file
155
src/drivers/shared/xsm3/excrypt_sha.c
Normal file
@@ -0,0 +1,155 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xsm3/excrypt.h"
|
||||
|
||||
// SHA1 code based on https://github.com/mohaps/TinySHA1
|
||||
|
||||
void sha1_process_block(EXCRYPT_SHA_STATE* state)
|
||||
{
|
||||
uint32_t w[80];
|
||||
for (size_t i = 0; i < 16; i++) {
|
||||
w[i] = ((uint32_t)state->buffer[i * 4 + 0] << 24);
|
||||
w[i] |= ((uint32_t)state->buffer[i * 4 + 1] << 16);
|
||||
w[i] |= ((uint32_t)state->buffer[i * 4 + 2] << 8);
|
||||
w[i] |= ((uint32_t)state->buffer[i * 4 + 3]);
|
||||
}
|
||||
for (size_t i = 16; i < 80; i++) {
|
||||
w[i] = ROTL32((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
|
||||
}
|
||||
|
||||
uint32_t a = state->state[0];
|
||||
uint32_t b = state->state[1];
|
||||
uint32_t c = state->state[2];
|
||||
uint32_t d = state->state[3];
|
||||
uint32_t e = state->state[4];
|
||||
|
||||
for (int i = 0; i < 80; ++i) {
|
||||
uint32_t f = 0;
|
||||
uint32_t k = 0;
|
||||
|
||||
if (i < 20) {
|
||||
f = (b & c) | (~b & d);
|
||||
k = 0x5A827999;
|
||||
}
|
||||
else if (i < 40) {
|
||||
f = b ^ c ^ d;
|
||||
k = 0x6ED9EBA1;
|
||||
}
|
||||
else if (i < 60) {
|
||||
f = (b & c) | (b & d) | (c & d);
|
||||
k = 0x8F1BBCDC;
|
||||
}
|
||||
else {
|
||||
f = b ^ c ^ d;
|
||||
k = 0xCA62C1D6;
|
||||
}
|
||||
uint32_t temp = ROTL32(a, 5) + f + e + k + w[i];
|
||||
e = d;
|
||||
d = c;
|
||||
c = ROTL32(b, 30);
|
||||
b = a;
|
||||
a = temp;
|
||||
}
|
||||
|
||||
state->state[0] += a;
|
||||
state->state[1] += b;
|
||||
state->state[2] += c;
|
||||
state->state[3] += d;
|
||||
state->state[4] += e;
|
||||
}
|
||||
|
||||
void sha1_process_byte(EXCRYPT_SHA_STATE* state, uint8_t octet)
|
||||
{
|
||||
uint32_t offset = state->count++ & 0x3F;
|
||||
state->buffer[offset] = octet;
|
||||
if ((state->count & 0x3F) == 0)
|
||||
{
|
||||
sha1_process_block(state);
|
||||
}
|
||||
}
|
||||
|
||||
void ExCryptShaInit(EXCRYPT_SHA_STATE* state)
|
||||
{
|
||||
state->count = 0;
|
||||
state->state[0] = 0x67452301;
|
||||
state->state[1] = 0xEFCDAB89;
|
||||
state->state[2] = 0x98BADCFE;
|
||||
state->state[3] = 0x10325476;
|
||||
state->state[4] = 0xC3D2E1F0;
|
||||
}
|
||||
|
||||
void ExCryptShaUpdate(EXCRYPT_SHA_STATE* state, const uint8_t* input, uint32_t input_size)
|
||||
{
|
||||
for (uint32_t i = 0; i < input_size; i++)
|
||||
{
|
||||
sha1_process_byte(state, input[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ExCryptShaFinal(EXCRYPT_SHA_STATE* state, uint8_t* output, uint32_t output_size)
|
||||
{
|
||||
uint64_t bit_count = (uint64_t)state->count * 8;
|
||||
|
||||
sha1_process_byte(state, 0x80);
|
||||
|
||||
if ((state->count & 0x3F) > 56)
|
||||
{
|
||||
while ((state->count & 0x3F) != 0)
|
||||
{
|
||||
sha1_process_byte(state, 0);
|
||||
}
|
||||
while ((state->count & 0x3F) < 56)
|
||||
{
|
||||
sha1_process_byte(state, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((state->count & 0x3F) < 56)
|
||||
{
|
||||
sha1_process_byte(state, 0);
|
||||
}
|
||||
}
|
||||
|
||||
sha1_process_byte(state, 0);
|
||||
sha1_process_byte(state, 0);
|
||||
sha1_process_byte(state, 0);
|
||||
sha1_process_byte(state, 0);
|
||||
|
||||
sha1_process_byte(state, (uint8_t)((bit_count >> 24) & 0xFF));
|
||||
sha1_process_byte(state, (uint8_t)((bit_count >> 16) & 0xFF));
|
||||
sha1_process_byte(state, (uint8_t)((bit_count >> 8) & 0xFF));
|
||||
sha1_process_byte(state, (uint8_t)((bit_count) & 0xFF));
|
||||
|
||||
//sha1_process_block(state);
|
||||
uint32_t result[5];
|
||||
result[0] = SWAP32(state->state[0]);
|
||||
result[1] = SWAP32(state->state[1]);
|
||||
result[2] = SWAP32(state->state[2]);
|
||||
result[3] = SWAP32(state->state[3]);
|
||||
result[4] = SWAP32(state->state[4]);
|
||||
memcpy(output, result, 0x14);
|
||||
}
|
||||
|
||||
void ExCryptSha(const uint8_t* input1, uint32_t input1_size, const uint8_t* input2, uint32_t input2_size,
|
||||
const uint8_t* input3, uint32_t input3_size, uint8_t* output, uint32_t output_size)
|
||||
{
|
||||
EXCRYPT_SHA_STATE state[1];
|
||||
ExCryptShaInit(state);
|
||||
|
||||
if (input1 && input1_size)
|
||||
{
|
||||
ExCryptShaUpdate(state, input1, input1_size);
|
||||
}
|
||||
if (input2 && input2_size)
|
||||
{
|
||||
ExCryptShaUpdate(state, input2, input2_size);
|
||||
}
|
||||
if (input3 && input3_size)
|
||||
{
|
||||
ExCryptShaUpdate(state, input3, input3_size);
|
||||
}
|
||||
|
||||
ExCryptShaFinal(state, output, output_size);
|
||||
}
|
||||
157
src/drivers/shared/xsm3/usbdsec.c
Normal file
157
src/drivers/shared/xsm3/usbdsec.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
usbdsec.c - part of libxsm3
|
||||
Copyright (C) 2013 oct0xor
|
||||
Copyright (C) 2022 InvoxiPlayGames
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "xsm3/excrypt.h"
|
||||
|
||||
static uint8_t UsbdSecSboxData[256] __attribute__ ((aligned(4))) = {
|
||||
0xB0, 0x3D, 0x9B, 0x70, 0xF3, 0xC7, 0x80, 0x60,
|
||||
0x73, 0x9F, 0x6C, 0xC0, 0xF1, 0x3D, 0xBB, 0x40,
|
||||
0xB3, 0xC8, 0x37, 0x14, 0xDF, 0x49, 0xDA, 0xD4,
|
||||
0x48, 0x22, 0x78, 0x80, 0x6E, 0xCD, 0xE7, 0x00,
|
||||
0x81, 0x86, 0x68, 0xE1, 0x5D, 0x7C, 0x54, 0x2C,
|
||||
0x55, 0x7B, 0xEF, 0x48, 0x42, 0x7B, 0x3B, 0x68,
|
||||
0xE3, 0xDB, 0xAA, 0xC0, 0x0F, 0xA9, 0x96, 0x20,
|
||||
0x95, 0x05, 0x93, 0x94, 0x9A, 0xF6, 0xA3, 0x64,
|
||||
0x5D, 0xCC, 0x76, 0x00, 0xE5, 0x08, 0x19, 0xE8,
|
||||
0x8D, 0x29, 0xD7, 0x4C, 0x21, 0x91, 0x17, 0xF4,
|
||||
0xBC, 0x6A, 0xB3, 0x80, 0x83, 0xC6, 0xD4, 0x90,
|
||||
0x9B, 0xAE, 0x0E, 0xFE, 0x2E, 0x4A, 0xF2, 0x00,
|
||||
0x73, 0x88, 0xD9, 0x40, 0x66, 0xC5, 0xD4, 0x08,
|
||||
0x57, 0xB1, 0x89, 0x48, 0xDC, 0x54, 0xFC, 0x43,
|
||||
0x6A, 0x26, 0x87, 0xB8, 0x09, 0x5F, 0xCE, 0x80,
|
||||
0xE4, 0x0B, 0x05, 0x9C, 0x24, 0xF3, 0xDE, 0xE2,
|
||||
0x3E, 0xEC, 0x38, 0x8A, 0xA2, 0x55, 0xA4, 0x50,
|
||||
0x4E, 0x4B, 0xE9, 0x58, 0x7F, 0x9F, 0x7D, 0x80,
|
||||
0x23, 0x0C, 0x4D, 0x80, 0x05, 0x44, 0x26, 0xB8,
|
||||
0xE9, 0xD8, 0xBC, 0xE6, 0x76, 0x3A, 0x6E, 0xA4,
|
||||
0x19, 0xDE, 0xC2, 0xD0, 0xC4, 0xBC, 0xC3, 0x5C,
|
||||
0x59, 0xDF, 0x16, 0x46, 0x39, 0x70, 0xF4, 0xEE,
|
||||
0x2D, 0x58, 0x5A, 0xA8, 0x17, 0x86, 0x6B, 0x60,
|
||||
0x29, 0x58, 0x4D, 0xD2, 0x5F, 0x28, 0x7A, 0xD8,
|
||||
0x8E, 0x79, 0xEA, 0x82, 0x94, 0x33, 0x31, 0x81,
|
||||
0xD9, 0x22, 0xD5, 0x10, 0xDA, 0x92, 0xA0, 0x7D,
|
||||
0x3D, 0xDA, 0xAC, 0x1C, 0xA2, 0x53, 0x31, 0xB8,
|
||||
0x3C, 0x96, 0x52, 0x00, 0x82, 0x6B, 0x56, 0xA0,
|
||||
0xD3, 0xC2, 0x40, 0xC7, 0x1B, 0x7F, 0xDC, 0x01,
|
||||
0x72, 0x70, 0xB1, 0x8C, 0x01, 0x09, 0x09, 0x36,
|
||||
0xFC, 0x97, 0xEA, 0xDE, 0xE3, 0x0D, 0xAE, 0x7E,
|
||||
0xE3, 0x0D, 0xAE, 0x7E, 0x33, 0x69, 0x80, 0x40
|
||||
};
|
||||
|
||||
static uint8_t UsbdSecPlainTextData[128] __attribute__ ((aligned(4))) = {
|
||||
0xD1, 0xD2, 0xF2, 0x80, 0x6E, 0xBA, 0x0C, 0xC0,
|
||||
0xB6, 0xC4, 0xC9, 0xD8, 0x61, 0x75, 0x1D, 0x1A,
|
||||
0x3F, 0x95, 0x58, 0xBE, 0xD8, 0x0D, 0xE2, 0xC0,
|
||||
0xD0, 0x21, 0x79, 0x20, 0x65, 0x2D, 0x99, 0x40,
|
||||
0x3C, 0x96, 0x52, 0x00, 0x1B, 0x7F, 0xDC, 0x01,
|
||||
0x82, 0x1C, 0x13, 0xD8, 0x33, 0x69, 0x80, 0x40,
|
||||
0xFC, 0x97, 0xEA, 0xDE, 0x08, 0xEA, 0x14, 0xDC,
|
||||
0xEB, 0x0F, 0x6A, 0x18, 0x6F, 0x78, 0x2C, 0xB0,
|
||||
0xD3, 0xC2, 0x40, 0xC7, 0x82, 0x6B, 0x56, 0xA0,
|
||||
0x19, 0x09, 0x36, 0xE0, 0x72, 0x70, 0xB1, 0x8C,
|
||||
0xE3, 0x0D, 0xAE, 0x7E, 0x50, 0xA5, 0x2B, 0xE2,
|
||||
0xC9, 0xAF, 0xC7, 0x70, 0x1C, 0x29, 0x80, 0x56,
|
||||
0x24, 0xF0, 0x66, 0xFA, 0x02, 0x2B, 0x58, 0x98,
|
||||
0x8F, 0xE4, 0xD1, 0x3C, 0x6E, 0x38, 0x2A, 0xFF,
|
||||
0xB8, 0xFA, 0x35, 0xB0, 0x52, 0x49, 0xC5, 0xB4,
|
||||
0x66, 0xFA, 0x47, 0x55, 0x6C, 0x8D, 0x40, 0x08
|
||||
};
|
||||
|
||||
void UsbdSecXSM3AuthenticationCrypt(const uint8_t *key, const uint8_t *input, size_t length, uint8_t *output, uint8_t encrypt) {
|
||||
EXCRYPT_DES3_STATE des;
|
||||
uint64_t sk[3];
|
||||
uint8_t iv[8];
|
||||
|
||||
// clear local variables
|
||||
memset(iv, 0, sizeof(iv));
|
||||
// run parity on the key
|
||||
ExCryptDesParity(key, 0x10, (uint8_t *)sk);
|
||||
sk[2] = sk[0];
|
||||
// set the key in the state and run triple-des cbc en/decryption on it
|
||||
ExCryptDes3Key(&des, sk);
|
||||
ExCryptDes3Cbc(&des, input, length, output, iv, encrypt);
|
||||
}
|
||||
|
||||
void UsbdSecXSM3AuthenticationMac(const uint8_t *key, uint8_t *salt, uint8_t *input, size_t length, uint8_t *output) {
|
||||
EXCRYPT_DES3_STATE des3;
|
||||
EXCRYPT_DES_STATE des;
|
||||
uint64_t sk[3];
|
||||
uint8_t iv[8];
|
||||
uint8_t temp[8];
|
||||
uint64_t input_temp;
|
||||
int i;
|
||||
|
||||
// clear iv + temp value of stack junk
|
||||
memset(iv, 0, sizeof(iv));
|
||||
memset(temp, 0, sizeof(temp));
|
||||
// run parity on the key
|
||||
ExCryptDesParity(key, 0x10, (uint8_t *)sk);
|
||||
sk[2] = sk[0];
|
||||
// set the key in our initial des state
|
||||
ExCryptDesKey(&des, (uint8_t *)&sk[0]);
|
||||
// if we have a salt, encrypt it into the temp value
|
||||
if (salt) {
|
||||
memcpy(&input_temp, salt, sizeof(input_temp));
|
||||
input_temp = SWAP64(SWAP64(input_temp) + 1);
|
||||
memcpy(salt, &input_temp, sizeof(input_temp)); // no idea what this does
|
||||
ExCryptDesEcb(&des, salt, temp, 1);
|
||||
}
|
||||
// for every 8 byte input block, xor the temp value with it and encrypt over itself
|
||||
for (i = 0; i < length; i += 8) {
|
||||
memcpy(&input_temp, input+i, sizeof(input_temp));
|
||||
*(uint64_t *)temp ^= input_temp;
|
||||
|
||||
ExCryptDesEcb(&des, temp, temp, 1);
|
||||
}
|
||||
// xor the highest bit of the temp value
|
||||
temp[0] ^= 0x80;
|
||||
// set the key and perform the final triple-des encryption
|
||||
ExCryptDes3Key(&des3, sk);
|
||||
ExCryptDes3Cbc(&des3, temp, 8, output, iv, 1);
|
||||
// real kernel does the following, but the above works:
|
||||
// XeCryptDesEcb(des_state_1, temp, temp, 1);
|
||||
// XeCryptDesEcb(des_state_2, temp, temp, 0);
|
||||
// XeCryptDesEcb(des_state_1, temp, output, 1);
|
||||
}
|
||||
|
||||
void UsbdSecXSMAuthenticationAcr(const uint8_t *console_id, const uint8_t *input, const uint8_t *key, uint8_t *output) {
|
||||
uint8_t block[8];
|
||||
uint8_t iv[8];
|
||||
uint8_t ab[8];
|
||||
uint8_t cd[8];
|
||||
|
||||
// fill in the input block with the first 4 bytes of input data and the first 4 bytes of the console ID
|
||||
// *(uint32_t *)block = *(uint32_t *)input;
|
||||
// *(uint32_t *)(block + 4) = *(uint32_t *)console_id;
|
||||
memcpy(block, input, 4);
|
||||
memcpy(block+4, console_id, 4);
|
||||
// run custom "parve" crypto algorithms. idk whar they do
|
||||
ExCryptParveEcb(key, UsbdSecSboxData, input + 0x10, iv);
|
||||
ExCryptParveEcb(key, UsbdSecSboxData, block, cd);
|
||||
ExCryptParveCbcMac(key, UsbdSecSboxData, iv, UsbdSecPlainTextData, 0x80, ab);
|
||||
ExCryptChainAndSumMac((uint32_t *)cd, (uint32_t *)ab, (uint32_t *)UsbdSecPlainTextData, 0x20, (uint32_t *)output);
|
||||
uint64_t current;
|
||||
memcpy(¤t, output, sizeof(current));
|
||||
current ^= *(uint64_t *)ab;
|
||||
// *(uint64_t *)output ^= *(uint64_t *)ab;
|
||||
memcpy(output, ¤t, sizeof(current));
|
||||
}
|
||||
269
src/drivers/shared/xsm3/xsm3.c
Normal file
269
src/drivers/shared/xsm3/xsm3.c
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
xsm3.c - part of libxsm3
|
||||
Copyright (C) 2022 InvoxiPlayGames
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "xsm3/xsm3.h"
|
||||
|
||||
//#include <avr/pgmspace.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
//#include "xsm3/config.h"
|
||||
#include "xsm3/excrypt.h"
|
||||
#include "xsm3/usbdsec.h"
|
||||
|
||||
#define XSM3_NO_DEBUGGING true
|
||||
|
||||
// disable debugging by specifying XSM3_NO_DEBUGGING at compile time
|
||||
#ifndef XSM3_NO_DEBUGGING
|
||||
#define XSM3_printf printf
|
||||
#else
|
||||
#define XSM3_printf
|
||||
#endif // XSM3_NO_DEBUGGING
|
||||
|
||||
// constant variables
|
||||
uint8_t xsm3_id_data_ms_controller[0x1D] = {
|
||||
0x49, 0x4B, 0x00, 0x00, 0x17, 0x41, 0x41, 0x41,
|
||||
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
|
||||
0x00, 0x00, 0x80, 0x02, 0x09, 0x12, 0x82, 0x28,
|
||||
0x03, 0x00, 0x01, 0x01, 0x71};
|
||||
|
||||
// static global keys from the keyvault (shared across every retail system)
|
||||
static const uint8_t xsm3_key_0x1D[0x10] = {
|
||||
0xE3, 0x5B, 0xFB, 0x1C, 0xCD, 0xAD, 0x32, 0x5B,
|
||||
0xF7, 0x0E, 0x07, 0xFD, 0x62, 0x3D, 0xA7, 0xC4};
|
||||
static const uint8_t xsm3_key_0x1E[0x10] = {
|
||||
0x8F, 0x29, 0x08, 0x38, 0x0B, 0x5B, 0xFE, 0x68,
|
||||
0x7C, 0x26, 0x46, 0x2A, 0x51, 0xF2, 0xBC, 0x19};
|
||||
|
||||
// retail keys for generating 0x23/0x24 keys from console ID
|
||||
static const uint8_t xsm3_root_key_0x23[0x10] = {
|
||||
0x82, 0x80, 0x78, 0x68, 0x3A, 0x52, 0x3A, 0x98,
|
||||
0x10, 0xF4, 0x0C, 0x12, 0x70, 0x66, 0xDC, 0xBA};
|
||||
|
||||
static const uint8_t xsm3_root_key_0x24[0x10] = {
|
||||
0x66, 0x62, 0x1A, 0x78, 0xF8, 0x60, 0x9C, 0x8A,
|
||||
0x26, 0x9A, 0x04, 0xAE, 0xD8, 0x5C, 0x1E, 0xC8};
|
||||
|
||||
// response to give to the given challenge command
|
||||
uint8_t xsm3_challenge_response[0x30];
|
||||
// console id fetched from challenge init packet
|
||||
uint8_t xsm3_console_id[0x8];
|
||||
|
||||
// buffer to store the first key fetched from the KV (0x23)
|
||||
static uint8_t xsm3_kv_2des_key_1[0x10];
|
||||
// buffer to store the second key fetched from the KV (0x24)
|
||||
static uint8_t xsm3_kv_2des_key_2[0x10];
|
||||
|
||||
// temporary buffer for decrypting packets
|
||||
static uint8_t xsm3_decryption_buffer[0x30];
|
||||
// identification data for the current device
|
||||
static uint8_t xsm3_identification_data[0x20];
|
||||
// random data sent from the console during the challenge init stage
|
||||
static uint8_t xsm3_random_console_data[0x10];
|
||||
static uint8_t xsm3_random_console_data_enc[0x10];
|
||||
static uint8_t xsm3_random_console_data_swap[0x10];
|
||||
static uint8_t xsm3_random_console_data_swap_enc[0x10];
|
||||
// random data set by the controller during the challenge init stage
|
||||
static uint8_t xsm3_random_controller_data[0x10];
|
||||
// hash of the decrypted data sent by the controller during challenge init
|
||||
static uint8_t xsm3_challenge_init_hash[0x14];
|
||||
void xsm3_initialise_state() {
|
||||
// set all variables to all zeroes
|
||||
memset(xsm3_challenge_response, 0, sizeof(xsm3_challenge_response));
|
||||
memset(xsm3_console_id, 0, sizeof(xsm3_console_id));
|
||||
memset(xsm3_kv_2des_key_1, 0, sizeof(xsm3_kv_2des_key_1));
|
||||
memset(xsm3_kv_2des_key_2, 0, sizeof(xsm3_kv_2des_key_2));
|
||||
memset(xsm3_decryption_buffer, 0, sizeof(xsm3_decryption_buffer));
|
||||
memset(xsm3_identification_data, 0, sizeof(xsm3_identification_data));
|
||||
memset(xsm3_random_console_data, 0, sizeof(xsm3_random_console_data));
|
||||
memset(xsm3_random_console_data_enc, 0, sizeof(xsm3_random_console_data_enc));
|
||||
memset(xsm3_random_console_data_swap, 0, sizeof(xsm3_random_console_data_swap));
|
||||
memset(xsm3_random_console_data_swap_enc, 0, sizeof(xsm3_random_console_data_swap_enc));
|
||||
memset(xsm3_random_controller_data, 0, sizeof(xsm3_random_controller_data));
|
||||
memset(xsm3_challenge_init_hash, 0, sizeof(xsm3_challenge_init_hash));
|
||||
}
|
||||
|
||||
static uint8_t xsm3_calculate_checksum(const uint8_t* packet) {
|
||||
// packet length in header doesn't include the header itself
|
||||
uint8_t packet_length = packet[0x4] + 0x5;
|
||||
uint8_t checksum = 0x00;
|
||||
int i = 0;
|
||||
// checksum is just a XOR over all packet bytes
|
||||
for (i = 0x5; i < packet_length; i++) {
|
||||
checksum ^= packet[i];
|
||||
}
|
||||
// last byte of the packet is the checksum
|
||||
return checksum;
|
||||
}
|
||||
|
||||
void xsm3_set_vid_pid(const uint8_t serial[0x0C], uint16_t vid, uint16_t pid) {
|
||||
memcpy(xsm3_id_data_ms_controller + 6, serial, 0x0C);
|
||||
uint8_t* id_data = xsm3_id_data_ms_controller;
|
||||
// skip over the packet header
|
||||
id_data += 0x5;
|
||||
// vendor ID
|
||||
memcpy(id_data + 0xf, &vid, sizeof(unsigned short));
|
||||
// product ID
|
||||
memcpy(id_data + 0x11, &pid, sizeof(unsigned short));
|
||||
xsm3_id_data_ms_controller[0x1C] = xsm3_calculate_checksum(xsm3_id_data_ms_controller);
|
||||
}
|
||||
|
||||
static bool xsm3_verify_checksum(const uint8_t* packet) {
|
||||
// packet length in header doesn't include the header itself
|
||||
uint8_t packet_length = packet[0x4] + 0x5;
|
||||
// last byte of the packet is the checksum
|
||||
return (xsm3_calculate_checksum(packet) == packet[packet_length]);
|
||||
}
|
||||
|
||||
void xsm3_set_identification_data(const uint8_t id_data[0x1D]) {
|
||||
// validate the checksum
|
||||
if (!xsm3_verify_checksum(id_data)) {
|
||||
XSM3_printf("[ Checksum failed when setting identification data! ]\n");
|
||||
}
|
||||
|
||||
// skip over the packet header
|
||||
id_data += 0x5;
|
||||
|
||||
// prepare the xsm3_identification_data buffer
|
||||
|
||||
// contains serial number (len: 0xC), unknown (len: 0x2) and the "category node" to use (len: 0x1)
|
||||
memcpy(xsm3_identification_data, id_data, 0xF);
|
||||
// vendor ID
|
||||
memcpy(xsm3_identification_data + 0x10, id_data + 0xF, sizeof(unsigned short));
|
||||
// product ID
|
||||
memcpy(xsm3_identification_data + 0x12, id_data + 0x11, sizeof(unsigned short));
|
||||
// unknown
|
||||
memcpy(xsm3_identification_data + 0x14, id_data + 0x13, sizeof(unsigned char));
|
||||
// unknown
|
||||
memcpy(xsm3_identification_data + 0x15, id_data + 0x16, sizeof(unsigned char));
|
||||
// unknown
|
||||
memcpy(xsm3_identification_data + 0x16, id_data + 0x14, sizeof(unsigned short));
|
||||
}
|
||||
|
||||
void xsm3_generate_kv_keys(const uint8_t console_id[0x8]) {
|
||||
// make a sha-1 hash of the console id
|
||||
uint8_t console_id_hash[0x14];
|
||||
ExCryptSha(console_id, 0x8, NULL, 0, NULL, 0, console_id_hash, 0x14);
|
||||
// encrypt it with the root keys for 1st party controllers
|
||||
UsbdSecXSM3AuthenticationCrypt(xsm3_root_key_0x23, console_id_hash, 0x10, xsm3_kv_2des_key_1, 1);
|
||||
UsbdSecXSM3AuthenticationCrypt(xsm3_root_key_0x24, console_id_hash + 0x4, 0x10, xsm3_kv_2des_key_2, 1);
|
||||
}
|
||||
|
||||
void xsm3_do_challenge_init(uint8_t challenge_packet[0x22]) {
|
||||
uint8_t incoming_packet_mac[0x8];
|
||||
uint8_t response_packet_mac[0x8];
|
||||
int i = 0;
|
||||
|
||||
// validate the checksum
|
||||
if (!xsm3_verify_checksum(challenge_packet)) {
|
||||
XSM3_printf("[ Checksum failed when validating challenge init! ]\n");
|
||||
}
|
||||
|
||||
// decrypt the packet content using the static key from the keyvault
|
||||
UsbdSecXSM3AuthenticationCrypt(xsm3_key_0x1D, challenge_packet + 0x5, 0x18, xsm3_decryption_buffer, 0);
|
||||
// first 0x10 bytes are random data
|
||||
memcpy(xsm3_random_console_data, xsm3_decryption_buffer, 0x10);
|
||||
// next 0x8 bytes are from the console certificate
|
||||
memcpy(xsm3_console_id, xsm3_decryption_buffer + 0x10, 0x8);
|
||||
// last 4 bytes of the packet are the last 4 bytes of the MAC
|
||||
UsbdSecXSM3AuthenticationMac(xsm3_key_0x1E, NULL, challenge_packet + 5, 0x18, incoming_packet_mac);
|
||||
// validate the MAC
|
||||
if (memcmp(incoming_packet_mac + 4, challenge_packet + 0x5 + 0x18, 0x4) != 0) {
|
||||
XSM3_printf("[ MAC failed when validating challenge init! ]\n");
|
||||
}
|
||||
xsm3_generate_kv_keys(xsm3_console_id);
|
||||
|
||||
// the random value is swapped at an 8 byte boundary
|
||||
memcpy(xsm3_random_console_data_swap, xsm3_random_console_data + 0x8, 0x8);
|
||||
memcpy(xsm3_random_console_data_swap + 0x8, xsm3_random_console_data, 0x8);
|
||||
// and then encrypted - the regular value encrypted with key 1, the swapped value encrypted with key 2
|
||||
UsbdSecXSM3AuthenticationCrypt(xsm3_kv_2des_key_1, xsm3_random_console_data, 0x10, xsm3_random_console_data_enc, 1);
|
||||
UsbdSecXSM3AuthenticationCrypt(xsm3_kv_2des_key_2, xsm3_random_console_data_swap, 0x10, xsm3_random_console_data_swap_enc, 1);
|
||||
|
||||
// generate random data
|
||||
srand(time(NULL));
|
||||
for (i = 0; i < 0x10; i++) {
|
||||
xsm3_random_controller_data[i] = rand() & 0xFF;
|
||||
}
|
||||
|
||||
// clear response buffers
|
||||
memset(xsm3_challenge_response, 0, sizeof(xsm3_challenge_response));
|
||||
memset(xsm3_decryption_buffer, 0, sizeof(xsm3_decryption_buffer));
|
||||
// set header and packet length of challenge response
|
||||
xsm3_challenge_response[0] = 0x49; // packet magic
|
||||
xsm3_challenge_response[1] = 0x4C;
|
||||
xsm3_challenge_response[4] = 0x28; // packet length
|
||||
// copy random controller, random console data to the encryption buffer
|
||||
memcpy(xsm3_decryption_buffer, xsm3_random_controller_data, 0x10);
|
||||
memcpy(xsm3_decryption_buffer + 0x10, xsm3_random_console_data, 0x10);
|
||||
// save the sha1 hash of the decrypted contents for later
|
||||
ExCryptSha(xsm3_decryption_buffer, 0x20, NULL, 0, NULL, 0, xsm3_challenge_init_hash, 0x14);
|
||||
|
||||
// encrypt challenge response packet using the encrypted random key
|
||||
UsbdSecXSM3AuthenticationCrypt(xsm3_random_console_data_enc, xsm3_decryption_buffer, 0x20, xsm3_challenge_response + 0x5, 1);
|
||||
// calculate MAC using the encrypted swapped random key and use it to calculate ACR
|
||||
UsbdSecXSM3AuthenticationMac(xsm3_random_console_data_swap_enc, NULL, xsm3_challenge_response + 0x5, 0x20, response_packet_mac);
|
||||
// calculate ACR and append to the end of the xsm3_challenge_response
|
||||
UsbdSecXSMAuthenticationAcr(xsm3_console_id, xsm3_identification_data, response_packet_mac, xsm3_challenge_response + 0x5 + 0x20);
|
||||
// calculate the checksum for the response packet
|
||||
xsm3_challenge_response[0x5 + 0x28] = xsm3_calculate_checksum(xsm3_challenge_response);
|
||||
|
||||
// the console random value changes slightly after this point
|
||||
memcpy(xsm3_random_console_data, xsm3_random_controller_data + 0xC, 0x4);
|
||||
memcpy(xsm3_random_console_data + 0x4, xsm3_random_console_data + 0xC, 0x4);
|
||||
}
|
||||
|
||||
void xsm3_do_challenge_verify(uint8_t challenge_packet[0x16]) {
|
||||
uint8_t incoming_packet_mac[0x8];
|
||||
|
||||
// validate the checksum
|
||||
if (!xsm3_verify_checksum(challenge_packet)) {
|
||||
XSM3_printf("[ Checksum failed when validating challenge verify! ]\n");
|
||||
}
|
||||
|
||||
// decrypt the packet using the controller generated random value
|
||||
UsbdSecXSM3AuthenticationCrypt(xsm3_random_controller_data, challenge_packet + 0x5, 0x8, xsm3_decryption_buffer, 0);
|
||||
// replace part of our random encryption value with the decrypted buffer
|
||||
memcpy(xsm3_random_console_data + 0x8, xsm3_decryption_buffer, 0x8);
|
||||
|
||||
// calculate the MAC of the incoming packet
|
||||
UsbdSecXSM3AuthenticationMac(xsm3_challenge_init_hash, xsm3_random_console_data, challenge_packet + 0x5, 0x8, incoming_packet_mac);
|
||||
// validate the MAC
|
||||
if (memcmp(incoming_packet_mac, challenge_packet + 0x5 + 0x8, 0x8) != 0) {
|
||||
XSM3_printf("[ MAC failed when validating challenge verify! ]\n");
|
||||
}
|
||||
// clear response buffers
|
||||
memset(xsm3_challenge_response, 0, sizeof(xsm3_challenge_response));
|
||||
memset(xsm3_decryption_buffer, 0, sizeof(xsm3_decryption_buffer));
|
||||
// set header and packet length of challenge response
|
||||
xsm3_challenge_response[0] = 0x49; // packet magic
|
||||
xsm3_challenge_response[1] = 0x4C;
|
||||
xsm3_challenge_response[4] = 0x10; // packet length
|
||||
// calculate the ACR value and encrypt it into the outgoing packet using the encrypted random
|
||||
UsbdSecXSMAuthenticationAcr(xsm3_console_id, xsm3_identification_data, xsm3_random_console_data + 0x8, xsm3_decryption_buffer);
|
||||
UsbdSecXSM3AuthenticationCrypt(xsm3_random_console_data_enc, xsm3_decryption_buffer, 0x8, xsm3_challenge_response + 0x5, 1);
|
||||
// calculate the MAC of the encrypted packet and append it to the end
|
||||
UsbdSecXSM3AuthenticationMac(xsm3_random_console_data_swap_enc, xsm3_random_console_data, xsm3_challenge_response + 0x5, 0x8, xsm3_challenge_response + 0x5 + 0x8);
|
||||
// calculate the checksum for the response packet
|
||||
xsm3_challenge_response[0x5 + 0x10] = xsm3_calculate_checksum(xsm3_challenge_response);
|
||||
}
|
||||
@@ -2,24 +2,66 @@
|
||||
#include "drivers/xinput/XInputAuthUSBListener.h"
|
||||
#include "peripheralmanager.h"
|
||||
|
||||
#include "xsm3/xsm3.h"
|
||||
|
||||
void XInputAuth::initialize() {
|
||||
if ( available() ) {
|
||||
listener = new XInputAuthUSBListener();
|
||||
if ( !available() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( available() ) {
|
||||
listener = nullptr;
|
||||
if (authType == InputModeAuthType::INPUT_MODE_AUTH_TYPE_USB ) {
|
||||
listener = new XInputAuthUSBListener();
|
||||
xinputAuthData.xinputState = auth_idle_state;
|
||||
xinputAuthData.authCompleted = false;
|
||||
((XInputAuthUSBListener*)listener)->setup();
|
||||
((XInputAuthUSBListener*)listener)->setAuthData(&xinputAuthData);
|
||||
} else {
|
||||
// Generate a serial number from the pico's unique ID
|
||||
uint8_t serial[0x0C];
|
||||
pico_unique_board_id_t id;
|
||||
pico_get_unique_board_id(&id);
|
||||
for(int i = 0; i < 0x0C; i++) {
|
||||
serial[i] = 'A' + (id.id[i]%25); // some alphanumeric from 'A' to 'Z'
|
||||
}
|
||||
xsm3_set_vid_pid(serial, 0x045E, 0x028E);
|
||||
xsm3_initialise_state();
|
||||
xsm3_set_identification_data(xsm3_id_data_ms_controller);
|
||||
xinputAuthData.xinputState = auth_idle_state;
|
||||
xinputAuthData.authCompleted = false;
|
||||
xinputAuthData.dongle_ready = true;
|
||||
memcpy(xinputAuthData.dongleSerial, xsm3_id_data_ms_controller, X360_AUTHLEN_DONGLE_SERIAL);
|
||||
}
|
||||
}
|
||||
|
||||
bool XInputAuth::available() {
|
||||
return PeripheralManager::getInstance().isUSBEnabled(0);
|
||||
// Move options over to their own ps4 data structure or gamepad?
|
||||
if ( authType == InputModeAuthType::INPUT_MODE_AUTH_TYPE_USB ) {
|
||||
return (PeripheralManager::getInstance().isUSBEnabled(0));
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void XInputAuth::process() {
|
||||
((XInputAuthUSBListener*)listener)->process();
|
||||
}
|
||||
// Use USB dongle
|
||||
if ( authType == InputModeAuthType::INPUT_MODE_AUTH_TYPE_USB ) {
|
||||
((XInputAuthUSBListener*)listener)->process(); // send to USB dongle
|
||||
return;
|
||||
}
|
||||
|
||||
// Process Xbox360 Console Request
|
||||
if ( xinputAuthData.xinputState == GPAuthState::send_auth_console_to_dongle ) {
|
||||
if ( xinputAuthData.passthruBufferID == XSM360AuthRequest::XSM360_INIT_AUTH ) {
|
||||
xsm3_do_challenge_init(xinputAuthData.passthruBuffer);
|
||||
memcpy(xinputAuthData.passthruBuffer, xsm3_challenge_response, X360_AUTHLEN_DONGLE_INIT);
|
||||
xinputAuthData.passthruBufferLen = X360_AUTHLEN_DONGLE_INIT;
|
||||
xinputAuthData.xinputState = GPAuthState::send_auth_dongle_to_console;
|
||||
} else if ( xinputAuthData.passthruBufferID == XSM360AuthRequest::XSM360_VERIFY_AUTH ) {
|
||||
xsm3_do_challenge_verify(xinputAuthData.passthruBuffer);
|
||||
memcpy(xinputAuthData.passthruBuffer, xsm3_challenge_response, X360_AUTHLEN_CHALLENGE);
|
||||
xinputAuthData.passthruBufferLen = X360_AUTHLEN_CHALLENGE;
|
||||
xinputAuthData.xinputState = GPAuthState::send_auth_dongle_to_console;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,18 +151,17 @@ void XInputDriver::initialize() {
|
||||
};
|
||||
|
||||
xAuthDriver = nullptr;
|
||||
xAuthSent = false;
|
||||
}
|
||||
|
||||
void XInputDriver::initializeAux() {
|
||||
xAuthDriver = nullptr;
|
||||
// AUTH DRIVER NON-FUNCTIONAL FOR NOW
|
||||
GamepadOptions & gamepadOptions = Storage::getInstance().getGamepadOptions();
|
||||
if ( gamepadOptions.xinputAuthType == InputModeAuthType::INPUT_MODE_AUTH_TYPE_USB ) {
|
||||
xAuthDriver = new XInputAuth();
|
||||
if ( xAuthDriver->available() ) {
|
||||
xAuthDriver->initialize();
|
||||
xinputAuthData = xAuthDriver->getAuthData();
|
||||
}
|
||||
xAuthDriver = new XInputAuth(gamepadOptions.xinputAuthType);
|
||||
if ( xAuthDriver->available() ) {
|
||||
xAuthDriver->initialize();
|
||||
xinputAuthData = xAuthDriver->getAuthData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,8 +172,8 @@ USBListener * XInputDriver::get_usb_auth_listener() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool XInputDriver::getAuthEnabled() {
|
||||
return (xAuthDriver != nullptr);
|
||||
bool XInputDriver::getAuthSent() {
|
||||
return xAuthSent;
|
||||
}
|
||||
|
||||
bool XInputDriver::process(Gamepad * gamepad) {
|
||||
@@ -315,6 +314,7 @@ bool XInputDriver::vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_co
|
||||
}
|
||||
len = X360_AUTHLEN_DONGLE_SERIAL;
|
||||
memcpy(tud_buffer, xinputAuthData->dongleSerial, len);
|
||||
xAuthSent = true; // triggers on serial request but this is only for visual flair
|
||||
break;
|
||||
case XSM360_RESPOND_CHALLENGE:
|
||||
if ( xinputAuthData->xinputState == GPAuthState::send_auth_dongle_to_console ) {
|
||||
|
||||
@@ -80,7 +80,7 @@ export default {
|
||||
'xbone-mode-text':
|
||||
'<span>INFO:</span> Xbox One requires a USB host connection and USB dongle to properly authenticate in Xbox One mode.',
|
||||
'xinput-mode-text':
|
||||
'<span>INFO:</span> Xinput will work on a PC without any authentication. If you would like to on a Xbox 360 please choose USB authentication and attach an appropriate dongle.',
|
||||
'<span>INFO:</span> XInput mode will work on a retail Xbox 360 console without a dongle. Only select USB if you would like to use an external dongle for authentication.',
|
||||
'hotkey-settings-label': 'Hotkey Settings',
|
||||
'hotkey-settings-sub-header':
|
||||
'The <strong>Fn</strong> slider provides a mappable Function button in the <link_pinmap>Pin Mapping</link_pinmap> page. By selecting the <strong>Fn</strong> slider option, the Function button must be held along with the selected hotkey settings. <br /> Additionally, select <strong>None</strong> from the dropdown to unassign any button.',
|
||||
|
||||
Reference in New Issue
Block a user