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 };