diff --git a/gui/include/registdialog.h b/gui/include/registdialog.h index 06098ee..7d16b0f 100644 --- a/gui/include/registdialog.h +++ b/gui/include/registdialog.h @@ -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; diff --git a/gui/src/registdialog.cpp b/gui/src/registdialog.cpp index 50c0cad..c101bf3 100644 --- a/gui/src/registdialog.cpp +++ b/gui/src/registdialog.cpp @@ -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 diff --git a/lib/include/chiaki/common.h b/lib/include/chiaki/common.h index 651d9fa..aa70cbc 100644 --- a/lib/include/chiaki/common.h +++ b/lib/include/chiaki/common.h @@ -11,6 +11,7 @@ #include #include +#include #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 */ diff --git a/lib/include/chiaki/session.h b/lib/include/chiaki/session.h index 72e9041..5da7087 100644 --- a/lib/include/chiaki/session.h +++ b/lib/include/chiaki/session.h @@ -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]; diff --git a/lib/src/regist.c b/lib/src/regist.c index 1181b4d..07063bc 100644 --- a/lib/src/regist.c +++ b/lib/src/regist.c @@ -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(®ist->stop_pipe); + err = chiaki_stop_pipe_init(®ist->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)); diff --git a/lib/src/rpcrypt.c b/lib/src/rpcrypt.c index bfab3e8..270048b 100644 --- a/lib/src/rpcrypt.c +++ b/lib/src/rpcrypt.c @@ -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; } } diff --git a/lib/src/session.c b/lib/src/session.c index 50d3ece..ab33d97 100644 --- a/lib/src/session.c +++ b/lib/src/session.c @@ -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"))