Add Regist Tests

This commit is contained in:
Florian Märkl 2019-08-15 15:32:59 +02:00
commit 0694af09ad
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
12 changed files with 187 additions and 58 deletions

View file

@ -22,6 +22,7 @@
#include "log.h"
#include "thread.h"
#include "stoppipe.h"
#include "rpcrypt.h"
#ifdef __cplusplus
extern "C" {
@ -62,6 +63,8 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_regist_start(ChiakiRegist *regist, ChiakiLo
CHIAKI_EXPORT void chiaki_regist_fini(ChiakiRegist *regist);
CHIAKI_EXPORT void chiaki_regist_stop(ChiakiRegist *regist);
CHIAKI_EXPORT ChiakiErrorCode chiaki_regist_request_payload_format(uint8_t *buf, size_t *buf_size, ChiakiRPCrypt *crypt, const char *psn_id);
#ifdef __cplusplus
}
#endif

View file

@ -27,19 +27,19 @@
extern "C" {
#endif
#define CHIAKI_KEY_BYTES 0x10
#define CHIAKI_RPCRYPT_KEY_SIZE 0x10
typedef struct chiaki_rpcrypt_t
{
uint8_t bright[CHIAKI_KEY_BYTES];
uint8_t ambassador[CHIAKI_KEY_BYTES];
uint8_t bright[CHIAKI_RPCRYPT_KEY_SIZE];
uint8_t ambassador[CHIAKI_RPCRYPT_KEY_SIZE];
} 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_aeropause(uint8_t *aeropause, const uint8_t *ambassador);
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 void chiaki_rpcrypt_init_regist(ChiakiRPCrypt *rpcrypt, const uint8_t *ambassador, 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);

View file

@ -137,13 +137,13 @@ typedef struct chiaki_session_t
char hostname[128];
char *regist_key;
char *ostype;
char auth[CHIAKI_KEY_BYTES];
uint8_t morning[CHIAKI_KEY_BYTES];
char auth[CHIAKI_RPCRYPT_KEY_SIZE];
uint8_t morning[CHIAKI_RPCRYPT_KEY_SIZE];
uint8_t did[CHIAKI_RP_DID_SIZE];
ChiakiConnectVideoProfile video_profile;
} connect_info;
uint8_t nonce[CHIAKI_KEY_BYTES];
uint8_t nonce[CHIAKI_RPCRYPT_KEY_SIZE];
ChiakiRPCrypt rpcrypt;
char session_id[CHIAKI_SESSION_ID_SIZE_MAX]; // zero-terminated
uint8_t handshake_key[CHIAKI_HANDSHAKE_KEY_SIZE];

View file

@ -341,11 +341,11 @@ static ChiakiErrorCode ctrl_connect(ChiakiCtrl *ctrl)
CHIAKI_LOGI(session->log, "Connected to %s:%d", session->connect_info.hostname, SESSION_CTRL_PORT);
uint8_t auth_enc[CHIAKI_KEY_BYTES];
ChiakiErrorCode err = chiaki_rpcrypt_encrypt(&session->rpcrypt, 0, (uint8_t *)session->connect_info.auth, auth_enc, CHIAKI_KEY_BYTES);
uint8_t auth_enc[CHIAKI_RPCRYPT_KEY_SIZE];
ChiakiErrorCode err = chiaki_rpcrypt_encrypt(&session->rpcrypt, 0, (uint8_t *)session->connect_info.auth, auth_enc, CHIAKI_RPCRYPT_KEY_SIZE);
if(err != CHIAKI_ERR_SUCCESS)
goto error;
char auth_b64[CHIAKI_KEY_BYTES*2];
char auth_b64[CHIAKI_RPCRYPT_KEY_SIZE*2];
err = chiaki_base64_encode(auth_enc, sizeof(auth_enc), auth_b64, sizeof(auth_b64));
if(err != CHIAKI_ERR_SUCCESS)
goto error;

View file

@ -93,14 +93,30 @@ static const char * const request_fmt =
static const char * const request_inner_fmt =
"Client-Type: Windows\r\n"
"Np-Online-Id: %s\r\n\r\n";
"Np-Online-Id: %s\r\n";
CHIAKI_EXPORT ChiakiErrorCode chiaki_regist_request_payload_format(uint8_t *buf, size_t *buf_size, ChiakiRPCrypt *crypt, const char *psn_id)
{
size_t buf_size_val = *buf_size;
static const size_t inner_header_off = 0x1e0;
if(buf_size_val < inner_header_off)
return CHIAKI_ERR_BUF_TOO_SMALL;
memset(buf, 'A', inner_header_off);
chiaki_rpcrypt_aeropause(buf + 0x11c, crypt->ambassador);
int inner_header_size = snprintf((char *)buf + inner_header_off, buf_size_val - inner_header_off, request_inner_fmt, psn_id);
if(inner_header_size < 0 || inner_header_size >= buf_size_val - inner_header_off)
return CHIAKI_ERR_BUF_TOO_SMALL;
ChiakiErrorCode err = chiaki_rpcrypt_encrypt(crypt, 0, buf + inner_header_off, buf + inner_header_off, inner_header_size);
*buf_size = inner_header_off + inner_header_size;
return err;
}
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));
uint8_t ambassador[CHIAKI_RPCRYPT_KEY_SIZE];
ChiakiErrorCode err = chiaki_random_bytes_crypt(ambassador, sizeof(ambassador));
if(err != CHIAKI_ERR_SUCCESS)
{
CHIAKI_LOGE(regist->log, "Regist failed to generate random nonce");
@ -108,20 +124,16 @@ static void *regist_thread_func(void *user)
}
ChiakiRPCrypt crypt;
chiaki_rpcrypt_init_regist(&crypt, nonce, regist->info.pin);
chiaki_rpcrypt_init_regist(&crypt, ambassador, 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)
size_t payload_size = sizeof(payload);
err = chiaki_regist_request_payload_format(payload, &payload_size, &crypt, regist->info.psn_id);
if(err != CHIAKI_ERR_SUCCESS)
{
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);

View file

@ -29,7 +29,7 @@ CHIAKI_EXPORT void chiaki_rpcrypt_bright_ambassador(uint8_t *bright, uint8_t *am
{
static const uint8_t echo_a[] = { 0x01, 0x49, 0x87, 0x9b, 0x65, 0x39, 0x8b, 0x39, 0x4b, 0x3a, 0x8d, 0x48, 0xc3, 0x0a, 0xef, 0x51 };
for(uint8_t i=0; i<CHIAKI_KEY_BYTES; i++)
for(uint8_t i=0; i<CHIAKI_RPCRYPT_KEY_SIZE; i++)
{
uint8_t v = nonce[i];
v -= i;
@ -38,7 +38,7 @@ CHIAKI_EXPORT void chiaki_rpcrypt_bright_ambassador(uint8_t *bright, uint8_t *am
ambassador[i] = v;
}
for(uint8_t i=0; i<CHIAKI_KEY_BYTES; i++)
for(uint8_t i=0; i<CHIAKI_RPCRYPT_KEY_SIZE; i++)
{
uint8_t v = morning[i];
v -= i;
@ -49,11 +49,11 @@ CHIAKI_EXPORT void chiaki_rpcrypt_bright_ambassador(uint8_t *bright, uint8_t *am
}
}
CHIAKI_EXPORT void chiaki_rpcrypt_aeropause(uint8_t *aeropause, const uint8_t *nonce)
CHIAKI_EXPORT void chiaki_rpcrypt_aeropause(uint8_t *aeropause, const uint8_t *ambassador)
{
for(size_t i=0; i<CHIAKI_KEY_BYTES; i++)
for(size_t i=0; i<CHIAKI_RPCRYPT_KEY_SIZE; i++)
{
uint8_t v = nonce[i];
uint8_t v = ambassador[i];
v -= i;
v -= 0x29;
v ^= echo_b[i];
@ -66,10 +66,10 @@ CHIAKI_EXPORT void chiaki_rpcrypt_init_auth(ChiakiRPCrypt *rpcrypt, const uint8_
chiaki_rpcrypt_bright_ambassador(rpcrypt->bright, rpcrypt->ambassador, nonce, morning);
}
CHIAKI_EXPORT void chiaki_rpcrypt_init_regist(ChiakiRPCrypt *rpcrypt, const uint8_t *nonce, uint32_t pin)
CHIAKI_EXPORT void chiaki_rpcrypt_init_regist(ChiakiRPCrypt *rpcrypt, const uint8_t *ambassador, 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));
static const uint8_t regist_aes_key[CHIAKI_RPCRYPT_KEY_SIZE] = { 0x3f, 0x1c, 0xc4, 0xb6, 0xdc, 0xbb, 0x3e, 0xcc, 0x50, 0xba, 0xed, 0xef, 0x97, 0x34, 0xc7, 0xc9 };
memcpy(rpcrypt->ambassador, ambassador, 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);
@ -81,26 +81,26 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_generate_iv(ChiakiRPCrypt *rpcrypt,
{
uint8_t hmac_key[] = { 0xac, 0x07, 0x88, 0x83, 0xc8, 0x3a, 0x1f, 0xe8, 0x11, 0x46, 0x3a, 0xf3, 0x9e, 0xe3, 0xe3, 0x77 };
uint8_t buf[CHIAKI_KEY_BYTES + 8];
memcpy(buf, rpcrypt->ambassador, CHIAKI_KEY_BYTES);
buf[CHIAKI_KEY_BYTES + 0] = (uint8_t)((counter >> 0x38) & 0xff);
buf[CHIAKI_KEY_BYTES + 1] = (uint8_t)((counter >> 0x30) & 0xff);
buf[CHIAKI_KEY_BYTES + 2] = (uint8_t)((counter >> 0x28) & 0xff);
buf[CHIAKI_KEY_BYTES + 3] = (uint8_t)((counter >> 0x20) & 0xff);
buf[CHIAKI_KEY_BYTES + 4] = (uint8_t)((counter >> 0x18) & 0xff);
buf[CHIAKI_KEY_BYTES + 5] = (uint8_t)((counter >> 0x10) & 0xff);
buf[CHIAKI_KEY_BYTES + 6] = (uint8_t)((counter >> 0x08) & 0xff);
buf[CHIAKI_KEY_BYTES + 7] = (uint8_t)((counter >> 0x00) & 0xff);
uint8_t buf[CHIAKI_RPCRYPT_KEY_SIZE + 8];
memcpy(buf, rpcrypt->ambassador, CHIAKI_RPCRYPT_KEY_SIZE);
buf[CHIAKI_RPCRYPT_KEY_SIZE + 0] = (uint8_t)((counter >> 0x38) & 0xff);
buf[CHIAKI_RPCRYPT_KEY_SIZE + 1] = (uint8_t)((counter >> 0x30) & 0xff);
buf[CHIAKI_RPCRYPT_KEY_SIZE + 2] = (uint8_t)((counter >> 0x28) & 0xff);
buf[CHIAKI_RPCRYPT_KEY_SIZE + 3] = (uint8_t)((counter >> 0x20) & 0xff);
buf[CHIAKI_RPCRYPT_KEY_SIZE + 4] = (uint8_t)((counter >> 0x18) & 0xff);
buf[CHIAKI_RPCRYPT_KEY_SIZE + 5] = (uint8_t)((counter >> 0x10) & 0xff);
buf[CHIAKI_RPCRYPT_KEY_SIZE + 6] = (uint8_t)((counter >> 0x08) & 0xff);
buf[CHIAKI_RPCRYPT_KEY_SIZE + 7] = (uint8_t)((counter >> 0x00) & 0xff);
uint8_t hmac[32];
unsigned int hmac_len = 0;
if(!HMAC(EVP_sha256(), hmac_key, CHIAKI_KEY_BYTES, buf, sizeof(buf), hmac, &hmac_len))
if(!HMAC(EVP_sha256(), hmac_key, CHIAKI_RPCRYPT_KEY_SIZE, buf, sizeof(buf), hmac, &hmac_len))
return CHIAKI_ERR_UNKNOWN;
if(hmac_len < CHIAKI_KEY_BYTES)
if(hmac_len < CHIAKI_RPCRYPT_KEY_SIZE)
return CHIAKI_ERR_UNKNOWN;
memcpy(iv, hmac, CHIAKI_KEY_BYTES);
memcpy(iv, hmac, CHIAKI_RPCRYPT_KEY_SIZE);
return CHIAKI_ERR_SUCCESS;
}
@ -110,7 +110,7 @@ static ChiakiErrorCode chiaki_rpcrypt_crypt(ChiakiRPCrypt *rpcrypt, uint64_t cou
if(!ctx)
return CHIAKI_ERR_UNKNOWN;
uint8_t iv[CHIAKI_KEY_BYTES];
uint8_t iv[CHIAKI_RPCRYPT_KEY_SIZE];
ChiakiErrorCode err = chiaki_rpcrypt_generate_iv(rpcrypt, iv, counter);
if(err != CHIAKI_ERR_SUCCESS)
return err;

View file

@ -584,9 +584,9 @@ static bool session_thread_request_session(ChiakiSession *session)
if(response.success)
{
size_t nonce_len = CHIAKI_KEY_BYTES;
size_t nonce_len = CHIAKI_RPCRYPT_KEY_SIZE;
err = chiaki_base64_decode(response.nonce, strlen(response.nonce), session->nonce, &nonce_len);
if(err != CHIAKI_ERR_SUCCESS || nonce_len != CHIAKI_KEY_BYTES)
if(err != CHIAKI_ERR_SUCCESS || nonce_len != CHIAKI_RPCRYPT_KEY_SIZE)
{
CHIAKI_LOGE(session->log, "Nonce invalid");
response.success = false;