diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 1b4651c..9d2daca 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -31,7 +31,8 @@ set(HEADER_FILES
include/chiaki/controller.h
include/chiaki/takionsendbuffer.h
include/chiaki/time.h
- include/chiaki/fec.h)
+ include/chiaki/fec.h
+ include/chiaki/regist.h)
set(SOURCE_FILES
src/common.c
@@ -65,7 +66,8 @@ set(SOURCE_FILES
src/controller.c
src/takionsendbuffer.c
src/time.c
- src/fec)
+ src/fec
+ src/regist.c)
add_subdirectory(protobuf)
include_directories("${NANOPB_SOURCE_DIR}")
diff --git a/lib/include/chiaki/regist.h b/lib/include/chiaki/regist.h
new file mode 100644
index 0000000..e62fb0e
--- /dev/null
+++ b/lib/include/chiaki/regist.h
@@ -0,0 +1,69 @@
+/*
+ * This file is part of Chiaki.
+ *
+ * Chiaki is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chiaki 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chiaki. If not, see .
+ */
+
+#ifndef CHIAKI_REGIST_H
+#define CHIAKI_REGIST_H
+
+#include "common.h"
+#include "log.h"
+#include "thread.h"
+#include "stoppipe.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct chiaki_regist_info_t
+{
+ char *host;
+ char *psn_id;
+ uint32_t pin;
+} ChiakiRegistInfo;
+
+typedef enum chiaki_regist_event_type_t {
+ CHIAKI_REGIST_EVENT_TYPE_CONNECTED,
+ CHIAKI_REGIST_EVENT_TYPE_FINISHED_FAILED,
+ CHIAKI_REGIST_EVENT_TYPE_FINISHED_SUCCESS
+} ChiakiRegistEventType;
+
+typedef struct chiaki_regist_event_t
+{
+ ChiakiRegistEventType type;
+} ChiakiRegistEvent;
+
+typedef void (*ChiakiRegistCb)(ChiakiRegistEvent *event, void *user);
+
+typedef struct chiaki_regist_t
+{
+ ChiakiLog *log;
+ ChiakiRegistInfo info;
+ ChiakiRegistCb cb;
+ void *cb_user;
+
+ ChiakiThread thread;
+ ChiakiStopPipe stop_pipe;
+} ChiakiRegist;
+
+CHIAKI_EXPORT ChiakiErrorCode chiaki_regist_start(ChiakiRegist *regist, ChiakiLog *log, ChiakiRegistInfo *info, ChiakiRegistCb cb, void *cb_user);
+CHIAKI_EXPORT void chiaki_regist_fini(ChiakiRegist *regist);
+CHIAKI_EXPORT void chiaki_regist_stop(ChiakiRegist *regist);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // CHIAKI_REGIST_H
diff --git a/lib/include/chiaki/rpcrypt.h b/lib/include/chiaki/rpcrypt.h
index eba61d9..7928b80 100644
--- a/lib/include/chiaki/rpcrypt.h
+++ b/lib/include/chiaki/rpcrypt.h
@@ -36,8 +36,10 @@ typedef struct chiaki_rpcrypt_t
} ChiakiRPCrypt;
CHIAKI_EXPORT void chiaki_rpcrypt_bright_ambassador(uint8_t *bright, uint8_t *ambassador, const uint8_t *nonce, const uint8_t *morning);
+CHIAKI_EXPORT void chiaki_rpcrypt_aeropause(uint8_t *aeropause, const uint8_t *nonce);
-CHIAKI_EXPORT void chiaki_rpcrypt_init(ChiakiRPCrypt *rpcrypt, const uint8_t *nonce, const uint8_t *morning);
+CHIAKI_EXPORT void chiaki_rpcrypt_init_auth(ChiakiRPCrypt *rpcrypt, const uint8_t *nonce, const uint8_t *morning);
+CHIAKI_EXPORT void chiaki_rpcrypt_init_regist(ChiakiRPCrypt *rpcrypt, const uint8_t *nonce, uint32_t pin);
CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_generate_iv(ChiakiRPCrypt *rpcrypt, uint8_t *iv, uint64_t counter);
CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_encrypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, uint8_t *in, uint8_t *out, size_t sz);
CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_decrypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, uint8_t *in, uint8_t *out, size_t sz);
diff --git a/lib/src/regist.c b/lib/src/regist.c
new file mode 100644
index 0000000..4b4dce6
--- /dev/null
+++ b/lib/src/regist.c
@@ -0,0 +1,228 @@
+/*
+ * This file is part of Chiaki.
+ *
+ * Chiaki is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chiaki 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chiaki. If not, see .
+ */
+
+#include "utils.h"
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#define REGIST_PORT 9295
+
+static void *regist_thread_func(void *user);
+static int regist_connect(ChiakiRegist *regist);
+
+CHIAKI_EXPORT ChiakiErrorCode chiaki_regist_start(ChiakiRegist *regist, ChiakiLog *log, ChiakiRegistInfo *info, ChiakiRegistCb cb, void *cb_user)
+{
+ regist->log = log;
+ regist->info = *info;
+ regist->info.host = strdup(regist->info.host);
+ if(!regist->info.host)
+ return CHIAKI_ERR_MEMORY;
+ regist->info.psn_id = strdup(regist->info.psn_id);
+ if(!regist->info.psn_id)
+ goto error_host;
+
+ regist->cb = cb;
+ regist->cb_user = cb_user;
+
+ ChiakiErrorCode err = chiaki_stop_pipe_init(®ist->stop_pipe);
+ if(err != CHIAKI_ERR_SUCCESS)
+ goto error_psn_id;
+
+ err = chiaki_thread_create(®ist->thread, regist_thread_func, regist);
+ if(err != CHIAKI_ERR_SUCCESS)
+ goto error_stop_pipe;
+
+ return CHIAKI_ERR_SUCCESS;
+
+error_stop_pipe:
+ chiaki_stop_pipe_fini(®ist->stop_pipe);
+error_psn_id:
+ free(regist->info.psn_id);
+error_host:
+ free(regist->info.host);
+ return err;
+}
+
+CHIAKI_EXPORT void chiaki_regist_fini(ChiakiRegist *regist)
+{
+ chiaki_thread_join(®ist->thread, NULL);
+ chiaki_stop_pipe_fini(®ist->stop_pipe);
+ free(regist->info.host);
+}
+
+CHIAKI_EXPORT void chiaki_regist_stop(ChiakiRegist *regist)
+{
+ chiaki_stop_pipe_stop(®ist->stop_pipe);
+}
+
+static void regist_event_simple(ChiakiRegist *regist, ChiakiRegistEventType type)
+{
+ ChiakiRegistEvent event = { 0 };
+ event.type = type;
+ regist->cb(&event, regist->cb_user);
+}
+
+static const char * const request_fmt =
+ "POST /sce/rp/regist HTTP/1.1\r\n"
+ "HOST: 10.0.2.15\r\n" // random lol
+ "User-Agent: remoteplay Windows\r\n"
+ "Connection: close\r\n"
+ "Content-Length: %llu\r\n\r\n";
+
+static const char * const request_inner_fmt =
+ "Client-Type: Windows\r\n"
+ "Np-Online-Id: %s\r\n\r\n";
+
+static void *regist_thread_func(void *user)
+{
+ ChiakiRegist *regist = user;
+
+ uint8_t nonce[CHIAKI_KEY_BYTES];
+ ChiakiErrorCode err = chiaki_random_bytes_crypt(nonce, sizeof(nonce));
+ if(err != CHIAKI_ERR_SUCCESS)
+ {
+ CHIAKI_LOGE(regist->log, "Regist failed to generate random nonce");
+ goto fail;
+ }
+
+ ChiakiRPCrypt crypt;
+ chiaki_rpcrypt_init_regist(&crypt, nonce, regist->info.pin);
+
+ uint8_t payload[0x400];
+ static const size_t inner_header_off = 0x1e0;
+ memset(payload, 'A', inner_header_off);
+ chiaki_rpcrypt_aeropause(payload + 0x11c, nonce);
+ int inner_header_size = snprintf((char *)payload + inner_header_off, sizeof(payload) - inner_header_off, request_inner_fmt, regist->info.psn_id);
+ if(inner_header_size >= sizeof(payload) - inner_header_off)
+ {
+ CHIAKI_LOGE(regist->log, "Regist failed to format payload");
+ goto fail;
+ }
+ chiaki_rpcrypt_encrypt(&crypt, 0, payload + inner_header_off, payload + inner_header_off, inner_header_size);
+ size_t payload_size = inner_header_off + inner_header_size;
+
+ char request_header[0x100];
+ int request_header_size = snprintf(request_header, sizeof(request_header), request_fmt, (unsigned long long)payload_size);
+ if(request_header_size >= sizeof(request_header))
+ {
+ CHIAKI_LOGE(regist->log, "Regist failed to format request");
+ goto fail;
+ }
+
+ int sock = regist_connect(regist);
+ if(sock < 0)
+ {
+ CHIAKI_LOGE(regist->log, "Regist eventually failed to connect");
+ goto fail;
+ }
+
+ int s = send(sock, request_header, request_header_size, 0);
+ if(s < 0)
+ {
+ CHIAKI_LOGE(regist->log, "Regist failed to send request header");
+ goto fail_socket;
+ }
+
+ s = send(s, payload, payload_size, 0);
+ if(s < 0)
+ {
+ CHIAKI_LOGE(regist->log, "Regist failed to send payload");
+ goto fail_socket;
+ }
+
+ char recv_buf[0x100];
+ ssize_t received;
+rerecv:
+ received = recv(sock, recv_buf, sizeof(recv_buf) - 1, 0);
+ if(received < 0)
+ CHIAKI_LOGE(regist->log, "Failed");
+ else
+ {
+ chiaki_log_hexdump(regist->log, CHIAKI_LOG_DEBUG, (uint8_t *)recv_buf, received);
+ goto rerecv;
+ }
+
+ close(sock);
+
+ regist_event_simple(regist, CHIAKI_REGIST_EVENT_TYPE_FINISHED_SUCCESS); // TODO: communicate params
+ return NULL;
+
+fail_socket:
+ close(sock);
+fail:
+ regist_event_simple(regist, CHIAKI_REGIST_EVENT_TYPE_FINISHED_FAILED);
+ return NULL;
+}
+
+static int regist_connect(ChiakiRegist *regist)
+{
+ struct addrinfo *addrinfos;
+ int r = getaddrinfo(regist->info.host, NULL, NULL, &addrinfos);
+ if(r != 0)
+ {
+ CHIAKI_LOGE(regist->log, "Regist failed to getaddrinfo on %s", regist->info.host);
+ regist_event_simple(regist, CHIAKI_REGIST_EVENT_TYPE_FINISHED_FAILED);
+ return -1;
+ }
+
+ int sock = -1;
+ for(struct addrinfo *ai=addrinfos; ai; ai=ai->ai_next)
+ {
+ if(ai->ai_protocol != IPPROTO_TCP)
+ continue;
+
+ if(ai->ai_addr->sa_family != AF_INET) // TODO: support IPv6
+ continue;
+
+ struct sockaddr *sa = malloc(ai->ai_addrlen);
+ if(!sa)
+ continue;
+ memcpy(sa, ai->ai_addr, ai->ai_addrlen);
+
+ set_port(sa, htons(REGIST_PORT));
+
+ sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if(sock < 0)
+ {
+ free(sa);
+ continue;
+ }
+ r = connect(sock, sa, ai->ai_addrlen);
+ if(r < 0)
+ {
+ int errsv = errno;
+ CHIAKI_LOGE(regist->log, "Regist connect failed: %s", strerror(errsv));
+ close(sock);
+ sock = -1;
+ free(sa);
+ continue;
+ }
+ free(sa);
+ break;
+ }
+ freeaddrinfo(addrinfos);
+
+ return sock;
+}
\ No newline at end of file
diff --git a/lib/src/rpcrypt.c b/lib/src/rpcrypt.c
index e58747f..31bc8ab 100644
--- a/lib/src/rpcrypt.c
+++ b/lib/src/rpcrypt.c
@@ -23,11 +23,11 @@
#include
#include
+static const uint8_t echo_b[] = { 0xe1, 0xec, 0x9c, 0x3a, 0xdd, 0xbd, 0x08, 0x85, 0xfc, 0x0e, 0x1d, 0x78, 0x90, 0x32, 0xc0, 0x04 };
CHIAKI_EXPORT void chiaki_rpcrypt_bright_ambassador(uint8_t *bright, uint8_t *ambassador, const uint8_t *nonce, const uint8_t *morning)
{
static const uint8_t echo_a[] = { 0x01, 0x49, 0x87, 0x9b, 0x65, 0x39, 0x8b, 0x39, 0x4b, 0x3a, 0x8d, 0x48, 0xc3, 0x0a, 0xef, 0x51 };
- static const uint8_t echo_b[] = { 0xe1, 0xec, 0x9c, 0x3a, 0xdd, 0xbd, 0x08, 0x85, 0xfc, 0x0e, 0x1d, 0x78, 0x90, 0x32, 0xc0, 0x04 };
for(uint8_t i=0; ibright, rpcrypt->ambassador, nonce, morning);
}
+CHIAKI_EXPORT void chiaki_rpcrypt_init_regist(ChiakiRPCrypt *rpcrypt, const uint8_t *nonce, uint32_t pin)
+{
+ static const uint8_t regist_aes_key[CHIAKI_KEY_BYTES] = { 0x3f, 0x1c, 0xc4, 0xb6, 0xdc, 0xbb, 0x3e, 0xcc, 0x50, 0xba, 0xed, 0xef, 0x97, 0x34, 0xc7, 0xc9 };
+ memcpy(rpcrypt->ambassador, nonce, sizeof(rpcrypt->ambassador));
+ memcpy(rpcrypt->bright, regist_aes_key, sizeof(rpcrypt->bright));
+ rpcrypt->bright[0] ^= (uint8_t)((pin >> 0x18) & 0xff);
+ rpcrypt->bright[1] ^= (uint8_t)((pin >> 0x10) & 0xff);
+ rpcrypt->bright[2] ^= (uint8_t)((pin >> 0x08) & 0xff);
+ rpcrypt->bright[3] ^= (uint8_t)((pin >> 0x00) & 0xff);
+}
+
CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_generate_iv(ChiakiRPCrypt *rpcrypt, uint8_t *iv, uint64_t counter)
{
uint8_t hmac_key[] = { 0xac, 0x07, 0x88, 0x83, 0xc8, 0x3a, 0x1f, 0xe8, 0x11, 0x46, 0x3a, 0xf3, 0x9e, 0xe3, 0xe3, 0x77 };
diff --git a/lib/src/session.c b/lib/src/session.c
index c435e7e..8ca880c 100644
--- a/lib/src/session.c
+++ b/lib/src/session.c
@@ -287,7 +287,7 @@ static void *session_thread_func(void *arg)
CHIAKI_LOGI(session->log, "Session request successful");
- chiaki_rpcrypt_init(&session->rpcrypt, session->nonce, session->connect_info.morning);
+ chiaki_rpcrypt_init_auth(&session->rpcrypt, session->nonce, session->connect_info.morning);
// PS4 doesn't always react right away, sleep a bit
chiaki_cond_timedwait_pred(&session->state_cond, &session->state_mutex, 10, session_check_state_pred, session);
@@ -482,7 +482,10 @@ static bool session_thread_request_session(ChiakiSession *session)
session_sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if(session_sock < 0)
+ {
+ free(sa);
continue;
+ }
r = connect(session_sock, sa, ai->ai_addrlen);
if(r < 0)
{
diff --git a/test/rpcrypt.c b/test/rpcrypt.c
index 9acd808..2ffaabb 100644
--- a/test/rpcrypt.c
+++ b/test/rpcrypt.c
@@ -47,7 +47,7 @@ static MunitResult test_iv(const MunitParameter params[], void *user)
ChiakiRPCrypt rpcrypt;
ChiakiErrorCode err;
- chiaki_rpcrypt_init(&rpcrypt, nonce, morning);
+ chiaki_rpcrypt_init_auth(&rpcrypt, nonce, morning);
uint8_t iv[CHIAKI_KEY_BYTES];
@@ -81,7 +81,7 @@ static MunitResult test_encrypt(const MunitParameter params[], void *user)
ChiakiRPCrypt rpcrypt;
ChiakiErrorCode err;
- chiaki_rpcrypt_init(&rpcrypt, nonce, morning);
+ chiaki_rpcrypt_init_auth(&rpcrypt, nonce, morning);
// less than block size
uint8_t buf_a[] = { 0x13, 0x37, 0xc0, 0xff, 0xee };
@@ -123,7 +123,7 @@ static MunitResult test_decrypt(const MunitParameter params[], void *user)
ChiakiRPCrypt rpcrypt;
ChiakiErrorCode err;
- chiaki_rpcrypt_init(&rpcrypt, nonce, morning);
+ chiaki_rpcrypt_init_auth(&rpcrypt, nonce, morning);
// less than block size
uint8_t buf_a[] = { 0x8d, 0xd2, 0x1d, 0xfb };