diff --git a/lib/include/chiaki/gkcrypt.h b/lib/include/chiaki/gkcrypt.h index ff9ee5b..43ff4c8 100644 --- a/lib/include/chiaki/gkcrypt.h +++ b/lib/include/chiaki/gkcrypt.h @@ -42,6 +42,8 @@ struct chiaki_session_t; CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_init(ChiakiGKCrypt *gkcrypt, struct chiaki_session_t *session, size_t key_buf_blocks, uint8_t index, uint8_t *handshake_key, uint8_t *ecdh_secret); CHIAKI_EXPORT void chiaki_gkcrypt_fini(ChiakiGKCrypt *gkcrypt); +CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_decrypt(ChiakiGKCrypt *gkcrypt, size_t key_pos, uint8_t *buf, size_t buf_size); +static inline ChiakiErrorCode chiaki_gkcrypt_encrypt(ChiakiGKCrypt *gkcrypt, size_t key_pos, uint8_t *buf, size_t buf_size) { return chiaki_gkcrypt_decrypt(gkcrypt, key_pos, buf, buf_size); } #ifdef __cplusplus } diff --git a/lib/include/chiaki/nagare.h b/lib/include/chiaki/nagare.h index c056fb1..86af8bd 100644 --- a/lib/include/chiaki/nagare.h +++ b/lib/include/chiaki/nagare.h @@ -21,6 +21,7 @@ #include "mirai.h" #include "takion.h" #include "log.h" +#include "ecdh.h" #include @@ -34,6 +35,7 @@ typedef struct chiaki_nagare_t ChiakiLog *log; ChiakiTakion takion; ChiakiMirai bang_mirai; + uint8_t ecdh_secret[CHIAKI_ECDH_SECRET_SIZE]; } ChiakiNagare; CHIAKI_EXPORT ChiakiErrorCode chiaki_nagare_run(struct chiaki_session_t *session); diff --git a/lib/src/gkcrypt.c b/lib/src/gkcrypt.c index eb84a05..25ce53e 100644 --- a/lib/src/gkcrypt.c +++ b/lib/src/gkcrypt.c @@ -24,6 +24,8 @@ #include #include +#include "utils.h" + static ChiakiErrorCode gkcrypt_gen_key_iv(ChiakiGKCrypt *gkcrypt, uint8_t index, uint8_t *handshake_key, uint8_t *ecdh_secret); @@ -74,3 +76,73 @@ static ChiakiErrorCode gkcrypt_gen_key_iv(ChiakiGKCrypt *gkcrypt, uint8_t index, return CHIAKI_ERR_SUCCESS; } + +static inline void counter_add(uint8_t *out, const uint8_t *base, int v) +{ + size_t i=CHIAKI_GKCRYPT_BLOCK_SIZE; + do + { + i--; + int r = (int)base[i] + v; + out[i] = (uint8_t)(r & 0xff); + v = r >> 8; + } while(i>0 && v); +} + +static ChiakiErrorCode gkcrypt_gen_key_stream(ChiakiGKCrypt *gkcrypt, size_t key_pos, uint8_t *buf, size_t buf_size) +{ + assert(key_pos % CHIAKI_GKCRYPT_BLOCK_SIZE == 0); + assert(buf_size % CHIAKI_GKCRYPT_BLOCK_SIZE == 0); + + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + if(!ctx) + return CHIAKI_ERR_UNKNOWN; + + if(!EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, gkcrypt->key, NULL)) + { + EVP_CIPHER_CTX_free(ctx); + return CHIAKI_ERR_UNKNOWN; + } + + if(!EVP_CIPHER_CTX_set_padding(ctx, 0)) + { + EVP_CIPHER_CTX_free(ctx); + return CHIAKI_ERR_UNKNOWN; + } + + for(uint8_t *cur = buf, *end = buf + buf_size; cur < end; cur += CHIAKI_GKCRYPT_BLOCK_SIZE) + counter_add(cur, gkcrypt->iv, (int)key_pos++); + + int outl; + EVP_EncryptUpdate(ctx, buf, &outl, buf, (int)buf_size); + if(outl != buf_size) + { + EVP_CIPHER_CTX_free(ctx); + return CHIAKI_ERR_UNKNOWN; + } + + EVP_CIPHER_CTX_free(ctx); + return CHIAKI_ERR_SUCCESS; +} + +CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_decrypt(ChiakiGKCrypt *gkcrypt, size_t key_pos, uint8_t *buf, size_t buf_size) +{ + size_t padding_pre = key_pos % CHIAKI_GKCRYPT_BLOCK_SIZE; + size_t full_size = ((padding_pre + buf_size + CHIAKI_GKCRYPT_BLOCK_SIZE - 1) / CHIAKI_GKCRYPT_BLOCK_SIZE) * CHIAKI_GKCRYPT_BLOCK_SIZE; + + uint8_t *key_stream = malloc(full_size); + if(!key_stream) + return CHIAKI_ERR_MEMORY; + + ChiakiErrorCode err = gkcrypt_gen_key_stream(gkcrypt, key_pos - padding_pre, key_stream, full_size); + if(err != CHIAKI_ERR_SUCCESS) + { + free(key_stream); + return err; + } + + xor_bytes(buf, key_stream + padding_pre, buf_size); + free(key_stream); + + return CHIAKI_ERR_SUCCESS; +} \ No newline at end of file diff --git a/lib/src/nagare.c b/lib/src/nagare.c index c940275..6d89ea3 100644 --- a/lib/src/nagare.c +++ b/lib/src/nagare.c @@ -41,7 +41,8 @@ static void nagare_takion_data(uint8_t *buf, size_t buf_size, void *user); static ChiakiErrorCode nagare_send_big(ChiakiNagare *nagare); static ChiakiErrorCode nagare_send_disconnect(ChiakiNagare *nagare); -static void nagare_handle_bang(ChiakiNagare *nagare, tkproto_BangPayload *payload); +static void nagare_takion_data_expect_bang(ChiakiNagare *nagare, uint8_t *buf, size_t buf_size); + CHIAKI_EXPORT ChiakiErrorCode chiaki_nagare_run(ChiakiSession *session) { @@ -104,6 +105,9 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_nagare_run(ChiakiSession *session) CHIAKI_LOGI(&session->log, "Nagare successfully received bang\n"); + + + CHIAKI_LOGI(&session->log, "Nagare is disconnecting\n"); nagare_send_disconnect(nagare); @@ -121,8 +125,6 @@ error_bang_mirai: -static void nagare_takion_data_expect_bang(ChiakiNagare *nagare, uint8_t *buf, size_t buf_size); - static void nagare_takion_data(uint8_t *buf, size_t buf_size, void *user) { ChiakiNagare *nagare = user; @@ -198,11 +200,8 @@ static void nagare_takion_data_expect_bang(ChiakiNagare *nagare, uint8_t *buf, s goto error; } - CHIAKI_LOGI(nagare->log, "Nagare bang looks good so far\n"); - - uint8_t secret[CHIAKI_ECDH_SECRET_SIZE]; ChiakiErrorCode err = chiaki_ecdh_derive_secret(&nagare->session->ecdh, - secret, + nagare->ecdh_secret, ecdh_pub_key_buf.buf, ecdh_pub_key_buf.size, nagare->session->handshake_key, ecdh_sig_buf.buf, ecdh_sig_buf.size); @@ -213,8 +212,10 @@ static void nagare_takion_data_expect_bang(ChiakiNagare *nagare, uint8_t *buf, s goto error; } -error: chiaki_mirai_signal(&nagare->bang_mirai, true); + return; +error: + chiaki_mirai_signal(&nagare->bang_mirai, false); }