Fix KeeLoq Uknown behavior, patch StarLine same way

This commit is contained in:
r3df0xx 2022-06-16 19:58:34 +03:00
parent 448c8ad988
commit 0a3aabc60d
6 changed files with 173 additions and 24 deletions

View File

@ -2,6 +2,7 @@
#include "../helpers/subghz_custom_event.h"
#include <dolphin/dolphin.h>
#include <lib/subghz/protocols/keeloq.h>
#include <lib/subghz/protocols/star_line.h>
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();
}

View File

@ -2,6 +2,7 @@
#include "../views/transmitter.h"
#include <dolphin/dolphin.h>
#include <lib/subghz/protocols/keeloq.h>
#include <lib/subghz/protocols/star_line.h>
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();
}

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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