Generate ECDH Key, Send Big

This commit is contained in:
Florian Märkl 2018-11-25 15:24:47 +01:00
commit 0b3ce4725d
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
8 changed files with 112 additions and 6 deletions

View file

@ -20,17 +20,22 @@
#include "common.h" #include "common.h"
#include <stdlib.h>
#include <stdint.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef struct chiaki_ecdh_t typedef struct chiaki_ecdh_t
{ {
struct ec_group_st *group;
struct ec_key_st *key_local;
} ChiakiECDH; } ChiakiECDH;
CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_init(ChiakiECDH *ecdh); CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_init(ChiakiECDH *ecdh);
CHIAKI_EXPORT void chiaki_ecdh_fini(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 #ifdef __cplusplus
} }

View file

@ -38,6 +38,7 @@ typedef struct chiaki_log_t
void chiaki_log(ChiakiLog *log, ChiakiLogLevel level, const char *fmt, ...); 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(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_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) #define CHIAKI_LOGI(log, ...) do { chiaki_log((log), CHIAKI_LOG_INFO, __VA_ARGS__); } while(0)

View file

@ -25,6 +25,7 @@
#include "ctrl.h" #include "ctrl.h"
#include "rpcrypt.h" #include "rpcrypt.h"
#include "takion.h" #include "takion.h"
#include "ecdh.h"
#include <stdint.h> #include <stdint.h>
#include <netdb.h> #include <netdb.h>
@ -101,6 +102,7 @@ typedef struct chiaki_session_t
uint8_t handshake_key[CHIAKI_HANDSHAKE_KEY_SIZE]; uint8_t handshake_key[CHIAKI_HANDSHAKE_KEY_SIZE];
unsigned int mtu; unsigned int mtu;
unsigned int rtt; unsigned int rtt;
ChiakiECDH ecdh;
ChiakiQuitReason quit_reason; ChiakiQuitReason quit_reason;

View file

@ -15,14 +15,55 @@
* along with Chiaki. If not, see <https://www.gnu.org/licenses/>. * along with Chiaki. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <chiaki/session.h>
#include <chiaki/ecdh.h> #include <chiaki/ecdh.h>
#include <chiaki/base64.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/hmac.h>
#include <string.h>
#include <stdio.h>
CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_init(ChiakiECDH *ecdh) 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; return CHIAKI_ERR_SUCCESS;
} }
CHIAKI_EXPORT void chiaki_ecdh_fini(ChiakiECDH *ecdh) 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;
} }

View file

@ -113,3 +113,19 @@ void chiaki_log_hexdump(ChiakiLog *log, ChiakiLogLevel level, const uint8_t *buf
break; 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<buf_size; i++)
{
uint8_t v = buf[i];
str[i*2+0] = hex_char[v >> 4];
str[i*2+1] = hex_char[v & 0xf];
}
str[buf_size*2] = 0;
chiaki_log(log, level, "%s\n", str);
free(str);
}

View file

@ -173,13 +173,15 @@ static ChiakiErrorCode nagare_send_big(ChiakiNagare *nagare)
char b64[LAUNCH_SPEC_JSON_BUF_SIZE * 2]; char b64[LAUNCH_SPEC_JSON_BUF_SIZE * 2];
} launch_spec_buf; } launch_spec_buf;
ssize_t launch_spec_json_size = chiaki_launchspec_format(launch_spec_buf.json, sizeof(launch_spec_buf.json), &launch_spec); 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"); CHIAKI_LOGE(nagare->log, "Nagare failed to format LaunchSpec json\n");
return CHIAKI_ERR_UNKNOWN; return CHIAKI_ERR_UNKNOWN;
} }
launch_spec_json_size += 1; // we also want the trailing 0 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]; uint8_t launch_spec_json_enc[LAUNCH_SPEC_JSON_BUF_SIZE];
memset(launch_spec_json_enc, 0, (size_t)launch_spec_json_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, 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; 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; tkproto_TakionMessage msg;
memset(&msg, 0, sizeof(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.arg = launch_spec_buf.b64;
msg.big_payload.launch_spec.funcs.encode = chiaki_pb_encode_string; 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.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 uint8_t buf[2048];
// TODO: msg.big_payload.ecdh_sig
uint8_t buf[12];
size_t buf_size; size_t buf_size;
pb_ostream_t stream = pb_ostream_from_buffer(buf, sizeof(buf)); pb_ostream_t stream = pb_ostream_from_buffer(buf, sizeof(buf));

View file

@ -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)); 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 #endif // CHIAKI_PB_UTILS_H

View file

@ -177,6 +177,13 @@ static void *session_thread_func(void *arg)
goto quit_ctrl; 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); err = chiaki_nagare_run(session);
if(err != CHIAKI_ERR_SUCCESS) if(err != CHIAKI_ERR_SUCCESS)
{ {