Просмотр исходного кода

Refactoring: split out the crypto functions

twisted_pear 2 лет назад
Родитель
Сommit
ed6edbe73a
3 измененных файлов с 140 добавлено и 46 удалено
  1. 73 0
      crypto_wrapper.c
  2. 34 0
      crypto_wrapper.h
  3. 33 46
      esubghz_chat.c

+ 73 - 0
crypto_wrapper.c

@@ -0,0 +1,73 @@
+#include <furi_hal.h>
+
+#include "crypto/gcm.h"
+#include "crypto_wrapper.h"
+
+struct ESugGhzChatCryptoCtx {
+	gcm_context gcm_ctx;
+};
+
+void crypto_init(void)
+{
+	/* init the GCM and AES tables */
+	gcm_initialize();
+}
+
+void crypto_explicit_bzero(void *s, size_t len)
+{
+	memset(s, 0, len);
+	asm volatile("" ::: "memory");
+}
+
+ESubGhzChatCryptoCtx *crypto_ctx_alloc(void)
+{
+	ESubGhzChatCryptoCtx *ret = malloc(sizeof(ESubGhzChatCryptoCtx));
+
+	if (ret != NULL) {
+		memset(ret, 0, sizeof(ESubGhzChatCryptoCtx));
+	}
+
+	return ret;
+}
+
+void crypto_ctx_free(ESubGhzChatCryptoCtx *ctx)
+{
+	crypto_ctx_clear(ctx);
+	free(ctx);
+}
+
+void crypto_ctx_clear(ESubGhzChatCryptoCtx *ctx)
+{
+	crypto_explicit_bzero(ctx, sizeof(ESubGhzChatCryptoCtx));
+}
+
+bool crypto_ctx_set_key(ESubGhzChatCryptoCtx *ctx, const uint8_t *key)
+{
+	return (gcm_setkey(&(ctx->gcm_ctx), key, KEY_BITS / 8) == 0);
+}
+
+bool crypto_ctx_decrypt(ESubGhzChatCryptoCtx *ctx, uint8_t *in, size_t in_len,
+		uint8_t *out)
+{
+	if (in_len < MSG_OVERHEAD + 1) {
+		return false;
+	}
+
+	return (gcm_auth_decrypt(&(ctx->gcm_ctx),
+			in, IV_BYTES,
+			NULL, 0,
+			in + IV_BYTES, out, in_len - MSG_OVERHEAD,
+			in + in_len - TAG_BYTES, TAG_BYTES) == 0);
+
+}
+
+bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx *ctx, uint8_t *in, size_t in_len,
+		uint8_t *out)
+{
+	furi_hal_random_fill_buf(out, IV_BYTES);
+	return (gcm_crypt_and_tag(&(ctx->gcm_ctx), ENCRYPT,
+			out, IV_BYTES,
+			NULL, 0,
+			in, out + IV_BYTES, in_len,
+			out + IV_BYTES + in_len, TAG_BYTES) == 0);
+}

+ 34 - 0
crypto_wrapper.h

@@ -0,0 +1,34 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define KEY_BITS 256
+#define IV_BYTES 12
+#define TAG_BYTES 16
+
+#define MSG_OVERHEAD (IV_BYTES + TAG_BYTES)
+
+typedef struct ESugGhzChatCryptoCtx ESubGhzChatCryptoCtx;
+
+void crypto_init(void);
+
+/* Function to clear sensitive memory. */
+void crypto_explicit_bzero(void *s, size_t len);
+
+ESubGhzChatCryptoCtx *crypto_ctx_alloc(void);
+void crypto_ctx_free(ESubGhzChatCryptoCtx *ctx);
+
+void crypto_ctx_clear(ESubGhzChatCryptoCtx *ctx);
+
+bool crypto_ctx_set_key(ESubGhzChatCryptoCtx *ctx, const uint8_t *key);
+
+bool crypto_ctx_decrypt(ESubGhzChatCryptoCtx *ctx, uint8_t *in, size_t in_len,
+		uint8_t *out);
+bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx *ctx, uint8_t *in, size_t in_len,
+		uint8_t *out);
+
+#ifdef __cplusplus
+}
+#endif

+ 33 - 46
esubghz_chat.c

@@ -14,16 +14,12 @@
 
 #include "esubghz_chat_icons.h"
 
-#include "crypto/gcm.h"
+#include "crypto_wrapper.h"
 
 #define APPLICATION_NAME "ESubGhzChat"
 
 #define DEFAULT_FREQ 433920000
 
-#define KEY_BITS 256
-#define IV_BYTES 12
-#define TAG_BYTES 16
-
 #define RX_TX_BUFFER_SIZE 1024
 
 #define CHAT_BOX_STORE_SIZE 4096
@@ -59,7 +55,7 @@ typedef struct {
 
 	// encryption
 	bool encrypted;
-	gcm_context gcm_ctx;
+	ESubGhzChatCryptoCtx *crypto_ctx;
 
 	// RX and TX buffers
 	uint8_t rx_buffer[RX_TX_BUFFER_SIZE];
@@ -95,13 +91,6 @@ typedef enum {
 	ESubGhzChatEvent_MsgEntered
 } ESubGhzChatEvent;
 
-/* Function to clear sensitive memory. */
-static void esubghz_chat_explicit_bzero(void *s, size_t len)
-{
-	memset(s, 0, len);
-	asm volatile("" ::: "memory");
-}
-
 /* Callback for RX events from the Sub-GHz worker. Records the current ticks as
  * the time of the last reception. */
 static void have_read_cb(void* context)
@@ -115,21 +104,17 @@ static void have_read_cb(void* context)
 /* Decrypts a message for post_rx(). */
 static bool post_rx_decrypt(ESubGhzChatState *state, size_t rx_size)
 {
-	if (rx_size < IV_BYTES + TAG_BYTES + 1) {
-		return false;
+	bool ret = crypto_ctx_decrypt(state->crypto_ctx,
+			state->rx_buffer, rx_size,
+			(uint8_t*) state->rx_str_buffer);
+
+	if (ret) {
+		state->rx_str_buffer[rx_size - (MSG_OVERHEAD)] = 0;
+	} else {
+		state->rx_str_buffer[0] = 0;
 	}
 
-	int ret = gcm_auth_decrypt(&(state->gcm_ctx),
-			state->rx_buffer, IV_BYTES,
-			NULL, 0,
-			state->rx_buffer + IV_BYTES,
-			(uint8_t *) state->rx_str_buffer,
-			rx_size - (IV_BYTES + TAG_BYTES),
-			state->rx_buffer + rx_size - TAG_BYTES,
-			TAG_BYTES);
-	state->rx_str_buffer[rx_size - (IV_BYTES + TAG_BYTES)] = 0;
-
-	return (ret == 0);
+	return ret;
 }
 
 /* Post RX handler, decrypts received messages, displays them in the text box
@@ -182,19 +167,14 @@ static void tx_msg_input(ESubGhzChatState *state)
 	size_t msg_len = strlen(furi_string_get_cstr(state->msg_input));
 	size_t tx_size = msg_len;
 	if (state->encrypted) {
-		tx_size += IV_BYTES + TAG_BYTES;
+		tx_size += MSG_OVERHEAD;
 		furi_check(tx_size <= sizeof(state->tx_buffer));
 
-		furi_hal_random_fill_buf(state->tx_buffer, IV_BYTES);
-		gcm_crypt_and_tag(&(state->gcm_ctx), ENCRYPT,
-				state->tx_buffer, IV_BYTES,
-				NULL, 0,
-				(unsigned char *)
+		crypto_ctx_encrypt(state->crypto_ctx,
+				(uint8_t *)
 				furi_string_get_cstr(state->msg_input),
-				state->tx_buffer + IV_BYTES,
 				msg_len,
-				state->tx_buffer + IV_BYTES + msg_len,
-				TAG_BYTES);
+				state->tx_buffer);
 	} else {
 		tx_size += 2;
 		furi_check(tx_size <= sizeof(state->tx_buffer));
@@ -275,7 +255,7 @@ static void pass_input_cb(void *context)
 			(state->encrypted ? "yes" : "no"));
 
 	/* clear the text input buffer to remove the password */
-	esubghz_chat_explicit_bzero(state->text_input_store,
+	crypto_explicit_bzero(state->text_input_store,
 			sizeof(state->text_input_store));
 
 	subghz_tx_rx_worker_start(state->subghz_worker, state->subghz_device,
@@ -326,15 +306,14 @@ static bool pass_input_validator(const char *text, FuriString *error,
 	/* derive a key from the password */
 	sha256((unsigned char *) text, strlen(text), key);
 
-	/* initiate the AES-GCM context */
-	int ret = gcm_setkey(&(state->gcm_ctx), key, KEY_BITS / 8);
+	/* initiate the crypto context */
+	bool ret = crypto_ctx_set_key(state->crypto_ctx, key);
 
 	/* cleanup */
-	esubghz_chat_explicit_bzero(key, sizeof(key));
+	crypto_explicit_bzero(key, sizeof(key));
 
-	if (ret != 0) {
-		esubghz_chat_explicit_bzero(&(state->gcm_ctx),
-				sizeof(state->gcm_ctx));
+	if (!ret) {
+		crypto_ctx_clear(state->crypto_ctx);
 		furi_string_printf(error, "Failed to\nset key!");
 		return false;
 	}
@@ -964,8 +943,8 @@ static void chat_box_free(ESubGhzChatState *state)
 
 int32_t esubghz_chat(void)
 {
-	/* init the GCM and AES tables */
-	gcm_initialize();
+	/* init the crypto system */
+	crypto_init();
 
 	int32_t err = -1;
 
@@ -1008,6 +987,11 @@ int32_t esubghz_chat(void)
 		goto err_alloc_worker;
 	}
 
+	state->crypto_ctx = crypto_ctx_alloc();
+	if (state->crypto_ctx == NULL) {
+		goto err_alloc_crypto;
+	}
+
 	/* set the have_read callback of the Sub-GHz worker */
 	subghz_tx_rx_worker_set_callback_have_read(state->subghz_worker,
 			have_read_cb, state);
@@ -1089,9 +1073,9 @@ int32_t esubghz_chat(void)
 	furi_record_close(RECORD_NOTIFICATION);
 
 	/* clear the key and potential password */
-	esubghz_chat_explicit_bzero(state->text_input_store,
+	crypto_explicit_bzero(state->text_input_store,
 			sizeof(state->text_input_store));
-	esubghz_chat_explicit_bzero(&(state->gcm_ctx), sizeof(state->gcm_ctx));
+	crypto_ctx_clear(state->crypto_ctx);
 
 	/* deinit devices */
 	subghz_devices_deinit();
@@ -1101,6 +1085,9 @@ int32_t esubghz_chat(void)
 
 	/* free everything we allocated */
 
+	crypto_ctx_free(state->crypto_ctx);
+
+err_alloc_crypto:
 	subghz_tx_rx_worker_free(state->subghz_worker);
 
 err_alloc_worker: