diff --git a/lib/include/chiaki/ecdh.h b/lib/include/chiaki/ecdh.h index 50162ad..af9dc36 100644 --- a/lib/include/chiaki/ecdh.h +++ b/lib/include/chiaki/ecdh.h @@ -20,17 +20,22 @@ #include "common.h" +#include +#include + #ifdef __cplusplus extern "C" { #endif typedef struct chiaki_ecdh_t { - + struct ec_group_st *group; + struct ec_key_st *key_local; } ChiakiECDH; CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_init(ChiakiECDH *ecdh); CHIAKI_EXPORT void chiaki_ecdh_fini(ChiakiECDH *ecdh); +CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_get_local_pub_key(ChiakiECDH *ecdh, uint8_t *key_out, size_t *key_out_size, uint8_t *handshake_key, uint8_t *sig_out, size_t *sig_out_size); #ifdef __cplusplus } diff --git a/lib/include/chiaki/log.h b/lib/include/chiaki/log.h index 666cacf..c224e4d 100644 --- a/lib/include/chiaki/log.h +++ b/lib/include/chiaki/log.h @@ -38,6 +38,7 @@ typedef struct chiaki_log_t void chiaki_log(ChiakiLog *log, ChiakiLogLevel level, const char *fmt, ...); void chiaki_log_hexdump(ChiakiLog *log, ChiakiLogLevel level, const uint8_t *buf, size_t buf_size); +void chiaki_log_hexdump_raw(ChiakiLog *log, ChiakiLogLevel level, const uint8_t *buf, size_t buf_size); #define CHIAKI_LOGD(log, ...) do { chiaki_log((log), CHIAKI_LOG_DEBUG, __VA_ARGS__); } while(0) #define CHIAKI_LOGI(log, ...) do { chiaki_log((log), CHIAKI_LOG_INFO, __VA_ARGS__); } while(0) diff --git a/lib/include/chiaki/session.h b/lib/include/chiaki/session.h index 41dbaca..1a4e7bc 100644 --- a/lib/include/chiaki/session.h +++ b/lib/include/chiaki/session.h @@ -25,6 +25,7 @@ #include "ctrl.h" #include "rpcrypt.h" #include "takion.h" +#include "ecdh.h" #include #include @@ -101,6 +102,7 @@ typedef struct chiaki_session_t uint8_t handshake_key[CHIAKI_HANDSHAKE_KEY_SIZE]; unsigned int mtu; unsigned int rtt; + ChiakiECDH ecdh; ChiakiQuitReason quit_reason; diff --git a/lib/src/ecdh.c b/lib/src/ecdh.c index 0cf366d..9aca9ea 100644 --- a/lib/src/ecdh.c +++ b/lib/src/ecdh.c @@ -15,14 +15,55 @@ * along with Chiaki. If not, see . */ +#include #include +#include + +#include +#include +#include + +#include + +#include + CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_init(ChiakiECDH *ecdh) { + memset(ecdh, 0, sizeof(ChiakiECDH)); + +#define CHECK(a) if(!(a)) { chiaki_ecdh_fini(ecdh); return CHIAKI_ERR_UNKNOWN; } + + CHECK(ecdh->group = EC_GROUP_new_by_curve_name(NID_secp256k1)); + + CHECK(ecdh->key_local = EC_KEY_new()); + CHECK(EC_KEY_set_group(ecdh->key_local, ecdh->group)); + CHECK(EC_KEY_generate_key(ecdh->key_local)); + +#undef CHECK + return CHIAKI_ERR_SUCCESS; } CHIAKI_EXPORT void chiaki_ecdh_fini(ChiakiECDH *ecdh) { + EC_KEY_free(ecdh->key_local); + EC_GROUP_free(ecdh->group); +} + +CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_get_local_pub_key(ChiakiECDH *ecdh, uint8_t *key_out, size_t *key_out_size, uint8_t *handshake_key, uint8_t *sig_out, size_t *sig_out_size) +{ + const EC_POINT *point = EC_KEY_get0_public_key(ecdh->key_local); + if(!point) + return CHIAKI_ERR_UNKNOWN; + + *key_out_size = EC_POINT_point2oct(ecdh->group, point, POINT_CONVERSION_UNCOMPRESSED, key_out, *key_out_size, NULL); + if(!(*key_out_size)) + return CHIAKI_ERR_UNKNOWN; + + if(!HMAC(EVP_sha256(), handshake_key, CHIAKI_HANDSHAKE_KEY_SIZE, key_out, *key_out_size, sig_out, (unsigned int *)sig_out_size)) + return CHIAKI_ERR_UNKNOWN; + + return CHIAKI_ERR_SUCCESS; } \ No newline at end of file diff --git a/lib/src/log.c b/lib/src/log.c index a62b1ca..572cdc6 100644 --- a/lib/src/log.c +++ b/lib/src/log.c @@ -112,4 +112,20 @@ void chiaki_log_hexdump(ChiakiLog *log, ChiakiLogLevel level, const uint8_t *buf else break; } +} + +void chiaki_log_hexdump_raw(ChiakiLog *log, ChiakiLogLevel level, const uint8_t *buf, size_t buf_size) +{ + char *str = malloc(buf_size * 2 + 1); + if(!str) + return; + for(size_t i=0; i> 4]; + str[i*2+1] = hex_char[v & 0xf]; + } + str[buf_size*2] = 0; + chiaki_log(log, level, "%s\n", str); + free(str); } \ No newline at end of file diff --git a/lib/src/nagare.c b/lib/src/nagare.c index 22b652f..159df20 100644 --- a/lib/src/nagare.c +++ b/lib/src/nagare.c @@ -173,13 +173,15 @@ static ChiakiErrorCode nagare_send_big(ChiakiNagare *nagare) char b64[LAUNCH_SPEC_JSON_BUF_SIZE * 2]; } launch_spec_buf; ssize_t launch_spec_json_size = chiaki_launchspec_format(launch_spec_buf.json, sizeof(launch_spec_buf.json), &launch_spec); - if(launch_spec_json_size != CHIAKI_ERR_SUCCESS) + if(launch_spec_json_size < 0) { CHIAKI_LOGE(nagare->log, "Nagare failed to format LaunchSpec json\n"); return CHIAKI_ERR_UNKNOWN; } launch_spec_json_size += 1; // we also want the trailing 0 + CHIAKI_LOGD(nagare->log, "LaunchSpec: %s\n", launch_spec_buf.json); + uint8_t launch_spec_json_enc[LAUNCH_SPEC_JSON_BUF_SIZE]; memset(launch_spec_json_enc, 0, (size_t)launch_spec_json_size); ChiakiErrorCode err = chiaki_rpcrypt_encrypt(&session->rpcrypt, 0, launch_spec_json_enc, launch_spec_json_enc, @@ -198,6 +200,20 @@ static ChiakiErrorCode nagare_send_big(ChiakiNagare *nagare) return err; } + char ecdh_pub_key[128]; + ChiakiPBBuf ecdh_pub_key_buf = { sizeof(ecdh_pub_key), ecdh_pub_key }; + char ecdh_sig[32]; + ChiakiPBBuf ecdh_sig_buf = { sizeof(ecdh_sig), ecdh_sig }; + err = chiaki_ecdh_get_local_pub_key(&session->ecdh, + ecdh_pub_key, &ecdh_pub_key_buf.size, + session->handshake_key, + ecdh_sig, &ecdh_sig_buf.size); + if(err != CHIAKI_ERR_SUCCESS) + { + CHIAKI_LOGE(nagare->log, "Nagare failed to get ECDH key and sig\n"); + return err; + } + tkproto_TakionMessage msg; memset(&msg, 0, sizeof(msg)); @@ -209,11 +225,12 @@ static ChiakiErrorCode nagare_send_big(ChiakiNagare *nagare) msg.big_payload.launch_spec.arg = launch_spec_buf.b64; msg.big_payload.launch_spec.funcs.encode = chiaki_pb_encode_string; msg.big_payload.encrypted_key.funcs.encode = chiaki_pb_encode_zero_encrypted_key; + msg.big_payload.ecdh_pub_key.arg = &ecdh_pub_key_buf; + msg.big_payload.ecdh_pub_key.funcs.encode = chiaki_pb_encode_buf; + msg.big_payload.ecdh_sig.arg = &ecdh_sig_buf; + msg.big_payload.ecdh_sig.funcs.encode = chiaki_pb_encode_buf; - // TODO: msg.big_payload.ecdh_pub_key - // TODO: msg.big_payload.ecdh_sig - - uint8_t buf[12]; + uint8_t buf[2048]; size_t buf_size; pb_ostream_t stream = pb_ostream_from_buffer(buf, sizeof(buf)); diff --git a/lib/src/pb_utils.h b/lib/src/pb_utils.h index 12381aa..c2aa4a9 100644 --- a/lib/src/pb_utils.h +++ b/lib/src/pb_utils.h @@ -30,4 +30,21 @@ static bool chiaki_pb_encode_string(pb_ostream_t *stream, const pb_field_t *fiel return pb_encode_string(stream, (uint8_t*)str, strlen(str)); } +typedef struct chiaki_pb_buf_t +{ + size_t size; + uint8_t *buf; +} ChiakiPBBuf; + +static bool chiaki_pb_encode_buf(pb_ostream_t *stream, const pb_field_t *field, void *const *arg) +{ + ChiakiPBBuf *buf = *arg; + + if (!pb_encode_tag_for_field(stream, field)) + return false; + + return pb_encode_string(stream, buf->buf, buf->size); +} + + #endif // CHIAKI_PB_UTILS_H diff --git a/lib/src/session.c b/lib/src/session.c index d3bf85e..ce8c456 100644 --- a/lib/src/session.c +++ b/lib/src/session.c @@ -177,6 +177,13 @@ static void *session_thread_func(void *arg) goto quit_ctrl; } + err = chiaki_ecdh_init(&session->ecdh); + if(err != CHIAKI_ERR_SUCCESS) + { + CHIAKI_LOGE(&session->log, "Session failed to initialize ECDH\n"); + goto quit_ctrl; + } + err = chiaki_nagare_run(session); if(err != CHIAKI_ERR_SUCCESS) {