diff --git a/applications/subghz/scenes/subghz_scene_receiver_info.c b/applications/subghz/scenes/subghz_scene_receiver_info.c index 19b9b69ef..9ae57f4c8 100644 --- a/applications/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/subghz/scenes/subghz_scene_receiver_info.c @@ -2,6 +2,7 @@ #include "../helpers/subghz_custom_event.h" #include #include +#include void subghz_scene_receiver_info_callback(GuiButtonType result, InputType type, void* context) { furi_assert(context); @@ -193,4 +194,7 @@ void subghz_scene_receiver_info_on_exit(void* context) { SubGhz* subghz = context; widget_reset(subghz->widget); keeloq_reset_mfname(); + keeloq_reset_kl_type(); + star_line_reset_mfname(); + star_line_reset_kl_type(); } diff --git a/applications/subghz/scenes/subghz_scene_transmitter.c b/applications/subghz/scenes/subghz_scene_transmitter.c index 070399672..8020966a2 100644 --- a/applications/subghz/scenes/subghz_scene_transmitter.c +++ b/applications/subghz/scenes/subghz_scene_transmitter.c @@ -2,6 +2,7 @@ #include "../views/transmitter.h" #include #include +#include void subghz_scene_transmitter_callback(SubGhzCustomEvent event, void* context) { furi_assert(context); @@ -111,4 +112,7 @@ void subghz_scene_transmitter_on_exit(void* context) { SubGhz* subghz = context; subghz->state_notifications = SubGhzNotificationStateIDLE; keeloq_reset_mfname(); + keeloq_reset_kl_type(); + star_line_reset_mfname(); + star_line_reset_kl_type(); } diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index 04ff9a110..0be5dcc71 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -82,11 +82,16 @@ const SubGhzProtocol subghz_protocol_keeloq = { }; static const char* mfname; +static int kl_type; void keeloq_reset_mfname() { mfname = ""; } +void keeloq_reset_kl_type() { + kl_type = 0; +} + /** * Analysis of received data * @param instance Pointer to a SubGhzBlockGeneric* instance @@ -136,6 +141,11 @@ static bool subghz_protocol_keeloq_gen_data(SubGhzProtocolEncoderKeeloq* instanc uint64_t code_found_reverse; int res = 0; + if (strcmp(instance->manufacture_name, "Unknown") == 0) { + code_found_reverse = subghz_protocol_blocks_reverse_key( + instance->generic.data, instance->generic.data_count_bit); + hop = code_found_reverse & 0x00000000ffffffff; + } else { for M_EACH(manufacture_code, *subghz_keystore_get_data(instance->keystore), SubGhzKeyArray_t) { res = strcmp(string_get_cstr(manufacture_code->name), instance->manufacture_name); @@ -157,20 +167,22 @@ static bool subghz_protocol_keeloq_gen_data(SubGhzProtocolEncoderKeeloq* instanc break; case KEELOQ_LEARNING_MAGIC_XOR_TYPE_1: //Magic XOR type-1 Learning - man = subghz_protocol_keeloq_common_magic_xor_type1_learning( - instance->generic.serial, manufacture_code->key); + man = subghz_protocol_keeloq_common_magic_xor_type1_learning(instance->generic.serial, manufacture_code->key); hop = subghz_protocol_keeloq_common_encrypt(decrypt, man); break; case KEELOQ_LEARNING_UNKNOWN: - //KeeLoq Replay Attack (sends just the captured key) - code_found_reverse = subghz_protocol_blocks_reverse_key( - instance->generic.data, instance->generic.data_count_bit); - hop = code_found_reverse & 0x00000000ffffffff; + if(kl_type == 1) { hop = subghz_protocol_keeloq_common_encrypt(decrypt, manufacture_code->key); } + if(kl_type == 2) { man = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); + hop = subghz_protocol_keeloq_common_encrypt(decrypt, man); } + if(kl_type == 3) { man = subghz_protocol_keeloq_common_secure_learning(fix, instance->generic.seed, manufacture_code->key); + hop = subghz_protocol_keeloq_common_encrypt(decrypt, man); } + if(kl_type == 4) { man = subghz_protocol_keeloq_common_magic_xor_type1_learning(instance->generic.serial, manufacture_code->key); + hop = subghz_protocol_keeloq_common_encrypt(decrypt, man); } break; } break; } - } + } } if(hop) { uint64_t yek = (uint64_t)fix << 32 | hop; instance->generic.data = @@ -385,6 +397,7 @@ void subghz_protocol_decoder_keeloq_reset(void* context) { SubGhzProtocolDecoderKeeloq* instance = context; instance->decoder.parser_step = KeeloqDecoderStepReset; mfname = ""; + kl_type = 0; } void subghz_protocol_decoder_keeloq_feed(void* context, bool level, uint32_t duration) { @@ -572,6 +585,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 1; return 1; } // Check for mirrored man @@ -585,6 +599,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 1; return 1; } //########################### @@ -595,6 +610,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 2; return 1; } @@ -604,6 +620,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 2; return 1; } @@ -614,6 +631,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 3; return 1; } @@ -623,6 +641,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 3; return 1; } @@ -633,6 +652,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 4; return 1; } @@ -642,6 +662,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 4; return 1; } break; @@ -700,6 +721,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 1; return 1; } // Check for mirrored man @@ -713,6 +735,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 1; return 1; } //########################### @@ -723,6 +746,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 2; return 1; } @@ -732,6 +756,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 2; return 1; } @@ -742,6 +767,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 3; return 1; } @@ -751,6 +777,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 3; return 1; } @@ -761,6 +788,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 4; return 1; } @@ -770,6 +798,7 @@ if(strcmp(mfname, "") == 0) { if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); mfname = *manufacture_name; + kl_type = 4; return 1; } break; diff --git a/lib/subghz/protocols/keeloq.h b/lib/subghz/protocols/keeloq.h index 9be299bd8..97c89b504 100644 --- a/lib/subghz/protocols/keeloq.h +++ b/lib/subghz/protocols/keeloq.h @@ -13,6 +13,8 @@ extern const SubGhzProtocol subghz_protocol_keeloq; void keeloq_reset_mfname(); +void keeloq_reset_kl_type(); + /** * Allocate SubGhzProtocolEncoderKeeloq. * @param environment Pointer to a SubGhzEnvironment instance diff --git a/lib/subghz/protocols/star_line.c b/lib/subghz/protocols/star_line.c index d00fb0384..b72eeb02f 100644 --- a/lib/subghz/protocols/star_line.c +++ b/lib/subghz/protocols/star_line.c @@ -80,6 +80,18 @@ const SubGhzProtocol subghz_protocol_star_line = { .encoder = &subghz_protocol_star_line_encoder, }; +static const char* mfname; + +static int kl_type; + +void star_line_reset_mfname() { + mfname = ""; +} + +void star_line_reset_kl_type() { + kl_type = 0; +} + /** * Analysis of received data * @param instance Pointer to a SubGhzBlockGeneric* instance @@ -129,6 +141,11 @@ static bool subghz_protocol_star_line_gen_data(SubGhzProtocolEncoderStarLine* in uint64_t code_found_reverse; int res = 0; + if (strcmp(instance->manufacture_name, "Unknown") == 0) { + code_found_reverse = subghz_protocol_blocks_reverse_key( + instance->generic.data, instance->generic.data_count_bit); + hop = code_found_reverse & 0x00000000ffffffff; + } else { for M_EACH(manufacture_code, *subghz_keystore_get_data(instance->keystore), SubGhzKeyArray_t) { res = strcmp(string_get_cstr(manufacture_code->name), instance->manufacture_name); @@ -139,25 +156,24 @@ static bool subghz_protocol_star_line_gen_data(SubGhzProtocolEncoderStarLine* in hop = subghz_protocol_keeloq_common_encrypt(decrypt, manufacture_code->key); break; case KEELOQ_LEARNING_NORMAL: - //Simple Learning + //Normal Learning man = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); hop = subghz_protocol_keeloq_common_encrypt(decrypt, man); break; - case KEELOQ_LEARNING_MAGIC_XOR_TYPE_1: - man = subghz_protocol_keeloq_common_magic_xor_type1_learning( - instance->generic.serial, manufacture_code->key); - hop = subghz_protocol_keeloq_common_encrypt(decrypt, man); - break; case KEELOQ_LEARNING_UNKNOWN: - code_found_reverse = subghz_protocol_blocks_reverse_key( - instance->generic.data, instance->generic.data_count_bit); - hop = code_found_reverse & 0x00000000ffffffff; + if(kl_type == 1) { hop = subghz_protocol_keeloq_common_encrypt(decrypt, manufacture_code->key); } + if(kl_type == 2) { man = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); + hop = subghz_protocol_keeloq_common_encrypt(decrypt, man); } + if(kl_type == 3) { man = subghz_protocol_keeloq_common_secure_learning(fix, instance->generic.seed, manufacture_code->key); + hop = subghz_protocol_keeloq_common_encrypt(decrypt, man); } + if(kl_type == 4) { man = subghz_protocol_keeloq_common_magic_xor_type1_learning(instance->generic.serial, manufacture_code->key); + hop = subghz_protocol_keeloq_common_encrypt(decrypt, man); } break; } break; } - } + } } if(hop) { uint64_t yek = (uint64_t)fix << 32 | hop; instance->generic.data = @@ -328,6 +344,8 @@ void subghz_protocol_decoder_star_line_reset(void* context) { furi_assert(context); SubGhzProtocolDecoderStarLine* instance = context; instance->decoder.parser_step = StarLineDecoderStepReset; + mfname = ""; + kl_type = 0; } void subghz_protocol_decoder_star_line_feed(void* context, bool level, uint32_t duration) { @@ -453,26 +471,30 @@ static uint8_t subghz_protocol_star_line_check_remote_controller_selector( uint8_t btn = (uint8_t)(fix >> 24); uint32_t decrypt = 0; uint64_t man_normal_learning; + int res = 0; + +if(strcmp(mfname, "") == 0) { for M_EACH(manufacture_code, *subghz_keystore_get_data(keystore), SubGhzKeyArray_t) { switch(manufacture_code->type) { case KEELOQ_LEARNING_SIMPLE: - //Simple Learning + // Simple Learning decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); + mfname = *manufacture_name; return 1; } break; case KEELOQ_LEARNING_NORMAL: - // Normal_Learning + // Normal Learning // https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37 - man_normal_learning = - subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); + man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); + mfname = *manufacture_name; return 1; } break; @@ -481,6 +503,8 @@ static uint8_t subghz_protocol_star_line_check_remote_controller_selector( decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); + mfname = *manufacture_name; + kl_type = 1; return 1; } // Check for mirrored man @@ -493,27 +517,109 @@ static uint8_t subghz_protocol_star_line_check_remote_controller_selector( decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_rev); if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); + mfname = *manufacture_name; + kl_type = 1; return 1; } //########################### - // Normal_Learning + // Normal Learning // https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37 - man_normal_learning = - subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); + man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); + mfname = *manufacture_name; + kl_type = 2; return 1; } + // Check for mirrored man man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = string_get_cstr(manufacture_code->name); + mfname = *manufacture_name; + kl_type = 2; return 1; } break; } } + } else { + + for + M_EACH(manufacture_code, *subghz_keystore_get_data(keystore), SubGhzKeyArray_t) { + res = strcmp(string_get_cstr(manufacture_code->name), mfname); + if(res == 0) { + switch(manufacture_code->type) { + case KEELOQ_LEARNING_SIMPLE: + // Simple Learning + decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); + if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { + *manufacture_name = string_get_cstr(manufacture_code->name); + mfname = *manufacture_name; + return 1; + } + break; + case KEELOQ_LEARNING_NORMAL: + // Normal Learning + // https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37 + man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); + decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); + if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { + *manufacture_name = string_get_cstr(manufacture_code->name); + mfname = *manufacture_name; + return 1; + } + break; + case KEELOQ_LEARNING_UNKNOWN: + // Simple Learning + decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); + if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { + *manufacture_name = string_get_cstr(manufacture_code->name); + mfname = *manufacture_name; + kl_type = 1; + return 1; + } + // Check for mirrored man + uint64_t man_rev = 0; + uint64_t man_rev_byte = 0; + for(uint8_t i = 0; i < 64; i += 8) { + man_rev_byte = (uint8_t)(manufacture_code->key >> i); + man_rev = man_rev | man_rev_byte << (56 - i); + } + decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_rev); + if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { + *manufacture_name = string_get_cstr(manufacture_code->name); + mfname = *manufacture_name; + kl_type = 1; + return 1; + } + //########################### + // Normal Learning + // https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37 + man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); + decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); + if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { + *manufacture_name = string_get_cstr(manufacture_code->name); + mfname = *manufacture_name; + kl_type = 2; + return 1; + } + + // Check for mirrored man + man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev); + decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); + if(subghz_protocol_star_line_check_decrypt(instance, decrypt, btn, end_serial)) { + *manufacture_name = string_get_cstr(manufacture_code->name); + mfname = *manufacture_name; + kl_type = 2; + return 1; + } + break; + } + } + } + } *manufacture_name = "Unknown"; instance->cnt = 0; diff --git a/lib/subghz/protocols/star_line.h b/lib/subghz/protocols/star_line.h index 8930648fe..286cfa7c5 100644 --- a/lib/subghz/protocols/star_line.h +++ b/lib/subghz/protocols/star_line.h @@ -11,6 +11,10 @@ extern const SubGhzProtocolDecoder subghz_protocol_star_line_decoder; extern const SubGhzProtocolEncoder subghz_protocol_star_line_encoder; extern const SubGhzProtocol subghz_protocol_star_line; +void star_line_reset_mfname(); + +void star_line_reset_kl_type(); + /** * Allocate SubGhzProtocolEncoderStarLine. * @param environment Pointer to a SubGhzEnvironment instance