MX пре 2 година
родитељ
комит
cf78fb6dd5
5 измењених фајлова са 156 додато и 4 уклоњено
  1. 39 1
      crypto_wrapper.c
  2. 10 0
      crypto_wrapper.h
  3. 18 0
      nfc_helpers.h
  4. 46 1
      scenes/esubghz_chat_key_read_popup.c
  5. 43 2
      scenes/esubghz_chat_key_share_popup.c

+ 39 - 1
crypto_wrapper.c

@@ -182,10 +182,48 @@ bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx *ctx, uint8_t *in, size_t in_len,
 			msg->tag, TAG_BYTES) == 0);
 #endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
 
-	// increase internal counter
+	// update replay dict and increase internal counter
 	if (ret) {
+		ESubGhzChatReplayDict_set_at(ctx->replay_dict, ctx->run_id,
+				ctx->counter);
 		ctx->counter++;
 	}
 
 	return ret;
 }
+
+size_t crypto_ctx_dump_replay_dict(ESubGhzChatCryptoCtx *ctx,
+		CryptoCtxReplayDictWriter writer, void *writer_ctx)
+{
+	size_t ret = 0;
+	ESubGhzChatReplayDict_it_t i;
+
+	for (ESubGhzChatReplayDict_it(i, ctx->replay_dict);
+			!ESubGhzChatReplayDict_end_p(i);
+			ESubGhzChatReplayDict_next(i), ret++) {
+		ESubGhzChatReplayDict_itref_t *ref =
+			ESubGhzChatReplayDict_ref(i);
+		if (!writer(ref->key, ref->value, writer_ctx)) {
+			break;
+		}
+	}
+
+	return ret;
+}
+
+size_t crypto_ctx_read_replay_dict(ESubGhzChatCryptoCtx *ctx,
+		CryptoCtxReplayDictReader reader, void *reader_ctx)
+{
+	size_t ret = 0;
+
+	uint64_t run_id;
+	uint32_t counter;
+
+	while (reader(&run_id, &counter, reader_ctx)) {
+		ESubGhzChatReplayDict_set_at(ctx->replay_dict, run_id,
+				counter);
+		ret++;
+	}
+
+	return ret;
+}

+ 10 - 0
crypto_wrapper.h

@@ -33,6 +33,16 @@ bool crypto_ctx_decrypt(ESubGhzChatCryptoCtx *ctx, uint8_t *in, size_t in_len,
 bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx *ctx, uint8_t *in, size_t in_len,
 		uint8_t *out);
 
+typedef bool (*CryptoCtxReplayDictWriter)(uint64_t run_id, uint32_t counter,
+		void *context);
+typedef bool (*CryptoCtxReplayDictReader)(uint64_t *run_id, uint32_t *counter,
+		void *context);
+
+size_t crypto_ctx_dump_replay_dict(ESubGhzChatCryptoCtx *ctx,
+		CryptoCtxReplayDictWriter writer, void *writer_ctx);
+size_t crypto_ctx_read_replay_dict(ESubGhzChatCryptoCtx *ctx,
+		CryptoCtxReplayDictReader reader, void *reader_ctx);
+
 #ifdef __cplusplus
 }
 #endif

+ 18 - 0
nfc_helpers.h

@@ -0,0 +1,18 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NFC_MAX_BYTES 256
+#define NFC_CONFIG_PAGES 4
+
+struct ReplayDictNfcEntry {
+	uint64_t run_id;
+	uint32_t counter;
+	uint32_t unused;
+} __attribute__ ((packed));
+
+#ifdef __cplusplus
+}
+#endif

+ 46 - 1
scenes/esubghz_chat_key_read_popup.c

@@ -1,4 +1,5 @@
 #include "../esubghz_chat_i.h"
+#include "../nfc_helpers.h"
 
 typedef enum {
 	KeyReadPopupState_Idle,
@@ -38,11 +39,45 @@ static void key_read_popup_timeout_cb(void* context)
 	}
 }
 
+struct ReplayDictNfcReaderContext {
+	uint8_t *cur;
+	uint8_t *max;
+};
+
+static bool replay_dict_nfc_reader(uint64_t *run_id, uint32_t *counter, void
+		*context)
+{
+	struct ReplayDictNfcReaderContext *ctx = (struct
+			ReplayDictNfcReaderContext *) context;
+
+	if (ctx->cur + sizeof(struct ReplayDictNfcEntry) > ctx->max) {
+		return false;
+	}
+
+	struct ReplayDictNfcEntry *entry = (struct ReplayDictNfcEntry *)
+		ctx->cur;
+	*run_id = entry->run_id;
+	*counter = __ntohl(entry->counter);
+
+	ctx->cur += sizeof(struct ReplayDictNfcEntry);
+
+	return true;
+}
+
 static bool key_read_popup_handle_key_read(ESubGhzChatState *state)
 {
 	NfcDeviceData *dev_data = state->nfc_dev_data;
 
-	if (dev_data->mf_ul_data.data_read < KEY_BITS / 8) {
+	/* check for config pages */
+	if (dev_data->mf_ul_data.data_read < NFC_CONFIG_PAGES * 4) {
+		return false;
+	}
+
+	size_t data_read = dev_data->mf_ul_data.data_read - (NFC_CONFIG_PAGES *
+			4);
+
+	/* check if key was transmitted */
+	if (data_read < KEY_BITS / 8) {
 		return false;
 	}
 
@@ -59,6 +94,16 @@ static bool key_read_popup_handle_key_read(ESubGhzChatState *state)
 		return false;
 	}
 
+	/* read the replay dict */
+	struct ReplayDictNfcReaderContext rd_ctx = {
+		.cur = dev_data->mf_ul_data.data + (KEY_BITS / 8),
+		.max = dev_data->mf_ul_data.data + (data_read < NFC_MAX_BYTES ?
+				data_read : NFC_MAX_BYTES)
+	};
+
+	crypto_ctx_read_replay_dict(state->crypto_ctx, replay_dict_nfc_reader,
+			&rd_ctx);
+
 	/* set encrypted flag */
 	state->encrypted = true;
 

+ 43 - 2
scenes/esubghz_chat_key_share_popup.c

@@ -1,4 +1,32 @@
 #include "../esubghz_chat_i.h"
+#include "../nfc_helpers.h"
+
+struct ReplayDictNfcWriterContext {
+	uint8_t *cur;
+	uint8_t *max;
+};
+
+static bool replay_dict_nfc_writer(uint64_t run_id, uint32_t counter, void
+		*context)
+{
+	struct ReplayDictNfcWriterContext *ctx = (struct
+			ReplayDictNfcWriterContext *) context;
+
+	struct ReplayDictNfcEntry entry = {
+		.run_id = run_id,
+		.counter = __htonl(counter),
+		.unused = 0
+	};
+
+	if (ctx->cur + sizeof(entry) > ctx->max) {
+		return false;
+	}
+
+	memcpy(ctx->cur, &entry, sizeof(entry));
+	ctx->cur += sizeof(entry);
+
+	return true;
+}
 
 static void prepare_nfc_dev_data(ESubGhzChatState *state)
 {
@@ -21,9 +49,22 @@ static void prepare_nfc_dev_data(ESubGhzChatState *state)
 	dev_data->mf_ul_data.version.storage_size = 0x11;
 	dev_data->mf_ul_data.version.protocol_type = 0x03;
 
-	/* Add 16 to the size for config pages */
-	dev_data->mf_ul_data.data_size = (KEY_BITS / 8) + 16;
+	/* write key */
 	crypto_ctx_get_key(state->crypto_ctx, dev_data->mf_ul_data.data);
+
+	/* write the replay dict */
+	struct ReplayDictNfcWriterContext wr_ctx = {
+		.cur = dev_data->mf_ul_data.data + (KEY_BITS / 8),
+		.max = dev_data->mf_ul_data.data + NFC_MAX_BYTES
+	};
+
+	size_t n_entries = crypto_ctx_dump_replay_dict(state->crypto_ctx,
+			replay_dict_nfc_writer, &wr_ctx);
+
+	/* calculate size of data, add 16 for config pages */
+	dev_data->mf_ul_data.data_size = (KEY_BITS / 8) + (n_entries *
+			sizeof(struct ReplayDictNfcEntry)) + (NFC_CONFIG_PAGES
+			* 4);
 }
 
 /* Prepares the key share popup scene. */