Add BFT creation

This commit is contained in:
r3df0xx
2022-05-24 23:43:23 +03:00
parent dd2da164de
commit 23053b9f82
8 changed files with 348 additions and 37 deletions

View File

@@ -20,6 +20,9 @@ ADD_SCENE(subghz, set_type, SetType)
ADD_SCENE(subghz, set_fix, SetFix) ADD_SCENE(subghz, set_fix, SetFix)
ADD_SCENE(subghz, set_cnt, SetCnt) ADD_SCENE(subghz, set_cnt, SetCnt)
ADD_SCENE(subghz, set_seed, SetSeed) ADD_SCENE(subghz, set_seed, SetSeed)
ADD_SCENE(subghz, set_fix_bft, SetFixBft)
ADD_SCENE(subghz, set_cnt_bft, SetCntBft)
ADD_SCENE(subghz, set_seed_bft, SetSeedBft)
ADD_SCENE(subghz, frequency_analyzer, FrequencyAnalyzer) ADD_SCENE(subghz, frequency_analyzer, FrequencyAnalyzer)
ADD_SCENE(subghz, read_raw, ReadRAW) ADD_SCENE(subghz, read_raw, ReadRAW)
ADD_SCENE(subghz, more_raw, MoreRAW) ADD_SCENE(subghz, more_raw, MoreRAW)

View File

@@ -0,0 +1,46 @@
#include "../subghz_i.h"
#define TAG "SubGhzSetCntBft"
void subghz_scene_set_cnt_bft_byte_input_callback(void* context) {
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone);
}
void subghz_scene_set_cnt_bft_on_enter(void* context) {
SubGhz* subghz = context;
// Setup view
ByteInput* byte_input = subghz->byte_input;
byte_input_set_header_text(byte_input, "Enter COUNTER in hex");
byte_input_set_result_callback(
byte_input,
subghz_scene_set_cnt_bft_byte_input_callback,
NULL,
subghz,
subghz->txrx->secure_data->cnt,
2);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput);
}
bool subghz_scene_set_cnt_bft_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventByteInputDone) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetSeedBft);
consumed = true;
}
}
return consumed;
}
void subghz_scene_set_cnt_bft_on_exit(void* context) {
SubGhz* subghz = context;
// Clear view
byte_input_set_result_callback(subghz->byte_input, NULL, NULL, NULL, NULL, 0);
byte_input_set_header_text(subghz->byte_input, "");
}

View File

@@ -0,0 +1,46 @@
#include "../subghz_i.h"
#define TAG "SubGhzSetFixBft"
void subghz_scene_set_fix_bft_byte_input_callback(void* context) {
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone);
}
void subghz_scene_set_fix_bft_on_enter(void* context) {
SubGhz* subghz = context;
// Setup view
ByteInput* byte_input = subghz->byte_input;
byte_input_set_header_text(byte_input, "Enter FIX in hex");
byte_input_set_result_callback(
byte_input,
subghz_scene_set_fix_bft_byte_input_callback,
NULL,
subghz,
subghz->txrx->secure_data->fix,
4);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput);
}
bool subghz_scene_set_fix_bft_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventByteInputDone) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetCntBft);
consumed = true;
}
}
return consumed;
}
void subghz_scene_set_fix_bft_on_exit(void* context) {
SubGhz* subghz = context;
// Clear view
byte_input_set_result_callback(subghz->byte_input, NULL, NULL, NULL, NULL, 0);
byte_input_set_header_text(subghz->byte_input, "");
}

View File

@@ -0,0 +1,99 @@
#include "../subghz_i.h"
#include <dolphin/dolphin.h>
#include <lib/subghz/protocols/keeloq.h>
#define TAG "SubGhzSetSeedBft"
void subghz_scene_set_seed_bft_byte_input_callback(void* context) {
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone);
}
void subghz_scene_set_seed_bft_on_enter(void* context) {
SubGhz* subghz = context;
// Setup view
ByteInput* byte_input = subghz->byte_input;
byte_input_set_header_text(byte_input, "Enter SEED in hex");
byte_input_set_result_callback(
byte_input,
subghz_scene_set_seed_bft_byte_input_callback,
NULL,
subghz,
subghz->txrx->secure_data->seed,
4);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput);
}
bool subghz_scene_set_seed_bft_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
bool consumed = false;
bool generated_protocol = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventByteInputDone) {
uint32_t fix_part = subghz->txrx->secure_data->fix[0] << 24 | subghz->txrx->secure_data->fix[1] << 16 |
subghz->txrx->secure_data->fix[2] << 8 | subghz->txrx->secure_data->fix[3];
uint16_t cnt = subghz->txrx->secure_data->cnt[0] << 8 | subghz->txrx->secure_data->cnt[1];
uint32_t seed = subghz->txrx->secure_data->seed[0] << 24 | subghz->txrx->secure_data->seed[1] << 16 |
subghz->txrx->secure_data->seed[2] << 8 | subghz->txrx->secure_data->seed[3];
subghz->txrx->transmitter =
subghz_transmitter_alloc_init(subghz->txrx->environment, "KeeLoq");
if(subghz->txrx->transmitter) {
subghz_protocol_keeloq_bft_create_data(
subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter),
subghz->txrx->fff_data,
fix_part & 0x0FFFFFFF,
fix_part >> 28,
cnt,
seed,
"BFT",
433920000,
FuriHalSubGhzPresetOok650Async);
uint8_t seed_data[sizeof(uint32_t)] = {0};
for(size_t i = 0; i < sizeof(uint32_t); i++) {
seed_data[sizeof(uint32_t) - i - 1] = (seed >> i * 8) & 0xFF;
}
flipper_format_write_hex(subghz->txrx->fff_data, "Seed", seed_data, sizeof(uint32_t));
FURI_LOG_I(TAG, "SEED: %8X\n", seed);
generated_protocol = true;
} else {
generated_protocol = false;
}
subghz_transmitter_free(subghz->txrx->transmitter);
if(!generated_protocol) {
string_set(
subghz->error_str, "Function requires\nan SD card with\nfresh databases.");
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
}
consumed = true;
}
if(generated_protocol) {
subghz_file_name_clear(subghz);
DOLPHIN_DEED(DolphinDeedSubGhzAddManually);
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneSetType, SubGhzCustomEventManagerSet);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
return true;
}
}
return consumed;;
}
void subghz_scene_set_seed_bft_on_exit(void* context) {
SubGhz* subghz = context;
// Clear view
byte_input_set_result_callback(subghz->byte_input, NULL, NULL, NULL, NULL, 0);
byte_input_set_header_text(subghz->byte_input, "");
}

View File

@@ -12,6 +12,7 @@
enum SubmenuIndex { enum SubmenuIndex {
SubmenuIndexFaacSLH, SubmenuIndexFaacSLH,
SubmenuIndexBFT,
SubmenuIndexPricenton, SubmenuIndexPricenton,
SubmenuIndexNiceFlo12bit, SubmenuIndexNiceFlo12bit,
SubmenuIndexNiceFlo24bit, SubmenuIndexNiceFlo24bit,
@@ -89,6 +90,12 @@ void subghz_scene_set_type_on_enter(void* context) {
SubmenuIndexFaacSLH, SubmenuIndexFaacSLH,
subghz_scene_set_type_submenu_callback, subghz_scene_set_type_submenu_callback,
subghz); subghz);
submenu_add_item(
subghz->submenu,
"BFT Mitto",
SubmenuIndexBFT,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item( submenu_add_item(
subghz->submenu, subghz->submenu,
"Princeton_433", "Princeton_433",
@@ -183,6 +190,9 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
case SubmenuIndexFaacSLH: case SubmenuIndexFaacSLH:
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFix); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFix);
break; break;
case SubmenuIndexBFT:
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFixBft);
break;
case SubmenuIndexPricenton: case SubmenuIndexPricenton:
key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
if(subghz_scene_set_type_submenu_gen_data_protocol( if(subghz_scene_set_type_submenu_gen_data_protocol(

View File

@@ -78,8 +78,6 @@ const SubGhzProtocol subghz_protocol_faac_slh = {
.encoder = &subghz_protocol_faac_slh_encoder, .encoder = &subghz_protocol_faac_slh_encoder,
}; };
//static uint32_t seed_global;
/** /**
* Analysis of received data * Analysis of received data
* @param instance Pointer to a SubGhzBlockGeneric* instance * @param instance Pointer to a SubGhzBlockGeneric* instance
@@ -163,20 +161,19 @@ bool subghz_protocol_faac_slh_create_data(
const char* manufacture_name, const char* manufacture_name,
uint32_t frequency, uint32_t frequency,
FuriHalSubGhzPreset preset) { FuriHalSubGhzPreset preset) {
furi_assert(context); furi_assert(context);
SubGhzProtocolEncoderFaacSLH* instance = context; SubGhzProtocolEncoderFaacSLH* instance = context;
instance->generic.serial = serial; instance->generic.serial = serial;
instance->generic.btn = btn; instance->generic.btn = btn;
instance->generic.cnt = cnt; instance->generic.cnt = cnt;
instance->generic.seed = seed; instance->generic.seed = seed;
//seed_global = instance->generic.seed; instance->manufacture_name = manufacture_name;
instance->manufacture_name = manufacture_name; instance->generic.data_count_bit = 64;
instance->generic.data_count_bit = 64; bool res = subghz_protocol_faac_slh_gen_data(instance);
bool res = subghz_protocol_faac_slh_gen_data(instance); if(res) {
if(res) { res = subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
res = subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset); }
} return res;
return res;
} }
/** /**
@@ -399,7 +396,7 @@ static void subghz_protocol_faac_slh_check_remote_controller
(SubGhzBlockGeneric* instance, (SubGhzBlockGeneric* instance,
SubGhzKeystore* keystore, SubGhzKeystore* keystore,
const char** manufacture_name) { const char** manufacture_name) {
//instance->seed = seed_global;
FURI_LOG_I(TAG, "seed check = %8X", instance->seed); FURI_LOG_I(TAG, "seed check = %8X", instance->seed);
uint32_t code_fix = instance->data >> 32; uint32_t code_fix = instance->data >> 32;
uint32_t code_hop = instance->data & 0xFFFFFFFF; uint32_t code_hop = instance->data & 0xFFFFFFFF;

View File

@@ -141,16 +141,22 @@ static bool subghz_protocol_keeloq_gen_data(SubGhzProtocolEncoderKeeloq* instanc
break; break;
case KEELOQ_LEARNING_NORMAL: case KEELOQ_LEARNING_NORMAL:
//Simple Learning //Simple Learning
man = man = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); hop = subghz_protocol_keeloq_common_encrypt(decrypt, man);
break;
case KEELOQ_LEARNING_SECURE:
//Secure Learning
man = subghz_protocol_keeloq_common_secure_learning(fix, instance->generic.seed, manufacture_code->key);
hop = subghz_protocol_keeloq_common_encrypt(decrypt, man); hop = subghz_protocol_keeloq_common_encrypt(decrypt, man);
break; break;
case KEELOQ_LEARNING_MAGIC_XOR_TYPE_1: case KEELOQ_LEARNING_MAGIC_XOR_TYPE_1:
//Magic XOR type-1 Learning
man = subghz_protocol_keeloq_common_magic_xor_type1_learning( man = subghz_protocol_keeloq_common_magic_xor_type1_learning(
instance->generic.serial, manufacture_code->key); instance->generic.serial, manufacture_code->key);
hop = subghz_protocol_keeloq_common_encrypt(decrypt, man); hop = subghz_protocol_keeloq_common_encrypt(decrypt, man);
break; break;
case KEELOQ_LEARNING_UNKNOWN: case KEELOQ_LEARNING_UNKNOWN:
//KeeLoq Replay Attack (sends just the captured key)
code_found_reverse = subghz_protocol_blocks_reverse_key( code_found_reverse = subghz_protocol_blocks_reverse_key(
instance->generic.data, instance->generic.data_count_bit); instance->generic.data, instance->generic.data_count_bit);
hop = code_found_reverse & 0x00000000ffffffff; hop = code_found_reverse & 0x00000000ffffffff;
@@ -176,18 +182,42 @@ bool subghz_protocol_keeloq_create_data(
const char* manufacture_name, const char* manufacture_name,
uint32_t frequency, uint32_t frequency,
FuriHalSubGhzPreset preset) { FuriHalSubGhzPreset preset) {
furi_assert(context); furi_assert(context);
SubGhzProtocolEncoderKeeloq* instance = context; SubGhzProtocolEncoderKeeloq* instance = context;
instance->generic.serial = serial; instance->generic.serial = serial;
instance->generic.cnt = cnt; instance->generic.cnt = cnt;
instance->manufacture_name = manufacture_name; instance->manufacture_name = manufacture_name;
instance->generic.data_count_bit = 64; instance->generic.data_count_bit = 64;
bool res = subghz_protocol_keeloq_gen_data(instance, btn); bool res = subghz_protocol_keeloq_gen_data(instance, btn);
if(res) { if(res) {
res = res = subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset); }
} return res;
return res; }
bool subghz_protocol_keeloq_bft_create_data(
void* context,
FlipperFormat* flipper_format,
uint32_t serial,
uint8_t btn,
uint16_t cnt,
uint32_t seed,
const char* manufacture_name,
uint32_t frequency,
FuriHalSubGhzPreset preset) {
furi_assert(context);
SubGhzProtocolEncoderKeeloq* instance = context;
instance->generic.serial = serial;
instance->generic.btn = btn;
instance->generic.cnt = cnt;
instance->generic.seed = seed;
instance->manufacture_name = manufacture_name;
instance->generic.data_count_bit = 64;
bool res = subghz_protocol_keeloq_gen_data(instance, btn);
if(res) {
res = subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
}
return res;
} }
/** /**
@@ -266,6 +296,16 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl
FURI_LOG_E(TAG, "Deserialize error"); FURI_LOG_E(TAG, "Deserialize error");
break; break;
} }
uint8_t seed_data[sizeof(uint32_t)] = {0};
for(size_t i = 0; i < sizeof(uint32_t); i++) {
seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF;
}
if(!flipper_format_read_hex(flipper_format, "Seed", seed_data, sizeof(uint32_t))) {
FURI_LOG_E(TAG, "Missing Seed");
break;
}
instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 | seed_data[3] ;
FURI_LOG_I(TAG, "encoder seed = %8X", instance->generic.seed);
subghz_protocol_keeloq_check_remote_controller( subghz_protocol_keeloq_check_remote_controller(
&instance->generic, instance->keystore, &instance->manufacture_name); &instance->generic, instance->keystore, &instance->manufacture_name);
@@ -474,7 +514,6 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
uint8_t btn = (uint8_t)(fix >> 28); uint8_t btn = (uint8_t)(fix >> 28);
uint32_t decrypt = 0; uint32_t decrypt = 0;
uint64_t man; uint64_t man;
uint32_t seed = 0;
for for
M_EACH(manufacture_code, *subghz_keystore_get_data(keystore), SubGhzKeyArray_t) { M_EACH(manufacture_code, *subghz_keystore_get_data(keystore), SubGhzKeyArray_t) {
@@ -499,7 +538,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
break; break;
case KEELOQ_LEARNING_SECURE: case KEELOQ_LEARNING_SECURE:
man = subghz_protocol_keeloq_common_secure_learning( man = subghz_protocol_keeloq_common_secure_learning(
fix, seed, manufacture_code->key); fix, instance->seed, manufacture_code->key);
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man);
if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) {
*manufacture_name = string_get_cstr(manufacture_code->name); *manufacture_name = string_get_cstr(manufacture_code->name);
@@ -554,7 +593,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
// Secure Learning // Secure Learning
man = subghz_protocol_keeloq_common_secure_learning( man = subghz_protocol_keeloq_common_secure_learning(
fix, seed, manufacture_code->key); fix, instance->seed, manufacture_code->key);
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man);
if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) {
*manufacture_name = string_get_cstr(manufacture_code->name); *manufacture_name = string_get_cstr(manufacture_code->name);
@@ -562,7 +601,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
} }
// Check for mirrored man // Check for mirrored man
man = subghz_protocol_keeloq_common_secure_learning(fix, seed, man_rev); man = subghz_protocol_keeloq_common_secure_learning(fix, instance->seed, man_rev);
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man);
if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) {
*manufacture_name = string_get_cstr(manufacture_code->name); *manufacture_name = string_get_cstr(manufacture_code->name);
@@ -633,11 +672,23 @@ bool subghz_protocol_decoder_keeloq_serialize(
FuriHalSubGhzPreset preset) { FuriHalSubGhzPreset preset) {
furi_assert(context); furi_assert(context);
SubGhzProtocolDecoderKeeloq* instance = context; SubGhzProtocolDecoderKeeloq* instance = context;
subghz_protocol_keeloq_check_remote_controller(
&instance->generic, instance->keystore, &instance->manufacture_name);
bool res = bool res =
subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset); subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
uint8_t seed_data[sizeof(uint32_t)] = {0};
for(size_t i = 0; i < sizeof(uint32_t); i++) {
seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF;
}
if(res && !flipper_format_write_hex(flipper_format, "Seed", seed_data, sizeof(uint32_t))) {
FURI_LOG_E(TAG, "Unable to add Seed");
res = false;
}
instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 | seed_data[3] ;
FURI_LOG_I(TAG, "decoder seed = %8X", instance->generic.seed);
subghz_protocol_keeloq_check_remote_controller(
&instance->generic, instance->keystore, &instance->manufacture_name);
if(res && !flipper_format_write_string_cstr( if(res && !flipper_format_write_string_cstr(
flipper_format, "Manufacture", instance->manufacture_name)) { flipper_format, "Manufacture", instance->manufacture_name)) {
@@ -656,6 +707,20 @@ bool subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* fl
FURI_LOG_E(TAG, "Deserialize error"); FURI_LOG_E(TAG, "Deserialize error");
break; break;
} }
if(!flipper_format_rewind(flipper_format)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
uint8_t seed_data[sizeof(uint32_t)] = {0};
for(size_t i = 0; i < sizeof(uint32_t); i++) {
seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF;
}
if(!flipper_format_read_hex(flipper_format, "Seed", seed_data, sizeof(uint32_t))) {
FURI_LOG_E(TAG, "Missing Seed");
break;
}
instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 | seed_data[3] ;
FURI_LOG_I(TAG, "decoder seed = %8X", instance->generic.seed);
res = true; res = true;
} while(false); } while(false);
@@ -676,7 +741,27 @@ void subghz_protocol_decoder_keeloq_get_string(void* context, string_t output) {
uint32_t code_found_reverse_hi = code_found_reverse >> 32; uint32_t code_found_reverse_hi = code_found_reverse >> 32;
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
if (strcmp(instance->generic.protocol_name, "BFT") == 0) {
string_cat_printf( string_cat_printf(
output,
"%s %dbit\r\n"
"Key:%08lX%08lX\r\n"
"Fix:0x%08lX Cnt:%04X\r\n"
"Hop:0x%08lX Btn:%01lX\r\n"
"MF:%s Sd:%08lX\r\n",
instance->generic.protocol_name,
instance->generic.data_count_bit,
code_found_hi,
code_found_lo,
code_found_reverse_hi,
instance->generic.cnt,
code_found_reverse_lo,
instance->generic.btn,
instance->manufacture_name,
instance->generic.seed);
} else {
string_cat_printf(
output, output,
"%s %dbit\r\n" "%s %dbit\r\n"
"Key:%08lX%08lX\r\n" "Key:%08lX%08lX\r\n"
@@ -693,4 +778,5 @@ void subghz_protocol_decoder_keeloq_get_string(void* context, string_t output) {
instance->generic.btn, instance->generic.btn,
instance->manufacture_name, instance->manufacture_name,
instance->generic.serial); instance->generic.serial);
}
} }

View File

@@ -46,6 +46,30 @@ bool subghz_protocol_keeloq_create_data(
uint32_t frequency, uint32_t frequency,
FuriHalSubGhzPreset preset); FuriHalSubGhzPreset preset);
/**
* Key generation for BFT.
* @param context Pointer to a SubGhzProtocolEncoderKeeloq instance
* @param flipper_format Pointer to a FlipperFormat instance
* @param serial Serial number, 28 bit
* @param btn Button number, 4 bit
* @param cnt Counter value, 16 bit
* @param seed Seed value, 32 bit
* @param manufacture_name Name of manufacturer's key
* @param frequency Transmission frequency, Hz
* @param preset Modulation, FuriHalSubGhzPreset
* @return true On success
*/
bool subghz_protocol_keeloq_bft_create_data(
void* context,
FlipperFormat* flipper_format,
uint32_t serial,
uint8_t btn,
uint16_t cnt,
uint32_t seed,
const char* manufacture_name,
uint32_t frequency,
FuriHalSubGhzPreset preset);
/** /**
* Deserialize and generating an upload to send. * Deserialize and generating an upload to send.
* @param context Pointer to a SubGhzProtocolEncoderKeeloq instance * @param context Pointer to a SubGhzProtocolEncoderKeeloq instance