Prepare Regist for PS5

This commit is contained in:
Florian Märkl 2020-12-11 16:47:39 +01:00
commit 21ef8fa018
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
7 changed files with 86 additions and 32 deletions

View file

@ -29,6 +29,7 @@ class RegistDialog : public QDialog
QRadioButton *ps4_pre9_radio_button;
QRadioButton *ps4_pre10_radio_button;
QRadioButton *ps4_10_radio_button;
QRadioButton *ps5_radio_button;
QLineEdit *psn_online_id_edit;
QLineEdit *psn_account_id_edit;
QLineEdit *pin_edit;

View file

@ -49,24 +49,27 @@ RegistDialog::RegistDialog(Settings *settings, const QString &host, QWidget *par
psn_account_id_edit->setEnabled(need_account_id);
};
auto version_layout = new QVBoxLayout(nullptr);
ps4_pre9_radio_button = new QRadioButton(tr("< 7.0"), this);
version_layout->addWidget(ps4_pre9_radio_button);
auto target_layout = new QVBoxLayout(nullptr);
ps4_pre9_radio_button = new QRadioButton(tr("PS4 Firmware < 7.0"), this);
target_layout->addWidget(ps4_pre9_radio_button);
connect(ps4_pre9_radio_button, &QRadioButton::toggled, this, UpdatePSNIDEdits);
ps4_pre10_radio_button = new QRadioButton(tr(">= 7.0, < 8.0"), this);
version_layout->addWidget(ps4_pre10_radio_button);
ps4_pre10_radio_button = new QRadioButton(tr("PS4 Firmware >= 7.0, < 8.0"), this);
target_layout->addWidget(ps4_pre10_radio_button);
connect(ps4_pre10_radio_button, &QRadioButton::toggled, this, UpdatePSNIDEdits);
ps4_10_radio_button = new QRadioButton(tr(">= 8.0"), this);
version_layout->addWidget(ps4_10_radio_button);
ps4_10_radio_button = new QRadioButton(tr("PS4 Firmware >= 8.0"), this);
target_layout->addWidget(ps4_10_radio_button);
connect(ps4_10_radio_button, &QRadioButton::toggled, this, UpdatePSNIDEdits);
form_layout->addRow(tr("PS4 Firmware:"), version_layout);
ps5_radio_button = new QRadioButton(tr("PS5"), this);
target_layout->addWidget(ps5_radio_button);
connect(ps5_radio_button, &QRadioButton::toggled, this, UpdatePSNIDEdits);
form_layout->addRow(tr("Console:"), target_layout);
psn_online_id_edit = new QLineEdit(this);
form_layout->addRow(tr("PSN Online-ID (username, case-sensitive):"), psn_online_id_edit);
psn_account_id_edit = new QLineEdit(this);
form_layout->addRow(tr("PSN Account-ID (base64):"), psn_account_id_edit);
ps4_10_radio_button->setChecked(true);
ps5_radio_button->setChecked(true);
UpdatePSNIDEdits();
@ -115,8 +118,10 @@ void RegistDialog::accept()
info.target = CHIAKI_TARGET_PS4_8;
else if(ps4_pre10_radio_button->isChecked())
info.target = CHIAKI_TARGET_PS4_9;
else
else if(ps4_10_radio_button->isChecked())
info.target = CHIAKI_TARGET_PS4_10;
else
info.target = CHIAKI_TARGET_PS5_1;
bool need_account_id = NeedAccountId();
QByteArray psn_id; // keep this out of the if scope

View file

@ -11,6 +11,7 @@
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
@ -61,11 +62,21 @@ typedef enum
{
// values must not change
CHIAKI_TARGET_PS4_UNKNOWN = 0,
CHIAKI_TARGET_PS4_8 = 800,
CHIAKI_TARGET_PS4_9 = 900,
CHIAKI_TARGET_PS4_10 = 1000
CHIAKI_TARGET_PS4_8 = 800,
CHIAKI_TARGET_PS4_9 = 900,
CHIAKI_TARGET_PS4_10 = 1000,
CHIAKI_TARGET_PS5_UNKNOWN = 1000000,
CHIAKI_TARGET_PS5_1 = 1000100
} ChiakiTarget;
static inline bool chiaki_target_is_unknown(ChiakiTarget target)
{
return target == CHIAKI_TARGET_PS5_UNKNOWN
|| target == CHIAKI_TARGET_PS4_UNKNOWN;
}
static inline bool chiaki_target_is_ps5(ChiakiTarget target) { return target >= CHIAKI_TARGET_PS5_UNKNOWN; }
/**
* Perform initialization of global state needed for using the Chiaki lib
*/

View file

@ -35,7 +35,7 @@ CHIAKI_EXPORT const char *chiaki_rp_application_reason_string(uint32_t reason);
*/
CHIAKI_EXPORT const char *chiaki_rp_version_string(ChiakiTarget target);
CHIAKI_EXPORT ChiakiTarget chiaki_rp_version_parse(const char *rp_version_str);
CHIAKI_EXPORT ChiakiTarget chiaki_rp_version_parse(const char *rp_version_str, bool is_ps5);
#define CHIAKI_RP_DID_SIZE 32
@ -70,6 +70,7 @@ CHIAKI_EXPORT void chiaki_connect_video_profile_preset(ChiakiConnectVideoProfile
typedef struct chiaki_connect_info_t
{
bool ps5;
const char *host; // null terminated
char regist_key[CHIAKI_SESSION_AUTH_SIZE]; // must be completely filled (pad with \0)
uint8_t morning[0x10];
@ -149,6 +150,7 @@ typedef struct chiaki_session_t
{
struct
{
bool ps5;
struct addrinfo *host_addrinfos;
struct addrinfo *host_addrinfo_selected;
char hostname[128];

View file

@ -42,17 +42,21 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_regist_start(ChiakiRegist *regist, ChiakiLo
if(!regist->info.host)
return CHIAKI_ERR_MEMORY;
ChiakiErrorCode err = CHIAKI_ERR_UNKNOWN;
if(regist->info.psn_online_id)
{
regist->info.psn_online_id = strdup(regist->info.psn_online_id);
if(!regist->info.psn_online_id)
{
err = CHIAKI_ERR_MEMORY;
goto error_host;
}
}
regist->cb = cb;
regist->cb_user = cb_user;
ChiakiErrorCode err = chiaki_stop_pipe_init(&regist->stop_pipe);
err = chiaki_stop_pipe_init(&regist->stop_pipe);
if(err != CHIAKI_ERR_SUCCESS)
goto error_psn_id;
@ -98,9 +102,25 @@ static const char *const request_head_fmt =
"Connection: close\r\n"
"Content-Length: %llu\r\n";
static const char *request_path = "/sie/ps4/rp/sess/rgst";
static const char *request_path_ps5 = "/sie/ps5/rp/sess/rgst";
static const char *request_path_ps4 = "/sie/ps4/rp/sess/rgst";
static const char *request_path_ps4_pre10 = "/sce/rp/regist";
static const char *request_path(ChiakiTarget target)
{
switch(target)
{
case CHIAKI_TARGET_PS5_UNKNOWN:
case CHIAKI_TARGET_PS5_1:
return request_path_ps5;
case CHIAKI_TARGET_PS4_8:
case CHIAKI_TARGET_PS4_9:
return request_path_ps4_pre10;
default:
return request_path_ps4;
}
}
static const char *const request_rp_version_fmt = "RP-Version: %s\r\n";
static const char *const request_tail = "\r\n";
@ -119,8 +139,7 @@ static const char *const request_inner_online_id_fmt =
static int request_header_format(char *buf, size_t buf_size, size_t payload_size, ChiakiTarget target)
{
int cur = snprintf(buf, buf_size, request_head_fmt,
target < CHIAKI_TARGET_PS4_10 ? request_path_ps4_pre10 : request_path,
int cur = snprintf(buf, buf_size, request_head_fmt, request_path(target),
(unsigned long long)payload_size);
if(cur < 0 || cur >= payload_size)
return -1;
@ -339,12 +358,16 @@ static ChiakiErrorCode regist_search(ChiakiRegist *regist, struct addrinfo *addr
ChiakiErrorCode err = CHIAKI_ERR_SUCCESS;
const char *src = chiaki_target_is_ps5(regist->info.target) ? "SRC3" : "SRC2";
const char *res = chiaki_target_is_ps5(regist->info.target) ? "RES3" : "RES2";
size_t res_size = strlen(res);
CHIAKI_LOGI(regist->log, "Regist sending search packet");
int r;
if(regist->info.broadcast)
r = sendto_broadcast(regist->log, sock, "SRC2", 4, 0, &send_addr, send_addr_len);
r = sendto_broadcast(regist->log, sock, src, strlen(src) + 1, 0, &send_addr, send_addr_len);
else
r = send(sock, "SRC2", 4, 0);
r = send(sock, src, strlen(src) + 1, 0);
if(r < 0)
{
CHIAKI_LOGE(regist->log, "Regist failed to send search: %s", strerror(errno));
@ -379,10 +402,10 @@ static ChiakiErrorCode regist_search(ChiakiRegist *regist, struct addrinfo *addr
goto done;
}
CHIAKI_LOGV(regist->log, "Regist received packet:");
CHIAKI_LOGV(regist->log, "Regist received packet: %d >= %d", n, res_size);
chiaki_log_hexdump(regist->log, CHIAKI_LOG_VERBOSE, buf, n);
if(n >= 4 && memcmp(buf, "RES2", 4) == 0)
if(n >= res_size && !memcmp(buf, res, res_size))
{
char addr[64];
const char *addr_str = sockaddr_str(recv_addr, addr, sizeof(addr));

View file

@ -971,18 +971,21 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_init_regist(ChiakiRPCrypt *rpcrypt,
}
#define HMAC_KEY_SIZE 0x10
static const uint8_t hmac_key[HMAC_KEY_SIZE] = { 0x20, 0xd6, 0x6f, 0x59, 0x04, 0xea, 0x7c, 0x14, 0xe5, 0x57, 0xff, 0xc5, 0x2e, 0x48, 0x8a, 0xc8 };
static const uint8_t hmac_key_ps5[HMAC_KEY_SIZE] = { 0x46, 0x46, 0x87, 0xb3, 0x49, 0xca, 0x8c, 0xe8, 0x59, 0xc5, 0x27, 0x0f, 0x5d, 0x7a, 0x69, 0xd6 };
static const uint8_t hmac_key_ps4[HMAC_KEY_SIZE] = { 0x20, 0xd6, 0x6f, 0x59, 0x04, 0xea, 0x7c, 0x14, 0xe5, 0x57, 0xff, 0xc5, 0x2e, 0x48, 0x8a, 0xc8 };
static const uint8_t hmac_key_ps4_pre10[HMAC_KEY_SIZE] = { 0xac, 0x07, 0x88, 0x83, 0xc8, 0x3a, 0x1f, 0xe8, 0x11, 0x46, 0x3a, 0xf3, 0x9e, 0xe3, 0xe3, 0x77 };
static const uint8_t *rpcrypt_hmac_key(ChiakiRPCrypt *rpcrypt)
{
switch(rpcrypt->target)
{
case CHIAKI_TARGET_PS5_1:
return hmac_key_ps5;
case CHIAKI_TARGET_PS4_8:
case CHIAKI_TARGET_PS4_9:
return hmac_key_ps4_pre10;
default:
return hmac_key;
return hmac_key_ps4;
}
}

View file

@ -62,18 +62,26 @@ const char *chiaki_rp_version_string(ChiakiTarget version)
return "9.0";
case CHIAKI_TARGET_PS4_10:
return "10.0";
case CHIAKI_TARGET_PS5_1:
return "1.0";
default:
return NULL;
}
}
CHIAKI_EXPORT ChiakiTarget chiaki_rp_version_parse(const char *rp_version_str)
CHIAKI_EXPORT ChiakiTarget chiaki_rp_version_parse(const char *rp_version_str, bool is_ps5)
{
if(strcmp(rp_version_str, "8.0") == 0)
if(is_ps5)
{
if(!strcmp(rp_version_str, "1.0"))
return CHIAKI_TARGET_PS5_1;
return CHIAKI_TARGET_PS5_UNKNOWN;
}
if(!strcmp(rp_version_str, "8.0"))
return CHIAKI_TARGET_PS4_8;
if(strcmp(rp_version_str, "9.0") == 0)
if(!strcmp(rp_version_str, "9.0"))
return CHIAKI_TARGET_PS4_9;
if(strcmp(rp_version_str, "10.0") == 0)
if(!strcmp(rp_version_str, "10.0"))
return CHIAKI_TARGET_PS4_10;
return CHIAKI_TARGET_PS4_UNKNOWN;
}
@ -205,6 +213,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_session_init(ChiakiSession *session, Chiaki
chiaki_controller_state_set_idle(&session->controller_state);
session->connect_info.ps5 = connect_info->ps5;
memcpy(session->connect_info.regist_key, connect_info->regist_key, sizeof(session->connect_info.regist_key));
memcpy(session->connect_info.morning, connect_info->morning, sizeof(session->connect_info.morning));
@ -359,17 +368,17 @@ static void *session_thread_func(void *arg)
CHIAKI_LOGI(session->log, "Starting session request");
ChiakiTarget server_target = CHIAKI_TARGET_PS4_UNKNOWN;
ChiakiTarget server_target = session->connect_info.ps5 ? CHIAKI_TARGET_PS5_UNKNOWN : CHIAKI_TARGET_PS4_UNKNOWN;
success = session_thread_request_session(session, &server_target);
if(!success && server_target != CHIAKI_TARGET_PS4_UNKNOWN)
if(!success && chiaki_target_is_unknown(server_target))
{
CHIAKI_LOGI(session->log, "Attempting to re-request session with Server's RP-Version");
session->target = server_target;
success = session_thread_request_session(session, &server_target);
}
if(!success && server_target != CHIAKI_TARGET_PS4_UNKNOWN)
if(!success && chiaki_target_is_unknown(server_target))
{
CHIAKI_LOGI(session->log, "Attempting to re-request session even harder with Server's RP-Version!!!");
session->target = server_target;
@ -757,7 +766,7 @@ static bool session_thread_request_session(ChiakiSession *session, ChiakiTarget
{
CHIAKI_LOGI(session->log, "Reported RP-Version mismatch. ours = %s, server = %s",
rp_version_str ? rp_version_str : "", response.rp_version);
*target_out = chiaki_rp_version_parse(response.rp_version);
*target_out = chiaki_rp_version_parse(response.rp_version, session->connect_info.ps5);
if(*target_out != CHIAKI_TARGET_PS4_UNKNOWN)
CHIAKI_LOGI(session->log, "Detected Server RP-Version %s", chiaki_rp_version_string(*target_out));
else if(!strcmp(response.rp_version, "5.0"))