|
@@ -1,6 +1,6 @@
|
|
|
#include <furi_hal.h>
|
|
#include <furi_hal.h>
|
|
|
#include <lib/mlib/m-dict.h>
|
|
#include <lib/mlib/m-dict.h>
|
|
|
-#include <toolbox/sha256.h>
|
|
|
|
|
|
|
+#include <mbedtls/sha256.h>
|
|
|
|
|
|
|
|
#ifndef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
|
#ifndef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
|
|
#include "crypto/gcm.h"
|
|
#include "crypto/gcm.h"
|
|
@@ -11,219 +11,227 @@
|
|
|
DICT_DEF2(ESubGhzChatReplayDict, uint64_t, uint32_t)
|
|
DICT_DEF2(ESubGhzChatReplayDict, uint64_t, uint32_t)
|
|
|
|
|
|
|
|
struct ESugGhzChatCryptoCtx {
|
|
struct ESugGhzChatCryptoCtx {
|
|
|
- uint8_t key[KEY_BITS / 8];
|
|
|
|
|
|
|
+ uint8_t key[KEY_BITS / 8];
|
|
|
#ifndef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
|
#ifndef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
|
|
- gcm_context gcm_ctx;
|
|
|
|
|
|
|
+ gcm_context gcm_ctx;
|
|
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
|
- ESubGhzChatReplayDict_t replay_dict;
|
|
|
|
|
- uint64_t run_id;
|
|
|
|
|
- uint32_t counter;
|
|
|
|
|
|
|
+ ESubGhzChatReplayDict_t replay_dict;
|
|
|
|
|
+ uint64_t run_id;
|
|
|
|
|
+ uint32_t counter;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
struct ESubGhzChatCryptoMsg {
|
|
struct ESubGhzChatCryptoMsg {
|
|
|
- uint64_t run_id;
|
|
|
|
|
- uint32_t counter;
|
|
|
|
|
- uint8_t iv[IV_BYTES];
|
|
|
|
|
- uint8_t tag[TAG_BYTES];
|
|
|
|
|
- uint8_t data[0];
|
|
|
|
|
-} __attribute__ ((packed));
|
|
|
|
|
-
|
|
|
|
|
-void crypto_init(void)
|
|
|
|
|
-{
|
|
|
|
|
|
|
+ uint64_t run_id;
|
|
|
|
|
+ uint32_t counter;
|
|
|
|
|
+ uint8_t iv[IV_BYTES];
|
|
|
|
|
+ uint8_t tag[TAG_BYTES];
|
|
|
|
|
+ uint8_t data[0];
|
|
|
|
|
+} __attribute__((packed));
|
|
|
|
|
+
|
|
|
|
|
+void crypto_init(void) {
|
|
|
#ifndef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
|
#ifndef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
|
|
- /* init the GCM and AES tables */
|
|
|
|
|
- gcm_initialize();
|
|
|
|
|
|
|
+ /* init the GCM and AES tables */
|
|
|
|
|
+ gcm_initialize();
|
|
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void crypto_explicit_bzero(void *s, size_t len)
|
|
|
|
|
-{
|
|
|
|
|
- memset(s, 0, len);
|
|
|
|
|
- asm volatile("" ::: "memory");
|
|
|
|
|
|
|
+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));
|
|
|
|
|
|
|
+ESubGhzChatCryptoCtx* crypto_ctx_alloc(void) {
|
|
|
|
|
+ ESubGhzChatCryptoCtx* ret = malloc(sizeof(ESubGhzChatCryptoCtx));
|
|
|
|
|
|
|
|
- if (ret != NULL) {
|
|
|
|
|
- memset(ret, 0, sizeof(ESubGhzChatCryptoCtx));
|
|
|
|
|
- ESubGhzChatReplayDict_init(ret->replay_dict);
|
|
|
|
|
- ret->run_id = 0;
|
|
|
|
|
- ret->counter = 1;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if(ret != NULL) {
|
|
|
|
|
+ memset(ret, 0, sizeof(ESubGhzChatCryptoCtx));
|
|
|
|
|
+ ESubGhzChatReplayDict_init(ret->replay_dict);
|
|
|
|
|
+ ret->run_id = 0;
|
|
|
|
|
+ ret->counter = 1;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- return ret;
|
|
|
|
|
|
|
+ return ret;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void crypto_ctx_free(ESubGhzChatCryptoCtx *ctx)
|
|
|
|
|
-{
|
|
|
|
|
- crypto_ctx_clear(ctx);
|
|
|
|
|
- ESubGhzChatReplayDict_clear(ctx->replay_dict);
|
|
|
|
|
- free(ctx);
|
|
|
|
|
|
|
+void crypto_ctx_free(ESubGhzChatCryptoCtx* ctx) {
|
|
|
|
|
+ crypto_ctx_clear(ctx);
|
|
|
|
|
+ ESubGhzChatReplayDict_clear(ctx->replay_dict);
|
|
|
|
|
+ free(ctx);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void crypto_ctx_clear(ESubGhzChatCryptoCtx *ctx)
|
|
|
|
|
-{
|
|
|
|
|
- crypto_explicit_bzero(ctx->key, sizeof(ctx->key));
|
|
|
|
|
|
|
+void crypto_ctx_clear(ESubGhzChatCryptoCtx* ctx) {
|
|
|
|
|
+ crypto_explicit_bzero(ctx->key, sizeof(ctx->key));
|
|
|
#ifndef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
|
#ifndef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
|
|
- crypto_explicit_bzero(&(ctx->gcm_ctx), sizeof(ctx->gcm_ctx));
|
|
|
|
|
|
|
+ crypto_explicit_bzero(&(ctx->gcm_ctx), sizeof(ctx->gcm_ctx));
|
|
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
|
- ESubGhzChatReplayDict_reset(ctx->replay_dict);
|
|
|
|
|
- ctx->run_id = 0;
|
|
|
|
|
- ctx->counter = 1;
|
|
|
|
|
|
|
+ ESubGhzChatReplayDict_reset(ctx->replay_dict);
|
|
|
|
|
+ ctx->run_id = 0;
|
|
|
|
|
+ ctx->counter = 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static uint64_t crypto_calc_run_id(FuriString *flipper_name, uint32_t tick)
|
|
|
|
|
-{
|
|
|
|
|
- const char *fn = furi_string_get_cstr(flipper_name);
|
|
|
|
|
- size_t fn_len = strlen(fn);
|
|
|
|
|
|
|
+static uint64_t crypto_calc_run_id(FuriString* flipper_name, uint32_t tick) {
|
|
|
|
|
+ const char* fn = furi_string_get_cstr(flipper_name);
|
|
|
|
|
+ size_t fn_len = strlen(fn);
|
|
|
|
|
|
|
|
- uint8_t h_in[fn_len + sizeof(uint32_t)];
|
|
|
|
|
- memcpy(h_in, fn, fn_len);
|
|
|
|
|
- memcpy(h_in + fn_len, &tick, sizeof(uint32_t));
|
|
|
|
|
|
|
+ uint8_t h_in[fn_len + sizeof(uint32_t)];
|
|
|
|
|
+ memcpy(h_in, fn, fn_len);
|
|
|
|
|
+ memcpy(h_in + fn_len, &tick, sizeof(uint32_t));
|
|
|
|
|
|
|
|
- uint8_t h_out[256];
|
|
|
|
|
- sha256(h_in, fn_len + sizeof(uint32_t), h_out);
|
|
|
|
|
|
|
+ uint8_t h_out[256];
|
|
|
|
|
+ mbedtls_sha256(h_in, fn_len + sizeof(uint32_t), h_out, 0);
|
|
|
|
|
|
|
|
- uint64_t run_id;
|
|
|
|
|
- memcpy(&run_id, h_out, sizeof(uint64_t));
|
|
|
|
|
|
|
+ uint64_t run_id;
|
|
|
|
|
+ memcpy(&run_id, h_out, sizeof(uint64_t));
|
|
|
|
|
|
|
|
- return run_id;
|
|
|
|
|
|
|
+ return run_id;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-bool crypto_ctx_set_key(ESubGhzChatCryptoCtx *ctx, const uint8_t *key,
|
|
|
|
|
- FuriString *flipper_name, uint32_t tick)
|
|
|
|
|
-{
|
|
|
|
|
- ctx->run_id = crypto_calc_run_id(flipper_name, tick);
|
|
|
|
|
- ctx->counter = 1;
|
|
|
|
|
|
|
+bool crypto_ctx_set_key(
|
|
|
|
|
+ ESubGhzChatCryptoCtx* ctx,
|
|
|
|
|
+ const uint8_t* key,
|
|
|
|
|
+ FuriString* flipper_name,
|
|
|
|
|
+ uint32_t tick) {
|
|
|
|
|
+ ctx->run_id = crypto_calc_run_id(flipper_name, tick);
|
|
|
|
|
+ ctx->counter = 1;
|
|
|
|
|
|
|
|
- memcpy(ctx->key, key, KEY_BITS / 8);
|
|
|
|
|
|
|
+ memcpy(ctx->key, key, KEY_BITS / 8);
|
|
|
#ifdef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
|
#ifdef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
|
|
- return true;
|
|
|
|
|
|
|
+ return true;
|
|
|
#else /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
#else /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
|
- return (gcm_setkey(&(ctx->gcm_ctx), key, KEY_BITS / 8) == 0);
|
|
|
|
|
|
|
+ return (gcm_setkey(&(ctx->gcm_ctx), key, KEY_BITS / 8) == 0);
|
|
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void crypto_ctx_get_key(ESubGhzChatCryptoCtx *ctx, uint8_t *key)
|
|
|
|
|
-{
|
|
|
|
|
- memcpy(key, ctx->key, KEY_BITS / 8);
|
|
|
|
|
|
|
+void crypto_ctx_get_key(ESubGhzChatCryptoCtx* ctx, uint8_t* key) {
|
|
|
|
|
+ memcpy(key, ctx->key, KEY_BITS / 8);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-bool crypto_ctx_decrypt(ESubGhzChatCryptoCtx *ctx, uint8_t *in, size_t in_len,
|
|
|
|
|
- uint8_t *out)
|
|
|
|
|
-{
|
|
|
|
|
- if (in_len < MSG_OVERHEAD + 1) {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- struct ESubGhzChatCryptoMsg *msg = (struct ESubGhzChatCryptoMsg *) in;
|
|
|
|
|
-
|
|
|
|
|
- // check if message is stale, if yes, discard
|
|
|
|
|
- uint32_t *counter = ESubGhzChatReplayDict_get(ctx->replay_dict,
|
|
|
|
|
- msg->run_id);
|
|
|
|
|
- if (counter != NULL) {
|
|
|
|
|
- if (*counter >= __ntohl(msg->counter)) {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // decrypt and auth message
|
|
|
|
|
|
|
+bool crypto_ctx_decrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, uint8_t* out) {
|
|
|
|
|
+ if(in_len < MSG_OVERHEAD + 1) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ struct ESubGhzChatCryptoMsg* msg = (struct ESubGhzChatCryptoMsg*)in;
|
|
|
|
|
+
|
|
|
|
|
+ // check if message is stale, if yes, discard
|
|
|
|
|
+ uint32_t* counter = ESubGhzChatReplayDict_get(ctx->replay_dict, msg->run_id);
|
|
|
|
|
+ if(counter != NULL) {
|
|
|
|
|
+ if(*counter >= __ntohl(msg->counter)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // decrypt and auth message
|
|
|
#ifdef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
|
#ifdef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
|
|
- bool ret = (furi_hal_crypto_gcm_decrypt_and_verify(ctx->key,
|
|
|
|
|
- msg->iv,
|
|
|
|
|
- (uint8_t *) msg, RUN_ID_BYTES + COUNTER_BYTES,
|
|
|
|
|
- msg->data, out,
|
|
|
|
|
- in_len - MSG_OVERHEAD,
|
|
|
|
|
- msg->tag) == FuriHalCryptoGCMStateOk);
|
|
|
|
|
|
|
+ bool ret =
|
|
|
|
|
+ (furi_hal_crypto_gcm_decrypt_and_verify(
|
|
|
|
|
+ ctx->key,
|
|
|
|
|
+ msg->iv,
|
|
|
|
|
+ (uint8_t*)msg,
|
|
|
|
|
+ RUN_ID_BYTES + COUNTER_BYTES,
|
|
|
|
|
+ msg->data,
|
|
|
|
|
+ out,
|
|
|
|
|
+ in_len - MSG_OVERHEAD,
|
|
|
|
|
+ msg->tag) == FuriHalCryptoGCMStateOk);
|
|
|
#else /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
#else /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
|
- bool ret = (gcm_auth_decrypt(&(ctx->gcm_ctx),
|
|
|
|
|
- msg->iv, IV_BYTES,
|
|
|
|
|
- (uint8_t *) msg, RUN_ID_BYTES + COUNTER_BYTES,
|
|
|
|
|
- msg->data, out,
|
|
|
|
|
- in_len - MSG_OVERHEAD,
|
|
|
|
|
- msg->tag, TAG_BYTES) == 0);
|
|
|
|
|
|
|
+ bool ret =
|
|
|
|
|
+ (gcm_auth_decrypt(
|
|
|
|
|
+ &(ctx->gcm_ctx),
|
|
|
|
|
+ msg->iv,
|
|
|
|
|
+ IV_BYTES,
|
|
|
|
|
+ (uint8_t*)msg,
|
|
|
|
|
+ RUN_ID_BYTES + COUNTER_BYTES,
|
|
|
|
|
+ msg->data,
|
|
|
|
|
+ out,
|
|
|
|
|
+ in_len - MSG_OVERHEAD,
|
|
|
|
|
+ msg->tag,
|
|
|
|
|
+ TAG_BYTES) == 0);
|
|
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
|
|
|
|
|
|
- // if auth was successful update replay dict
|
|
|
|
|
- if (ret) {
|
|
|
|
|
- ESubGhzChatReplayDict_set_at(ctx->replay_dict, msg->run_id,
|
|
|
|
|
- __ntohl(msg->counter));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // if auth was successful update replay dict
|
|
|
|
|
+ if(ret) {
|
|
|
|
|
+ ESubGhzChatReplayDict_set_at(ctx->replay_dict, msg->run_id, __ntohl(msg->counter));
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- return ret;
|
|
|
|
|
|
|
+ return ret;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx *ctx, uint8_t *in, size_t in_len,
|
|
|
|
|
- uint8_t *out)
|
|
|
|
|
-{
|
|
|
|
|
- struct ESubGhzChatCryptoMsg *msg = (struct ESubGhzChatCryptoMsg *) out;
|
|
|
|
|
|
|
+bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, uint8_t* out) {
|
|
|
|
|
+ struct ESubGhzChatCryptoMsg* msg = (struct ESubGhzChatCryptoMsg*)out;
|
|
|
|
|
|
|
|
- // fill message header
|
|
|
|
|
- msg->run_id = ctx->run_id;
|
|
|
|
|
- msg->counter = __htonl(ctx->counter);
|
|
|
|
|
- furi_hal_random_fill_buf(msg->iv, IV_BYTES);
|
|
|
|
|
|
|
+ // fill message header
|
|
|
|
|
+ msg->run_id = ctx->run_id;
|
|
|
|
|
+ msg->counter = __htonl(ctx->counter);
|
|
|
|
|
+ furi_hal_random_fill_buf(msg->iv, IV_BYTES);
|
|
|
|
|
|
|
|
- // encrypt message and store tag in header
|
|
|
|
|
|
|
+ // encrypt message and store tag in header
|
|
|
#ifdef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
|
#ifdef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
|
|
- bool ret = (furi_hal_crypto_gcm_encrypt_and_tag(ctx->key,
|
|
|
|
|
- msg->iv,
|
|
|
|
|
- (uint8_t *) msg, RUN_ID_BYTES + COUNTER_BYTES,
|
|
|
|
|
- in, msg->data,
|
|
|
|
|
- in_len,
|
|
|
|
|
- msg->tag) == FuriHalCryptoGCMStateOk);
|
|
|
|
|
|
|
+ bool ret =
|
|
|
|
|
+ (furi_hal_crypto_gcm_encrypt_and_tag(
|
|
|
|
|
+ ctx->key,
|
|
|
|
|
+ msg->iv,
|
|
|
|
|
+ (uint8_t*)msg,
|
|
|
|
|
+ RUN_ID_BYTES + COUNTER_BYTES,
|
|
|
|
|
+ in,
|
|
|
|
|
+ msg->data,
|
|
|
|
|
+ in_len,
|
|
|
|
|
+ msg->tag) == FuriHalCryptoGCMStateOk);
|
|
|
#else /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
#else /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
|
- bool ret = (gcm_crypt_and_tag(&(ctx->gcm_ctx), ENCRYPT,
|
|
|
|
|
- msg->iv, IV_BYTES,
|
|
|
|
|
- (uint8_t *) msg, RUN_ID_BYTES + COUNTER_BYTES,
|
|
|
|
|
- in, msg->data,
|
|
|
|
|
- in_len,
|
|
|
|
|
- msg->tag, TAG_BYTES) == 0);
|
|
|
|
|
|
|
+ bool ret =
|
|
|
|
|
+ (gcm_crypt_and_tag(
|
|
|
|
|
+ &(ctx->gcm_ctx),
|
|
|
|
|
+ ENCRYPT,
|
|
|
|
|
+ msg->iv,
|
|
|
|
|
+ IV_BYTES,
|
|
|
|
|
+ (uint8_t*)msg,
|
|
|
|
|
+ RUN_ID_BYTES + COUNTER_BYTES,
|
|
|
|
|
+ in,
|
|
|
|
|
+ msg->data,
|
|
|
|
|
+ in_len,
|
|
|
|
|
+ msg->tag,
|
|
|
|
|
+ TAG_BYTES) == 0);
|
|
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
|
|
|
|
|
|
|
- // update replay dict and increase internal counter
|
|
|
|
|
- if (ret) {
|
|
|
|
|
- ESubGhzChatReplayDict_set_at(ctx->replay_dict, ctx->run_id,
|
|
|
|
|
- ctx->counter);
|
|
|
|
|
- ctx->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;
|
|
|
|
|
|
|
+ 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_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;
|
|
|
|
|
|
|
+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;
|
|
|
|
|
|
|
+ uint64_t run_id;
|
|
|
|
|
+ uint32_t counter;
|
|
|
|
|
|
|
|
- while (reader(&run_id, &counter, reader_ctx)) {
|
|
|
|
|
- ESubGhzChatReplayDict_set_at(ctx->replay_dict, run_id,
|
|
|
|
|
- counter);
|
|
|
|
|
- ret++;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ while(reader(&run_id, &counter, reader_ctx)) {
|
|
|
|
|
+ ESubGhzChatReplayDict_set_at(ctx->replay_dict, run_id, counter);
|
|
|
|
|
+ ret++;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- return ret;
|
|
|
|
|
|
|
+ return ret;
|
|
|
}
|
|
}
|