diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 289fca4..2c8a829 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -14,7 +14,8 @@ set(HEADER_FILES include/chiaki/mirai.h include/chiaki/ecdh.h include/chiaki/launchspec.h - include/chiaki/random.h) + include/chiaki/random.h + include/chiaki/gkcrypt.h) set(SOURCE_FILES src/common.c @@ -33,7 +34,8 @@ set(SOURCE_FILES src/mirai.c src/ecdh.c src/launchspec.c - src/random.c) + src/random.c + src/gkcrypt.c) add_subdirectory(protobuf) include_directories("${NANOPB_SOURCE_DIR}") diff --git a/lib/include/chiaki/gkcrypt.h b/lib/include/chiaki/gkcrypt.h new file mode 100644 index 0000000..ff9ee5b --- /dev/null +++ b/lib/include/chiaki/gkcrypt.h @@ -0,0 +1,50 @@ +/* + * 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_GKCRYPT_H +#define CHIAKI_GKCRYPT_H + +#include "common.h" +#include "log.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define CHIAKI_GKCRYPT_BLOCK_SIZE 0x10 + +typedef struct chiaki_gkcrypt_t { + uint8_t *key_buf; + size_t key_buf_size; + uint8_t key[CHIAKI_GKCRYPT_BLOCK_SIZE]; + uint8_t iv[CHIAKI_GKCRYPT_BLOCK_SIZE]; + ChiakiLog *log; +} ChiakiGKCrypt; + +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); + +#ifdef __cplusplus +} +#endif + +#endif //CHIAKI_GKCRYPT_H diff --git a/lib/src/gkcrypt.c b/lib/src/gkcrypt.c new file mode 100644 index 0000000..eb84a05 --- /dev/null +++ b/lib/src/gkcrypt.c @@ -0,0 +1,76 @@ +/* + * 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 +#include + +#include +#include + +#include +#include + + +static ChiakiErrorCode gkcrypt_gen_key_iv(ChiakiGKCrypt *gkcrypt, uint8_t index, uint8_t *handshake_key, uint8_t *ecdh_secret); + + +CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_init(ChiakiGKCrypt *gkcrypt, ChiakiSession *session, size_t key_buf_blocks, uint8_t index, uint8_t *handshake_key, uint8_t *ecdh_secret) +{ + gkcrypt->log = &session->log; + gkcrypt->key_buf_size = key_buf_blocks * CHIAKI_GKCRYPT_BLOCK_SIZE; + gkcrypt->key_buf = malloc(gkcrypt->key_buf_size); + if(!gkcrypt->key_buf) + return CHIAKI_ERR_MEMORY; + + ChiakiErrorCode err = gkcrypt_gen_key_iv(gkcrypt, index, handshake_key, ecdh_secret); + if(err != CHIAKI_ERR_SUCCESS) + { + CHIAKI_LOGE(gkcrypt->log, "GKCrypt failed to generate key and IV\n"); + return CHIAKI_ERR_UNKNOWN; + } + + return CHIAKI_ERR_SUCCESS; +} + +CHIAKI_EXPORT void chiaki_gkcrypt_fini(ChiakiGKCrypt *gkcrypt) +{ + free(gkcrypt->key_buf); +} + + +static ChiakiErrorCode gkcrypt_gen_key_iv(ChiakiGKCrypt *gkcrypt, uint8_t index, uint8_t *handshake_key, uint8_t *ecdh_secret) +{ + uint8_t data[3 + CHIAKI_HANDSHAKE_KEY_SIZE + 2]; + data[0] = 1; + data[1] = index; + data[2] = 0; + memcpy(data + 3, handshake_key, CHIAKI_HANDSHAKE_KEY_SIZE); + data[3 + CHIAKI_HANDSHAKE_KEY_SIZE + 0] = 1; + data[3 + CHIAKI_HANDSHAKE_KEY_SIZE + 1] = 0; + + uint8_t hmac[CHIAKI_GKCRYPT_BLOCK_SIZE*2]; + size_t hmac_size = sizeof(hmac); + if(!HMAC(EVP_sha256(), handshake_key, CHIAKI_HANDSHAKE_KEY_SIZE, ecdh_secret, CHIAKI_ECDH_SECRET_SIZE, hmac, (unsigned int *)&hmac_size)) + return CHIAKI_ERR_UNKNOWN; + + assert(hmac_size == sizeof(hmac)); + + memcpy(gkcrypt->key, hmac, CHIAKI_GKCRYPT_BLOCK_SIZE); + memcpy(gkcrypt->iv, hmac + CHIAKI_GKCRYPT_BLOCK_SIZE, CHIAKI_GKCRYPT_BLOCK_SIZE); + + return CHIAKI_ERR_SUCCESS; +} diff --git a/lib/src/nagare.c b/lib/src/nagare.c index 94ac8cf..c940275 100644 --- a/lib/src/nagare.c +++ b/lib/src/nagare.c @@ -201,12 +201,18 @@ static void nagare_takion_data_expect_bang(ChiakiNagare *nagare, uint8_t *buf, s CHIAKI_LOGI(nagare->log, "Nagare bang looks good so far\n"); uint8_t secret[CHIAKI_ECDH_SECRET_SIZE]; - chiaki_ecdh_derive_secret(&nagare->session->ecdh, + ChiakiErrorCode err = chiaki_ecdh_derive_secret(&nagare->session->ecdh, secret, ecdh_pub_key_buf.buf, ecdh_pub_key_buf.size, nagare->session->handshake_key, ecdh_sig_buf.buf, ecdh_sig_buf.size); + if(err != CHIAKI_ERR_SUCCESS) + { + CHIAKI_LOGE(nagare->log, "Nagare failed to derive secret from bang\n"); + goto error; + } + error: chiaki_mirai_signal(&nagare->bang_mirai, true); } diff --git a/test/gkcrypt.c b/test/gkcrypt.c index 57751ce..f738029 100644 --- a/test/gkcrypt.c +++ b/test/gkcrypt.c @@ -19,8 +19,6 @@ #include -#include - static MunitResult test_ecdh(const MunitParameter params[], void *user) { static const uint8_t handshake_key[] = { 0xfc, 0x5d, 0x4b, 0xa0, 0x3a, 0x35, 0x3a, 0xbb, 0x6a, 0x7f, 0xac, 0x79, 0x1b, 0x17, 0xbb, 0x34 };