Compare commits

...
Author SHA1 Message Date
David 2a182a2f5c Allow saved KIA V5 captures to reopen
Build Dev Firmware / build (push) Has been cancelled
2026-07-11 18:33:15 +02:00
David b13f42f8bc Fix KeeLoq and KIA V5 replay handling
Build Dev Firmware / build (push) Has been cancelled
2026-07-11 18:00:58 +02:00
2 changed files with 26 additions and 8 deletions
@@ -187,12 +187,15 @@ bool subghz_scene_keeloq_decrypt_on_event(void* context, SceneManagerEvent event
if(!subghz->keeloq_keys_manager) { if(!subghz->keeloq_keys_manager) {
subghz->keeloq_keys_manager = subghz_keeloq_keys_alloc(); subghz->keeloq_keys_manager = subghz_keeloq_keys_alloc();
} }
uint16_t learning_type = ctx->recovered_type ?
ctx->recovered_type :
KEELOQ_LEARNING_SIMPLE;
char key_name[24]; char key_name[24];
snprintf(key_name, sizeof(key_name), "BF_%07lX", ctx->serial); snprintf(key_name, sizeof(key_name), "BF_%07lX", ctx->serial);
subghz_keeloq_keys_add( subghz_keeloq_keys_add(
subghz->keeloq_keys_manager, subghz->keeloq_keys_manager,
ctx->recovered_mfkey, ctx->recovered_mfkey,
KEELOQ_LEARNING_SIMPLE, learning_type,
key_name); key_name);
subghz_keeloq_keys_save(subghz->keeloq_keys_manager); subghz_keeloq_keys_save(subghz->keeloq_keys_manager);
@@ -202,7 +205,7 @@ bool subghz_scene_keeloq_decrypt_on_event(void* context, SceneManagerEvent event
SubGhzKey* entry = SubGhzKeyArray_push_raw(*env_arr); SubGhzKey* entry = SubGhzKeyArray_push_raw(*env_arr);
entry->name = furi_string_alloc_set(key_name); entry->name = furi_string_alloc_set(key_name);
entry->key = ctx->recovered_mfkey; entry->key = ctx->recovered_mfkey;
entry->type = KEELOQ_LEARNING_SIMPLE; entry->type = learning_type;
return true; return true;
} else if(event.event == KL_DECRYPT_EVENT_DONE) { } else if(event.event == KL_DECRYPT_EVENT_DONE) {
+21 -6
View File
@@ -95,8 +95,7 @@ static uint16_t mixer_decode(uint32_t encrypted) {
return (s0 + (s1 << 8)) & 0xFFFF; return (s0 + (s1 << 8)) & 0xFFFF;
} }
static __attribute__((unused)) uint32_t mixer_encode( static uint32_t mixer_encode(uint32_t serial, uint16_t counter, uint8_t button) {
uint32_t serial, uint16_t counter, uint8_t button) {
uint8_t s0 = (uint8_t)(((serial >> 8) & 0x0FU) | ((button & 0x0FU) << 4)); uint8_t s0 = (uint8_t)(((serial >> 8) & 0x0FU) | ((button & 0x0FU) << 4));
uint8_t s1 = (uint8_t)((counter >> 8) & 0xFFU); uint8_t s1 = (uint8_t)((counter >> 8) & 0xFFU);
uint8_t s2 = (uint8_t)(serial & 0xFFU); uint8_t s2 = (uint8_t)(serial & 0xFFU);
@@ -156,6 +155,17 @@ static __attribute__((unused)) uint32_t mixer_encode(
return ((uint32_t)s0 << 24) | ((uint32_t)s2 << 16) | ((uint32_t)s1 << 8) | (uint32_t)s3; return ((uint32_t)s0 << 24) | ((uint32_t)s2 << 16) | ((uint32_t)s1 << 8) | (uint32_t)s3;
} }
static uint64_t kia_v5_encode_data(uint32_t serial, uint16_t counter, uint8_t button) {
serial &= 0x0FFFFFFFU;
button &= 0x0FU;
const uint32_t encrypted = mixer_encode(serial, counter, button);
const uint64_t yek =
((uint64_t)button << 60) | ((uint64_t)serial << 32) | (uint64_t)encrypted;
return bit_reverse_64(yek);
}
struct SubGhzProtocolDecoderKiaV5 { struct SubGhzProtocolDecoderKiaV5 {
SubGhzProtocolDecoderBase base; SubGhzProtocolDecoderBase base;
SubGhzBlockDecoder decoder; SubGhzBlockDecoder decoder;
@@ -326,6 +336,8 @@ SubGhzProtocolStatus
} }
subghz_custom_btn_set_max(4); subghz_custom_btn_set_max(4);
instance->generic.data = kia_v5_encode_data(
instance->generic.serial, instance->generic.cnt, instance->generic.btn);
instance->replay_data = instance->generic.data; instance->replay_data = instance->generic.data;
instance->replay_crc = kia_v5_calculate_crc(instance->replay_data); instance->replay_crc = kia_v5_calculate_crc(instance->replay_data);
@@ -675,10 +687,13 @@ SubGhzProtocolStatus
furi_assert(context); furi_assert(context);
SubGhzProtocolDecoderKiaV5* instance = context; SubGhzProtocolDecoderKiaV5* instance = context;
SubGhzProtocolStatus ret = subghz_block_generic_deserialize_check_count_bit( SubGhzProtocolStatus ret = subghz_block_generic_deserialize(&instance->generic, flipper_format);
&instance->generic,
flipper_format, if((ret == SubGhzProtocolStatusOk) &&
subghz_protocol_kia_v5_const.min_count_bit_for_found); (instance->generic.data_count_bit <
subghz_protocol_kia_v5_const.min_count_bit_for_found)) {
ret = SubGhzProtocolStatusErrorParserBitCount;
}
if(ret == SubGhzProtocolStatusOk) { if(ret == SubGhzProtocolStatusOk) {
flipper_format_rewind(flipper_format); flipper_format_rewind(flipper_format);