From bc87b86d06caa0612b4a35b79f6e622bfa5cdd0b Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 9 Feb 2026 23:15:00 +0300 Subject: [PATCH 1/2] better defines --- defines.h | 22 ++++++++++++++++++++++ protopirate_app_i.h | 24 +----------------------- scenes/protopirate_scene_config.h | 5 +++-- scenes/protopirate_scene_emulate.c | 2 ++ 4 files changed, 28 insertions(+), 25 deletions(-) create mode 100644 defines.h diff --git a/defines.h b/defines.h new file mode 100644 index 0000000..447a825 --- /dev/null +++ b/defines.h @@ -0,0 +1,22 @@ +//#define ENABLE_TIMING_TUNER_SCENE +#define ENABLE_SUB_DECODE_SCENE + +// #define ENABLE_EMULATE_FEATURE + +#define REMOVE_LOGS + +#ifdef REMOVE_LOGS +// Undefine existing macros +#undef FURI_LOG_E +#undef FURI_LOG_W +#undef FURI_LOG_I +#undef FURI_LOG_D +#undef FURI_LOG_T +// Define empty macros +#define FURI_LOG_E(tag, format, ...) +#define FURI_LOG_W(tag, format, ...) +#define FURI_LOG_I(tag, format, ...) +#define FURI_LOG_D(tag, format, ...) +#define FURI_LOG_T(tag, format, ...) + +#endif // REMOVE_LOGS diff --git a/protopirate_app_i.h b/protopirate_app_i.h index 8492956..14c22cf 100644 --- a/protopirate_app_i.h +++ b/protopirate_app_i.h @@ -23,32 +23,10 @@ #include #include #include +#include "defines.h" #define PROTOPIRATE_KEYSTORE_DIR_NAME APP_ASSETS_PATH("encrypted") -//#define ENABLE_TIMING_TUNER_SCENE -//#define ENABLE_SUB_DECODE_SCENE - -//#define ENABLE_EMULATE_FEATURE - -#define REMOVE_LOGS - -#ifdef REMOVE_LOGS -// Undefine existing macros -#undef FURI_LOG_E -#undef FURI_LOG_W -#undef FURI_LOG_I -#undef FURI_LOG_D -#undef FURI_LOG_T -// Define empty macros -#define FURI_LOG_E(tag, format, ...) -#define FURI_LOG_W(tag, format, ...) -#define FURI_LOG_I(tag, format, ...) -#define FURI_LOG_D(tag, format, ...) -#define FURI_LOG_T(tag, format, ...) - -#endif // REMOVE_LOGS - typedef struct ProtoPirateApp ProtoPirateApp; typedef struct { diff --git a/scenes/protopirate_scene_config.h b/scenes/protopirate_scene_config.h index 9d27ca8..16b433b 100644 --- a/scenes/protopirate_scene_config.h +++ b/scenes/protopirate_scene_config.h @@ -1,7 +1,6 @@ // scenes/protopirate_scene_config.h -//#define ENABLE_TIMING_TUNER_SCENE -//#define ENABLE_SUB_DECODE_SCENE +#include "../defines.h" ADD_SCENE(protopirate, start, Start) #ifdef ENABLE_SUB_DECODE_SCENE @@ -13,7 +12,9 @@ ADD_SCENE(protopirate, receiver_config, ReceiverConfig) ADD_SCENE(protopirate, receiver_info, ReceiverInfo) ADD_SCENE(protopirate, saved, Saved) ADD_SCENE(protopirate, saved_info, SavedInfo) +#ifdef ENABLE_EMULATE_FEATURE ADD_SCENE(protopirate, emulate, Emulate) +#endif #ifdef ENABLE_TIMING_TUNER_SCENE ADD_SCENE(protopirate, timing_tuner, TimingTuner) #endif diff --git a/scenes/protopirate_scene_emulate.c b/scenes/protopirate_scene_emulate.c index 8e99cf1..4114266 100644 --- a/scenes/protopirate_scene_emulate.c +++ b/scenes/protopirate_scene_emulate.c @@ -1,5 +1,6 @@ // scenes/protopirate_scene_emulate.c #include "../protopirate_app_i.h" +#ifdef ENABLE_EMULATE_FEATURE #include "../helpers/protopirate_storage.h" #include "../protocols/protocol_items.h" @@ -735,3 +736,4 @@ void protopirate_scene_emulate_on_exit(void* context) { view_set_input_callback(app->view_about, NULL); view_set_context(app->view_about, NULL); } +#endif From d82c4df166b9ccab5ca1f3a8c550fe104cb35181 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 9 Feb 2026 23:36:27 +0300 Subject: [PATCH 2/2] apply code formatting and make app even smaller --- protocols/ford_v0.c | 28 +- protocols/psa.c | 854 ++++++++++++++++++++++++++------------------ protocols/psa.h | 1 - protocols/vag.c | 20 +- 4 files changed, 553 insertions(+), 350 deletions(-) diff --git a/protocols/ford_v0.c b/protocols/ford_v0.c index fa09de5..d294525 100644 --- a/protocols/ford_v0.c +++ b/protocols/ford_v0.c @@ -57,7 +57,7 @@ typedef struct SubGhzProtocolDecoderFordV0 { uint32_t count; uint8_t bs_magic; } SubGhzProtocolDecoderFordV0; - +#ifdef ENABLE_EMULATE_FEATURE typedef struct SubGhzProtocolEncoderFordV0 { SubGhzProtocolEncoderBase base; SubGhzProtocolBlockEncoder encoder; @@ -71,7 +71,7 @@ typedef struct SubGhzProtocolEncoderFordV0 { uint8_t bs; uint8_t bs_magic; } SubGhzProtocolEncoderFordV0; - +#endif typedef enum { FordV0DecoderStepReset = 0, FordV0DecoderStepPreamble, @@ -92,6 +92,7 @@ static void decode_ford_v0( uint8_t* button, uint32_t* count, uint8_t* bs_magic); +#ifdef ENABLE_EMULATE_FEATURE static void encode_ford_v0( uint8_t header_byte, uint32_t serial, @@ -99,6 +100,7 @@ static void encode_ford_v0( uint32_t count, uint8_t bs, uint64_t* key1); +#endif static bool ford_v0_process_data(SubGhzProtocolDecoderFordV0* instance); // ============================================================================= @@ -116,6 +118,7 @@ const SubGhzProtocolDecoder subghz_protocol_ford_v0_decoder = { .get_string = subghz_protocol_decoder_ford_v0_get_string, }; +#ifdef ENABLE_EMULATE_FEATURE const SubGhzProtocolEncoder subghz_protocol_ford_v0_encoder = { .alloc = subghz_protocol_encoder_ford_v0_alloc, .free = subghz_protocol_encoder_ford_v0_free, @@ -123,6 +126,15 @@ const SubGhzProtocolEncoder subghz_protocol_ford_v0_encoder = { .stop = subghz_protocol_encoder_ford_v0_stop, .yield = subghz_protocol_encoder_ford_v0_yield, }; +#else +const SubGhzProtocolEncoder subghz_protocol_ford_v0_encoder = { + .alloc = NULL, + .free = NULL, + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; +#endif const SubGhzProtocol ford_protocol_v0 = { .name = FORD_PROTOCOL_V0_NAME, @@ -137,13 +149,13 @@ const SubGhzProtocol ford_protocol_v0 = { // BS CALCULATION // BS = (counter_low_byte + 0x6F + (button << 4)) & 0xFF // ============================================================================= - +#ifdef ENABLE_EMULATE_FEATURE static uint8_t ford_v0_calculate_bs(uint32_t count, uint8_t button, uint8_t bs_magic) { //Do the BS calculation, move right the overflow bit if neccesary uint16_t result = ((uint16_t)count & 0xFF) + bs_magic + (button << 4); return (uint8_t)(result - ((result & 0xFF00) ? 0x80 : 0)); } - +#endif // ============================================================================= // CRC FUNCTIONS // ============================================================================= @@ -173,7 +185,7 @@ static uint8_t ford_v0_calculate_crc(uint8_t* buf) { return crc; } - +#ifdef ENABLE_EMULATE_FEATURE static uint8_t ford_v0_calculate_crc_for_tx(uint64_t key1, uint8_t bs) { uint8_t buf[16] = {0}; @@ -186,7 +198,7 @@ static uint8_t ford_v0_calculate_crc_for_tx(uint64_t key1, uint8_t bs) { uint8_t crc = ford_v0_calculate_crc(buf); return crc ^ 0x80; } - +#endif static bool ford_v0_verify_crc(uint64_t key1, uint16_t key2) { uint8_t buf[16] = {0}; @@ -273,7 +285,7 @@ static void decode_ford_v0( // ============================================================================= // ENCODE FUNCTION // ============================================================================= - +#ifdef ENABLE_EMULATE_FEATURE static void encode_ford_v0( uint8_t header_byte, uint32_t serial, @@ -681,7 +693,7 @@ LevelDuration subghz_protocol_encoder_ford_v0_yield(void* context) { return ret; } - +#endif // ============================================================================= // DECODER IMPLEMENTATION // ============================================================================= diff --git a/protocols/psa.c b/protocols/psa.c index f85e926..6e94846 100644 --- a/protocols/psa.c +++ b/protocols/psa.c @@ -9,21 +9,21 @@ static const SubGhzBlockConst subghz_protocol_psa_const = { .min_count_bit_for_found = 128, }; -#define PSA_TE_SHORT_125 0x7d -#define PSA_TE_LONG_250 0xfa -#define PSA_TE_END_1000 1000 -#define PSA_TE_END_500 500 -#define PSA_TOLERANCE_99 99 -#define PSA_TOLERANCE_100 100 -#define PSA_TOLERANCE_49 0x31 -#define PSA_TOLERANCE_50 0x32 +#define PSA_TE_SHORT_125 0x7d +#define PSA_TE_LONG_250 0xfa +#define PSA_TE_END_1000 1000 +#define PSA_TE_END_500 500 +#define PSA_TOLERANCE_99 99 +#define PSA_TOLERANCE_100 100 +#define PSA_TOLERANCE_49 0x31 +#define PSA_TOLERANCE_50 0x32 #define PSA_PATTERN_THRESHOLD_1 0x46 #define PSA_PATTERN_THRESHOLD_2 0x45 -#define PSA_MAX_BITS 0x79 -#define PSA_KEY1_BITS 0x40 -#define PSA_KEY2_BITS 0x50 +#define PSA_MAX_BITS 0x79 +#define PSA_KEY1_BITS 0x40 +#define PSA_KEY2_BITS 0x50 -#define TEA_DELTA 0x9E3779B9U +#define TEA_DELTA 0x9E3779B9U #define TEA_ROUNDS 32 #define PSA_BF1_CONST_U4 0x0E0F5C41U @@ -44,9 +44,9 @@ static const uint32_t PSA_BF2_KEY_SCHEDULE[4] = { }; #define PSA_BF1_START 0x23000000U -#define PSA_BF1_END 0x24000000U +#define PSA_BF1_END 0x24000000U #define PSA_BF2_START 0xF3000000U -#define PSA_BF2_END 0xF4000000U +#define PSA_BF2_END 0xF4000000U typedef enum { PSADecoderState0 = 0, @@ -59,28 +59,28 @@ typedef enum { struct SubGhzProtocolDecoderPSA { SubGhzProtocolDecoderBase base; SubGhzBlockDecoder decoder; - + uint32_t state; uint32_t prev_duration; - + uint32_t decode_data_low; uint32_t decode_data_high; uint8_t decode_count_bit; - + uint32_t seed; uint32_t key1_low; uint32_t key1_high; uint16_t validation_field; uint32_t key2_low; uint32_t key2_high; - + uint32_t status_flag; uint16_t decrypted; uint8_t mode_serialize; - + uint16_t pattern_counter; ManchesterState manchester_state; - + uint8_t decrypted_button; uint32_t decrypted_serial; uint32_t decrypted_counter; @@ -89,11 +89,12 @@ struct SubGhzProtocolDecoderPSA { uint8_t decrypted_type; }; +#ifdef ENABLE_EMULATE_FEATURE struct SubGhzProtocolEncoderPSA { SubGhzProtocolEncoderBase base; SubGhzProtocolBlockEncoder encoder; SubGhzBlockGeneric generic; - + uint32_t key1_low; uint32_t key1_high; uint16_t validation_field; @@ -107,7 +108,7 @@ struct SubGhzProtocolEncoderPSA { uint16_t crc; bool is_running; }; - +#endif const SubGhzProtocolDecoder subghz_protocol_psa_decoder = { .alloc = subghz_protocol_decoder_psa_alloc, .free = subghz_protocol_decoder_psa_free, @@ -118,7 +119,7 @@ const SubGhzProtocolDecoder subghz_protocol_psa_decoder = { .deserialize = subghz_protocol_decoder_psa_deserialize, .get_string = subghz_protocol_decoder_psa_get_string, }; - +#ifdef ENABLE_EMULATE_FEATURE const SubGhzProtocolEncoder subghz_protocol_psa_encoder = { .alloc = subghz_protocol_encoder_psa_alloc, .free = subghz_protocol_encoder_psa_free, @@ -126,7 +127,15 @@ const SubGhzProtocolEncoder subghz_protocol_psa_encoder = { .stop = subghz_protocol_encoder_psa_stop, .yield = subghz_protocol_encoder_psa_yield, }; - +#else +const SubGhzProtocolEncoder subghz_protocol_psa_encoder = { + .alloc = NULL, + .free = NULL, + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; +#endif const SubGhzProtocol psa_protocol = { .name = PSA_PROTOCOL_NAME, .type = SubGhzProtocolTypeDynamic, @@ -136,17 +145,21 @@ const SubGhzProtocol psa_protocol = { .encoder = &subghz_protocol_psa_encoder, }; -static void psa_setup_byte_buffer(uint8_t* buffer, uint32_t key1_low, uint32_t key1_high, uint32_t key2_low); +static void psa_setup_byte_buffer( + uint8_t* buffer, + uint32_t key1_low, + uint32_t key1_high, + uint32_t key2_low); static void psa_calculate_checksum(uint8_t* buffer); static uint8_t psa_calculate_tea_crc(uint32_t v0, uint32_t v1); static void psa_tea_encrypt(uint32_t* v0, uint32_t* v1, const uint32_t* key); static void psa_unpack_tea_result_to_buffer(uint8_t* buffer, uint32_t v0, uint32_t v1); +#ifdef ENABLE_EMULATE_FEATURE static void psa_second_stage_xor_encrypt(uint8_t* buffer) { - uint8_t E6 = buffer[8]; uint8_t E7 = buffer[9]; - + uint8_t P[6]; P[0] = buffer[2]; P[1] = buffer[3]; @@ -154,14 +167,14 @@ static void psa_second_stage_xor_encrypt(uint8_t* buffer) { P[3] = buffer[5]; P[4] = buffer[6]; P[5] = buffer[7]; - + uint8_t E5 = P[5] ^ E7 ^ E6; uint8_t E0 = P[2] ^ E5; uint8_t E2 = P[4] ^ E0; uint8_t E4 = P[3] ^ E2; uint8_t E3 = P[0] ^ E5; uint8_t E1 = P[1] ^ E3; - + buffer[2] = E0; buffer[3] = E1; buffer[4] = E2; @@ -170,15 +183,21 @@ static void psa_second_stage_xor_encrypt(uint8_t* buffer) { buffer[7] = E5; } -static void psa_build_buffer_mode23(SubGhzProtocolEncoderPSA* instance, uint8_t* buffer, uint8_t* preserve_buffer01) { - +static void psa_build_buffer_mode23( + SubGhzProtocolEncoderPSA* instance, + uint8_t* buffer, + uint8_t* preserve_buffer01) { FURI_LOG_I(TAG, "=== MODE 0x23 ENCRYPTION ==="); - FURI_LOG_I(TAG, "Input: Ser:%06lX Cnt:%08lX CRC:%02X Btn:%01X", - (unsigned long)instance->serial, (unsigned long)instance->counter, - (unsigned int)instance->crc, (unsigned int)instance->button); - + FURI_LOG_I( + TAG, + "Input: Ser:%06lX Cnt:%08lX CRC:%02X Btn:%01X", + (unsigned long)instance->serial, + (unsigned long)instance->counter, + (unsigned int)instance->crc, + (unsigned int)instance->button); + memset(buffer, 0, 48); - + buffer[2] = (uint8_t)((instance->serial >> 16) & 0xFF); buffer[3] = (uint8_t)((instance->serial >> 8) & 0xFF); buffer[4] = (uint8_t)(instance->serial & 0xFF); @@ -186,7 +205,7 @@ static void psa_build_buffer_mode23(SubGhzProtocolEncoderPSA* instance, uint8_t* buffer[6] = (uint8_t)(instance->counter & 0xFF); buffer[7] = (uint8_t)(instance->crc & 0xFF); buffer[8] = (uint8_t)(instance->button & 0xF); - + uint8_t original_buffer9 = 0; uint8_t original_buffer8 = 0; bool has_original_key2 = (instance->key2_low != 0); @@ -194,15 +213,28 @@ static void psa_build_buffer_mode23(SubGhzProtocolEncoderPSA* instance, uint8_t* original_buffer9 = (uint8_t)(instance->key2_low & 0xFF); original_buffer8 = (uint8_t)((instance->key2_low >> 8) & 0xFF); buffer[9] = original_buffer9; - FURI_LOG_D(TAG, "Original Key2: 0x%04X, buffer[8]=0x%02X buffer[9]=0x%02X, preserving buffer[9]", - (unsigned int)instance->key2_low, original_buffer8, original_buffer9); + FURI_LOG_D( + TAG, + "Original Key2: 0x%04X, buffer[8]=0x%02X buffer[9]=0x%02X, preserving buffer[9]", + (unsigned int)instance->key2_low, + original_buffer8, + original_buffer9); } else { FURI_LOG_D(TAG, "No original Key2, will find valid buffer[9]"); } - - FURI_LOG_D(TAG, "Plaintext buffer[2-9]: %02X %02X %02X %02X %02X %02X %02X %02X", - buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9]); - + + FURI_LOG_D( + TAG, + "Plaintext buffer[2-9]: %02X %02X %02X %02X %02X %02X %02X %02X", + buffer[2], + buffer[3], + buffer[4], + buffer[5], + buffer[6], + buffer[7], + buffer[8], + buffer[9]); + uint8_t initial_plaintext[6]; initial_plaintext[0] = buffer[2]; initial_plaintext[1] = buffer[3]; @@ -211,14 +243,13 @@ static void psa_build_buffer_mode23(SubGhzProtocolEncoderPSA* instance, uint8_t* initial_plaintext[4] = buffer[6]; initial_plaintext[5] = buffer[7]; uint8_t initial_button = buffer[8] & 0xF; - + bool found = false; uint8_t buffer9_to_use = has_original_key2 ? original_buffer9 : 0; uint8_t buffer9_end = has_original_key2 ? original_buffer9 + 1 : 255; - + for(uint8_t buffer9_try = buffer9_to_use; buffer9_try < buffer9_end && !found; buffer9_try++) { for(uint8_t buffer8_high_try = 0; buffer8_high_try < 16 && !found; buffer8_high_try++) { - buffer[2] = initial_plaintext[0]; buffer[3] = initial_plaintext[1]; buffer[4] = initial_plaintext[2]; @@ -227,24 +258,28 @@ static void psa_build_buffer_mode23(SubGhzProtocolEncoderPSA* instance, uint8_t* buffer[7] = initial_plaintext[5]; buffer[8] = initial_button | (buffer8_high_try << 4); buffer[9] = buffer9_try; - + psa_second_stage_xor_encrypt(buffer); - + psa_calculate_checksum(buffer); uint8_t checksum_after = buffer[11]; uint8_t key2_high_after = checksum_after & 0xF0; - + uint8_t validation = (checksum_after ^ buffer[8]) & 0xF0; if(validation == 0) { buffer[8] = (buffer[8] & 0x0F) | key2_high_after; buffer[13] = buffer[9] ^ buffer[8]; found = true; - FURI_LOG_D(TAG, "Found valid Key2: buffer[8]=0x%02X buffer[9]=0x%02X", buffer[8], buffer[9]); + FURI_LOG_D( + TAG, + "Found valid Key2: buffer[8]=0x%02X buffer[9]=0x%02X", + buffer[8], + buffer[9]); break; } } } - + if(!found) { FURI_LOG_W(TAG, "Brute force failed, using default approach"); buffer[2] = initial_plaintext[0]; @@ -255,7 +290,7 @@ static void psa_build_buffer_mode23(SubGhzProtocolEncoderPSA* instance, uint8_t* buffer[7] = initial_plaintext[5]; buffer[8] = initial_button; buffer[9] = has_original_key2 ? original_buffer9 : 0x23; - + psa_second_stage_xor_encrypt(buffer); psa_calculate_checksum(buffer); uint8_t checksum_after = buffer[11]; @@ -263,110 +298,154 @@ static void psa_build_buffer_mode23(SubGhzProtocolEncoderPSA* instance, uint8_t* buffer[8] = (buffer[8] & 0x0F) | key2_high_after; buffer[13] = buffer[9] ^ buffer[8]; } - + if(preserve_buffer01 != NULL) { buffer[0] = preserve_buffer01[0]; buffer[1] = preserve_buffer01[1]; - FURI_LOG_D(TAG, "Preserved buffer[0-1] from original Key1: %02X %02X", buffer[0], buffer[1]); + FURI_LOG_D( + TAG, "Preserved buffer[0-1] from original Key1: %02X %02X", buffer[0], buffer[1]); } else { buffer[0] = buffer[2] ^ buffer[6]; buffer[1] = buffer[3] ^ buffer[7]; FURI_LOG_D(TAG, "Derived buffer[0-1]: %02X %02X", buffer[0], buffer[1]); } - - FURI_LOG_I(TAG, "Encrypted buffer[0-9]: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", - buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9]); + + FURI_LOG_I( + TAG, + "Encrypted buffer[0-9]: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", + buffer[0], + buffer[1], + buffer[2], + buffer[3], + buffer[4], + buffer[5], + buffer[6], + buffer[7], + buffer[8], + buffer[9]); } -static void psa_build_buffer_mode36(SubGhzProtocolEncoderPSA* instance, uint8_t* buffer, uint8_t* preserve_buffer01) { +static void psa_build_buffer_mode36( + SubGhzProtocolEncoderPSA* instance, + uint8_t* buffer, + uint8_t* preserve_buffer01) { FURI_LOG_I(TAG, "=== MODE 0x36 ENCRYPTION ==="); - FURI_LOG_I(TAG, "Input: Ser:%06lX Cnt:%08lX CRC:%02X Btn:%01X", - (unsigned long)instance->serial, (unsigned long)instance->counter, - (unsigned int)instance->crc, (unsigned int)instance->button); - + FURI_LOG_I( + TAG, + "Input: Ser:%06lX Cnt:%08lX CRC:%02X Btn:%01X", + (unsigned long)instance->serial, + (unsigned long)instance->counter, + (unsigned int)instance->crc, + (unsigned int)instance->button); + memset(buffer, 0, 48); - - uint32_t v0 = ((instance->serial & 0xFFFFFF) << 8) | - ((instance->counter >> 24) & 0xFF); - uint32_t v1 = ((instance->counter & 0xFFFFFF) << 8) | - ((instance->button & 0xF) << 4) | - (instance->crc & 0xFF); - - FURI_LOG_D(TAG, "Packed v0:0x%08lX v1:0x%08lX (before CRC)", (unsigned long)v0, (unsigned long)v1); - + + uint32_t v0 = ((instance->serial & 0xFFFFFF) << 8) | ((instance->counter >> 24) & 0xFF); + uint32_t v1 = ((instance->counter & 0xFFFFFF) << 8) | ((instance->button & 0xF) << 4) | + (instance->crc & 0xFF); + + FURI_LOG_D( + TAG, "Packed v0:0x%08lX v1:0x%08lX (before CRC)", (unsigned long)v0, (unsigned long)v1); + uint8_t crc = psa_calculate_tea_crc(v0, v1); v1 = (v1 & 0xFFFFFF00) | crc; - - FURI_LOG_D(TAG, "Calculated CRC: 0x%02X, v1 after CRC: 0x%08lX", (unsigned int)crc, (unsigned long)v1); - + + FURI_LOG_D( + TAG, "Calculated CRC: 0x%02X, v1 after CRC: 0x%08lX", (unsigned int)crc, (unsigned long)v1); + uint32_t bf_counter = PSA_BF1_START | (instance->serial & 0xFFFFFF); FURI_LOG_D(TAG, "BF counter: 0x%08lX (BF1_START | serial)", (unsigned long)bf_counter); - + uint32_t working_key[4]; - + uint32_t wk2 = PSA_BF1_CONST_U4; uint32_t wk3 = bf_counter; psa_tea_encrypt(&wk2, &wk3, PSA_BF1_KEY_SCHEDULE); - + uint32_t wk0 = (bf_counter << 8) | 0x0E; uint32_t wk1 = PSA_BF1_CONST_U5; psa_tea_encrypt(&wk0, &wk1, PSA_BF1_KEY_SCHEDULE); - + working_key[0] = wk0; working_key[1] = wk1; working_key[2] = wk2; working_key[3] = wk3; - + psa_tea_encrypt(&v0, &v1, working_key); - + FURI_LOG_D(TAG, "TEA encrypted v0:0x%08lX v1:0x%08lX", (unsigned long)v0, (unsigned long)v1); - FURI_LOG_D(TAG, "Working key: %08lX %08lX %08lX %08lX", - (unsigned long)working_key[0], (unsigned long)working_key[1], - (unsigned long)working_key[2], (unsigned long)working_key[3]); - + FURI_LOG_D( + TAG, + "Working key: %08lX %08lX %08lX %08lX", + (unsigned long)working_key[0], + (unsigned long)working_key[1], + (unsigned long)working_key[2], + (unsigned long)working_key[3]); + psa_unpack_tea_result_to_buffer(buffer, v0, v1); - + if(preserve_buffer01 != NULL) { buffer[0] = preserve_buffer01[0]; buffer[1] = preserve_buffer01[1]; - FURI_LOG_D(TAG, "Preserved buffer[0-1] from original Key1: %02X %02X", buffer[0], buffer[1]); + FURI_LOG_D( + TAG, "Preserved buffer[0-1] from original Key1: %02X %02X", buffer[0], buffer[1]); } else { buffer[0] = buffer[2] ^ buffer[6]; buffer[1] = buffer[3] ^ buffer[7]; FURI_LOG_D(TAG, "Derived buffer[0-1]: %02X %02X", buffer[0], buffer[1]); } - - FURI_LOG_I(TAG, "Encrypted buffer[0-9]: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", - buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9]); + + FURI_LOG_I( + TAG, + "Encrypted buffer[0-9]: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", + buffer[0], + buffer[1], + buffer[2], + buffer[3], + buffer[4], + buffer[5], + buffer[6], + buffer[7], + buffer[8], + buffer[9]); } static void psa_encoder_build_upload(SubGhzProtocolEncoderPSA* instance) { furi_assert(instance); - + FURI_LOG_I(TAG, "=== ENCODER BUILD UPLOAD ==="); - FURI_LOG_I(TAG, "Mode: 0x%02X, Serial:%06lX Counter:%08lX CRC:%02X Button:%01X", - (unsigned int)instance->mode, (unsigned long)instance->serial, - (unsigned long)instance->counter, (unsigned int)instance->crc, + FURI_LOG_I( + TAG, + "Mode: 0x%02X, Serial:%06lX Counter:%08lX CRC:%02X Button:%01X", + (unsigned int)instance->mode, + (unsigned long)instance->serial, + (unsigned long)instance->counter, + (unsigned int)instance->crc, (unsigned int)instance->button); - + uint8_t buffer[48] = {0}; - + uint8_t preserve_buffer01[2] = {0}; uint8_t* preserve_ptr = NULL; - + if(instance->key1_low != 0 || instance->key1_high != 0) { uint8_t orig_buffer[48] = {0}; - psa_setup_byte_buffer(orig_buffer, instance->key1_low, instance->key1_high, instance->key2_low); + psa_setup_byte_buffer( + orig_buffer, instance->key1_low, instance->key1_high, instance->key2_low); preserve_buffer01[0] = orig_buffer[0]; preserve_buffer01[1] = orig_buffer[1]; preserve_ptr = preserve_buffer01; - FURI_LOG_D(TAG, "Original Key1: %08lX%08lX, preserving buffer[0-1]: %02X %02X", - (unsigned long)instance->key1_high, (unsigned long)instance->key1_low, - preserve_buffer01[0], preserve_buffer01[1]); + FURI_LOG_D( + TAG, + "Original Key1: %08lX%08lX, preserving buffer[0-1]: %02X %02X", + (unsigned long)instance->key1_high, + (unsigned long)instance->key1_low, + preserve_buffer01[0], + preserve_buffer01[1]); } else { FURI_LOG_D(TAG, "No original Key1, will derive buffer[0-1]"); } - + if(instance->mode == 0x23) { psa_build_buffer_mode23(instance, buffer, preserve_ptr); } else if(instance->mode == 0x36) { @@ -375,33 +454,33 @@ static void psa_encoder_build_upload(SubGhzProtocolEncoderPSA* instance) { FURI_LOG_E(TAG, "Unknown mode: 0x%02X", instance->mode); return; } - + uint32_t key1_high = ((uint32_t)buffer[0] << 24) | ((uint32_t)buffer[1] << 16) | ((uint32_t)buffer[2] << 8) | (uint32_t)buffer[3]; uint32_t key1_low = ((uint32_t)buffer[4] << 24) | ((uint32_t)buffer[5] << 16) | ((uint32_t)buffer[6] << 8) | (uint32_t)buffer[7]; uint16_t validation_field = ((uint16_t)buffer[8] << 8) | (uint16_t)buffer[9]; - + FURI_LOG_I(TAG, "=== ENCRYPTED KEYS ==="); FURI_LOG_I(TAG, "Key1: %08lX%08lX", (unsigned long)key1_high, (unsigned long)key1_low); FURI_LOG_I(TAG, "Key2: %04X", (unsigned int)validation_field); - + size_t index = 0; uint32_t te = PSA_TE_LONG_250; - + for(int i = 0; i < 80; i++) { if(index >= instance->encoder.size_upload - 2) break; instance->encoder.upload[index++] = level_duration_make(true, te); instance->encoder.upload[index++] = level_duration_make(false, te); } - + uint32_t te_long_transition = subghz_protocol_psa_const.te_long; if(index < instance->encoder.size_upload - 3) { instance->encoder.upload[index++] = level_duration_make(false, te); instance->encoder.upload[index++] = level_duration_make(true, te_long_transition); instance->encoder.upload[index++] = level_duration_make(false, te); } - + uint64_t key1_data = ((uint64_t)key1_high << 32) | key1_low; for(int bit = 63; bit >= 0; bit--) { if(index >= instance->encoder.size_upload - 2) break; @@ -414,7 +493,7 @@ static void psa_encoder_build_upload(SubGhzProtocolEncoderPSA* instance) { instance->encoder.upload[index++] = level_duration_make(true, te); } } - + for(int bit = 15; bit >= 0; bit--) { if(index >= instance->encoder.size_upload - 2) break; bool bit_value = (validation_field >> bit) & 1; @@ -426,22 +505,29 @@ static void psa_encoder_build_upload(SubGhzProtocolEncoderPSA* instance) { instance->encoder.upload[index++] = level_duration_make(true, te); } } - + uint32_t end_duration = PSA_TE_END_1000; if(index < instance->encoder.size_upload - 1) { instance->encoder.upload[index++] = level_duration_make(true, end_duration); instance->encoder.upload[index++] = level_duration_make(false, end_duration); } - + instance->encoder.size_upload = index; instance->encoder.front = 0; instance->encoder.repeat = 10; - + FURI_LOG_I(TAG, "=== TRANSMISSION PARAMETERS ==="); - FURI_LOG_I(TAG, "TE: %lu, TE_LONG_TRANS: %lu, TE_END: %lu", - (unsigned long)te, (unsigned long)te_long_transition, (unsigned long)end_duration); - FURI_LOG_I(TAG, "Upload size: %zu levels, Repeat: %d", - instance->encoder.size_upload, instance->encoder.repeat); + FURI_LOG_I( + TAG, + "TE: %lu, TE_LONG_TRANS: %lu, TE_END: %lu", + (unsigned long)te, + (unsigned long)te_long_transition, + (unsigned long)end_duration); + FURI_LOG_I( + TAG, + "Upload size: %zu levels, Repeat: %d", + instance->encoder.size_upload, + instance->encoder.repeat); FURI_LOG_I(TAG, "Key1 data (64-bit): %016llX", (unsigned long long)key1_data); FURI_LOG_I(TAG, "Key2 data (16-bit): %04X", (unsigned int)validation_field); FURI_LOG_I(TAG, "=== END ENCODER BUILD ==="); @@ -450,12 +536,12 @@ static void psa_encoder_build_upload(SubGhzProtocolEncoderPSA* instance) { void* subghz_protocol_encoder_psa_alloc(SubGhzEnvironment* environment) { UNUSED(environment); SubGhzProtocolEncoderPSA* instance = malloc(sizeof(SubGhzProtocolEncoderPSA)); - + if(instance) { memset(instance, 0, sizeof(SubGhzProtocolEncoderPSA)); instance->base.protocol = &psa_protocol; instance->generic.protocol_name = instance->base.protocol->name; - + instance->encoder.size_upload = 600; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); instance->encoder.repeat = 10; @@ -463,14 +549,14 @@ void* subghz_protocol_encoder_psa_alloc(SubGhzEnvironment* environment) { instance->encoder.is_running = false; instance->is_running = false; } - + return instance; } void subghz_protocol_encoder_psa_free(void* context) { furi_assert(context); SubGhzProtocolEncoderPSA* instance = context; - + if(instance->encoder.upload) { free(instance->encoder.upload); } @@ -481,22 +567,24 @@ SubGhzProtocolStatus subghz_protocol_encoder_psa_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderPSA* instance = context; - + FURI_LOG_I(TAG, "=== ENCODER DESERIALIZE ==="); - + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; FuriString* temp_str = furi_string_alloc(); uint8_t hex_buffer[8]; - + do { if(!flipper_format_read_string(flipper_format, "Key", temp_str)) { if(!flipper_format_read_hex(flipper_format, "Key1", hex_buffer, 8)) { FURI_LOG_E(TAG, "Failed to read Key1"); break; } - instance->key1_low = ((uint32_t)hex_buffer[0] << 24) | ((uint32_t)hex_buffer[1] << 16) | - ((uint32_t)hex_buffer[2] << 8) | (uint32_t)hex_buffer[3]; - instance->key1_high = ((uint32_t)hex_buffer[4] << 24) | ((uint32_t)hex_buffer[5] << 16) | + instance->key1_low = ((uint32_t)hex_buffer[0] << 24) | + ((uint32_t)hex_buffer[1] << 16) | ((uint32_t)hex_buffer[2] << 8) | + (uint32_t)hex_buffer[3]; + instance->key1_high = ((uint32_t)hex_buffer[4] << 24) | + ((uint32_t)hex_buffer[5] << 16) | ((uint32_t)hex_buffer[6] << 8) | (uint32_t)hex_buffer[7]; } else { const char* key_str = furi_string_get_cstr(temp_str); @@ -520,7 +608,7 @@ SubGhzProtocolStatus instance->key1_low = (uint32_t)(key1 & 0xFFFFFFFF); instance->key1_high = (uint32_t)((key1 >> 32) & 0xFFFFFFFF); } - + flipper_format_rewind(flipper_format); if(flipper_format_read_string(flipper_format, "Key_2", temp_str)) { const char* key2_str = furi_string_get_cstr(temp_str); @@ -547,9 +635,9 @@ SubGhzProtocolStatus uint32_t val_field_val; if(flipper_format_read_uint32(flipper_format, "ValidationField", &val_field_val, 1)) { instance->validation_field = (uint16_t)(val_field_val & 0xFFFF); - instance->key2_low = instance->validation_field; - } else { - uint8_t val_field[2]; + instance->key2_low = instance->validation_field; + } else { + uint8_t val_field[2]; if(flipper_format_read_hex(flipper_format, "ValidationField", val_field, 2)) { instance->validation_field = ((uint16_t)val_field[0] << 8) | val_field[1]; instance->key2_low = instance->validation_field; @@ -559,19 +647,19 @@ SubGhzProtocolStatus } } } - + flipper_format_rewind(flipper_format); if(!flipper_format_read_uint32(flipper_format, "Serial", &instance->serial, 1)) { FURI_LOG_E(TAG, "Serial not found"); break; } - + flipper_format_rewind(flipper_format); if(!flipper_format_read_uint32(flipper_format, "Cnt", &instance->counter, 1)) { FURI_LOG_E(TAG, "Counter not found"); break; } - + flipper_format_rewind(flipper_format); uint32_t btn_val = 0; if(!flipper_format_read_uint32(flipper_format, "Btn", &btn_val, 1)) { @@ -579,7 +667,7 @@ SubGhzProtocolStatus break; } instance->button = (uint8_t)(btn_val & 0xFF); - + flipper_format_rewind(flipper_format); uint32_t type_val = 0; if(!flipper_format_read_uint32(flipper_format, "Type", &type_val, 1)) { @@ -587,7 +675,7 @@ SubGhzProtocolStatus break; } instance->type = (uint8_t)(type_val & 0xFF); - + flipper_format_rewind(flipper_format); uint32_t crc_val = 0; if(!flipper_format_read_uint32(flipper_format, "CRC", &crc_val, 1)) { @@ -595,7 +683,7 @@ SubGhzProtocolStatus break; } instance->crc = (uint16_t)(crc_val & 0xFFFF); - + flipper_format_rewind(flipper_format); uint32_t seed_val = 0; if(!flipper_format_read_uint32(flipper_format, "Seed", &seed_val, 1)) { @@ -603,7 +691,7 @@ SubGhzProtocolStatus break; } instance->seed = (uint8_t)(seed_val & 0xFF); - + instance->mode = instance->type; if(instance->mode == 0x23 || instance->mode == 0) { instance->mode = 0x23; @@ -612,21 +700,33 @@ SubGhzProtocolStatus } else { instance->mode = 0x23; } - + FURI_LOG_I(TAG, "=== LOADED VALUES ==="); - FURI_LOG_I(TAG, "Key1: %08lX%08lX", (unsigned long)instance->key1_high, (unsigned long)instance->key1_low); - FURI_LOG_I(TAG, "Key2: %04X (validation_field: %04X)", - (unsigned int)instance->key2_low, (unsigned int)instance->validation_field); - FURI_LOG_I(TAG, "Serial: %06lX, Counter: %08lX, CRC: %02X, Button: %01X, Type/Mode: 0x%02X", - (unsigned long)instance->serial, (unsigned long)instance->counter, - (unsigned int)instance->crc, (unsigned int)instance->button, (unsigned int)instance->mode); - + FURI_LOG_I( + TAG, + "Key1: %08lX%08lX", + (unsigned long)instance->key1_high, + (unsigned long)instance->key1_low); + FURI_LOG_I( + TAG, + "Key2: %04X (validation_field: %04X)", + (unsigned int)instance->key2_low, + (unsigned int)instance->validation_field); + FURI_LOG_I( + TAG, + "Serial: %06lX, Counter: %08lX, CRC: %02X, Button: %01X, Type/Mode: 0x%02X", + (unsigned long)instance->serial, + (unsigned long)instance->counter, + (unsigned int)instance->crc, + (unsigned int)instance->button, + (unsigned int)instance->mode); + psa_encoder_build_upload(instance); - + instance->is_running = true; ret = SubGhzProtocolStatusOk; } while(false); - + furi_string_free(temp_str); return ret; } @@ -641,15 +741,15 @@ void subghz_protocol_encoder_psa_stop(void* context) { LevelDuration subghz_protocol_encoder_psa_yield(void* context) { furi_assert(context); SubGhzProtocolEncoderPSA* instance = context; - + if(!instance->is_running || instance->encoder.size_upload == 0) { instance->is_running = false; return level_duration_reset(); } - + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; instance->encoder.front++; - + if(instance->encoder.front >= instance->encoder.size_upload) { instance->encoder.front = 0; instance->encoder.repeat--; @@ -657,10 +757,10 @@ LevelDuration subghz_protocol_encoder_psa_yield(void* context) { instance->is_running = false; } } - + return ret; } - +#endif static uint32_t psa_abs_diff(uint32_t a, uint32_t b) { if(a < b) { return b - a; @@ -669,7 +769,11 @@ static uint32_t psa_abs_diff(uint32_t a, uint32_t b) { } } -static void psa_setup_byte_buffer(uint8_t* buffer, uint32_t key1_low, uint32_t key1_high, uint32_t key2_low) { +static void psa_setup_byte_buffer( + uint8_t* buffer, + uint32_t key1_low, + uint32_t key1_high, + uint32_t key2_low) { for(int i = 0; i < 8; i++) { int shift = i * 8; uint8_t byte_val; @@ -741,15 +845,14 @@ static void psa_tea_decrypt(uint32_t* v0, uint32_t* v1, const uint32_t* key) { } static void psa_prepare_tea_data(uint8_t* buffer, uint32_t* w0, uint32_t* w1) { - *w0 = ((uint32_t)buffer[3] << 16) | ((uint32_t)buffer[2] << 24) | - ((uint32_t)buffer[4] << 8) | (uint32_t)buffer[5]; - *w1 = ((uint32_t)buffer[7] << 16) | ((uint32_t)buffer[6] << 24) | - ((uint32_t)buffer[8] << 8) | (uint32_t)buffer[9]; + *w0 = ((uint32_t)buffer[3] << 16) | ((uint32_t)buffer[2] << 24) | ((uint32_t)buffer[4] << 8) | + (uint32_t)buffer[5]; + *w1 = ((uint32_t)buffer[7] << 16) | ((uint32_t)buffer[6] << 24) | ((uint32_t)buffer[8] << 8) | + (uint32_t)buffer[9]; } static uint8_t psa_calculate_tea_crc(uint32_t v0, uint32_t v1) { - uint32_t crc = ((v0 >> 24) & 0xFF) + ((v0 >> 16) & 0xFF) + - ((v0 >> 8) & 0xFF) + (v0 & 0xFF); + uint32_t crc = ((v0 >> 24) & 0xFF) + ((v0 >> 16) & 0xFF) + ((v0 >> 8) & 0xFF) + (v0 & 0xFF); crc += ((v1 >> 24) & 0xFF) + ((v1 >> 16) & 0xFF) + ((v1 >> 8) & 0xFF); return (uint8_t)(crc & 0xFF); } @@ -783,7 +886,8 @@ static void psa_unpack_tea_result_to_buffer(uint8_t* buffer, uint32_t v0, uint32 static void psa_extract_fields_mode23(uint8_t* buffer, SubGhzProtocolDecoderPSA* instance) { instance->decrypted_button = buffer[8] & 0xF; - instance->decrypted_serial = ((uint32_t)buffer[3] << 8) | ((uint32_t)buffer[2] << 16) | (uint32_t)buffer[4]; + instance->decrypted_serial = ((uint32_t)buffer[3] << 8) | ((uint32_t)buffer[2] << 16) | + (uint32_t)buffer[4]; instance->decrypted_counter = (uint32_t)buffer[6] | ((uint32_t)buffer[5] << 8); instance->decrypted_crc = (uint16_t)buffer[7]; instance->decrypted_type = 0x23; @@ -792,30 +896,35 @@ static void psa_extract_fields_mode23(uint8_t* buffer, SubGhzProtocolDecoderPSA* static void psa_extract_fields_mode36(uint8_t* buffer, SubGhzProtocolDecoderPSA* instance) { instance->decrypted_button = (buffer[5] >> 4) & 0xF; - instance->decrypted_serial = ((uint32_t)buffer[3] << 8) | ((uint32_t)buffer[2] << 16) | (uint32_t)buffer[4]; - instance->decrypted_counter = ((uint32_t)buffer[7] << 8) | ((uint32_t)buffer[6] << 16) | - (uint32_t)buffer[8] | (((uint32_t)buffer[5] & 0xF) << 24); + instance->decrypted_serial = ((uint32_t)buffer[3] << 8) | ((uint32_t)buffer[2] << 16) | + (uint32_t)buffer[4]; + instance->decrypted_counter = ((uint32_t)buffer[7] << 8) | ((uint32_t)buffer[6] << 16) | + (uint32_t)buffer[8] | (((uint32_t)buffer[5] & 0xF) << 24); instance->decrypted_crc = (uint16_t)buffer[9]; instance->decrypted_type = 0x36; instance->decrypted_seed = instance->decrypted_serial; } -static bool psa_brute_force_decrypt_bf1(SubGhzProtocolDecoderPSA* instance, uint8_t* buffer, uint32_t w0, uint32_t w1) { +static bool psa_brute_force_decrypt_bf1( + SubGhzProtocolDecoderPSA* instance, + uint8_t* buffer, + uint32_t w0, + uint32_t w1) { for(uint32_t counter = PSA_BF1_START; counter < PSA_BF1_END; counter++) { uint32_t wk2 = PSA_BF1_CONST_U4; uint32_t wk3 = counter; psa_tea_encrypt(&wk2, &wk3, PSA_BF1_KEY_SCHEDULE); - + uint32_t wk0 = (counter << 8) | 0x0E; uint32_t wk1 = PSA_BF1_CONST_U5; psa_tea_encrypt(&wk0, &wk1, PSA_BF1_KEY_SCHEDULE); - + uint32_t working_key[4] = {wk0, wk1, wk2, wk3}; - + uint32_t dec_v0 = w0; uint32_t dec_v1 = w1; psa_tea_decrypt(&dec_v0, &dec_v1, working_key); - + if((counter & 0xFFFFFF) == (dec_v0 >> 8)) { uint8_t crc = psa_calculate_tea_crc(dec_v0, dec_v1); if(crc == (dec_v1 & 0xFF)) { @@ -828,7 +937,11 @@ static bool psa_brute_force_decrypt_bf1(SubGhzProtocolDecoderPSA* instance, uint return false; } -static bool psa_brute_force_decrypt_bf2(SubGhzProtocolDecoderPSA* instance, uint8_t* buffer, uint32_t w0, uint32_t w1) { +static bool psa_brute_force_decrypt_bf2( + SubGhzProtocolDecoderPSA* instance, + uint8_t* buffer, + uint32_t w0, + uint32_t w1) { for(uint32_t counter = PSA_BF2_START; counter < PSA_BF2_END; counter++) { uint32_t working_key[4] = { PSA_BF2_KEY_SCHEDULE[0] ^ counter, @@ -836,14 +949,14 @@ static bool psa_brute_force_decrypt_bf2(SubGhzProtocolDecoderPSA* instance, uint PSA_BF2_KEY_SCHEDULE[2] ^ counter, PSA_BF2_KEY_SCHEDULE[3] ^ counter, }; - + uint32_t dec_v0 = w0; uint32_t dec_v1 = w1; psa_tea_decrypt(&dec_v0, &dec_v1, working_key); - + if((counter & 0xFFFFFF) == (dec_v0 >> 8)) { psa_unpack_tea_result_to_buffer(buffer, dec_v0, dec_v1); - + uint8_t crc_buffer[6] = { (uint8_t)((dec_v0 >> 24) & 0xFF), (uint8_t)((dec_v0 >> 8) & 0xFF), @@ -854,7 +967,7 @@ static bool psa_brute_force_decrypt_bf2(SubGhzProtocolDecoderPSA* instance, uint }; uint16_t crc16 = psa_calculate_crc16_bf2(crc_buffer, 6); uint16_t expected_crc = (((dec_v1 >> 16) & 0xFF) << 8) | (dec_v1 & 0xFF); - + if(crc16 == expected_crc) { psa_extract_fields_mode36(buffer, instance); return true; @@ -868,11 +981,15 @@ static bool psa_direct_xor_decrypt(SubGhzProtocolDecoderPSA* instance, uint8_t* psa_calculate_checksum(buffer); uint8_t checksum = buffer[11]; uint8_t key2_high = buffer[8]; - + uint8_t validation_result = (checksum ^ key2_high) & 0xF0; - FURI_LOG_D(TAG, "Direct XOR validation: checksum=0x%02X, key2_high=0x%02X, result=0x%02X", - checksum, key2_high, validation_result); - + FURI_LOG_D( + TAG, + "Direct XOR validation: checksum=0x%02X, key2_high=0x%02X, result=0x%02X", + checksum, + key2_high, + validation_result); + if(validation_result == 0) { buffer[13] = buffer[9] ^ buffer[8]; psa_second_stage_xor_decrypt(buffer); @@ -880,34 +997,41 @@ static bool psa_direct_xor_decrypt(SubGhzProtocolDecoderPSA* instance, uint8_t* FURI_LOG_D(TAG, "Direct XOR decryption completed"); return true; } - FURI_LOG_D(TAG, "Direct XOR validation FAILED: (checksum ^ key2_high) & 0xF0 = 0x%02X (expected 0x00)", + FURI_LOG_D( + TAG, + "Direct XOR validation FAILED: (checksum ^ key2_high) & 0xF0 = 0x%02X (expected 0x00)", validation_result); return false; } static void psa_decrypt_router(SubGhzProtocolDecoderPSA* instance) { FURI_LOG_I(TAG, "=== DECRYPTION ROUTER CALLED ==="); - FURI_LOG_I(TAG, "Key1:%08lX%08lX Key2:%04X mode_serialize:0x%02X decrypted:0x%02X", - (unsigned long)instance->key1_high, (unsigned long)instance->key1_low, - (unsigned int)(instance->key2_low & 0xFFFF), - (unsigned int)instance->mode_serialize, (unsigned int)instance->decrypted); - + FURI_LOG_I( + TAG, + "Key1:%08lX%08lX Key2:%04X mode_serialize:0x%02X decrypted:0x%02X", + (unsigned long)instance->key1_high, + (unsigned long)instance->key1_low, + (unsigned int)(instance->key2_low & 0xFFFF), + (unsigned int)instance->mode_serialize, + (unsigned int)instance->decrypted); + uint8_t buffer[48] = {0}; - + psa_setup_byte_buffer(buffer, instance->key1_low, instance->key1_high, instance->key2_low); - + uint8_t mode = instance->mode_serialize; - + if(mode == 1 || mode == 2) { if(psa_direct_xor_decrypt(instance, buffer)) { mode = 0x23; FURI_LOG_I(TAG, "Converted mode %d -> 0x23 (Direct XOR)", instance->mode_serialize); } else { mode = 0x36; - FURI_LOG_I(TAG, "Converted mode %d -> 0x36 (TEA Brute Force)", instance->mode_serialize); + FURI_LOG_I( + TAG, "Converted mode %d -> 0x36 (TEA Brute Force)", instance->mode_serialize); } } - + if(mode == 0x23) { FURI_LOG_I(TAG, "Attempting Direct XOR decryption (Type 0x23)"); if(psa_direct_xor_decrypt(instance, buffer)) { @@ -919,27 +1043,34 @@ static void psa_decrypt_router(SubGhzProtocolDecoderPSA* instance) { FURI_LOG_W(TAG, "Direct XOR decryption FAILED"); } else if(mode == 0x36) { FURI_LOG_I(TAG, "Attempting TEA brute force decryption (Type 0x36)"); - + uint32_t w0, w1; psa_prepare_tea_data(buffer, &w0, &w1); - FURI_LOG_D(TAG, "Prepared TEA data: w0=0x%08lX w1=0x%08lX", (unsigned long)w0, (unsigned long)w1); - + FURI_LOG_D( + TAG, "Prepared TEA data: w0=0x%08lX w1=0x%08lX", (unsigned long)w0, (unsigned long)w1); + FURI_LOG_I(TAG, "Starting BF1 brute force..."); if(psa_brute_force_decrypt_bf1(instance, buffer, w0, w1)) { instance->mode_serialize = 0x36; instance->decrypted = 0x50; - FURI_LOG_I(TAG, "BF1 brute force SUCCESS - Btn:%02X Ser:%06lX Cnt:%08lX", - (unsigned int)instance->decrypted_button, - (unsigned long)instance->decrypted_serial, (unsigned long)instance->decrypted_counter); + FURI_LOG_I( + TAG, + "BF1 brute force SUCCESS - Btn:%02X Ser:%06lX Cnt:%08lX", + (unsigned int)instance->decrypted_button, + (unsigned long)instance->decrypted_serial, + (unsigned long)instance->decrypted_counter); return; } FURI_LOG_W(TAG, "BF1 brute force FAILED - trying BF2..."); if(psa_brute_force_decrypt_bf2(instance, buffer, w0, w1)) { instance->mode_serialize = 0x36; instance->decrypted = 0x50; - FURI_LOG_I(TAG, "BF2 brute force SUCCESS - Btn:%02X Ser:%06lX Cnt:%08lX", - (unsigned int)instance->decrypted_button, - (unsigned long)instance->decrypted_serial, (unsigned long)instance->decrypted_counter); + FURI_LOG_I( + TAG, + "BF2 brute force SUCCESS - Btn:%02X Ser:%06lX Cnt:%08lX", + (unsigned int)instance->decrypted_button, + (unsigned long)instance->decrypted_serial, + (unsigned long)instance->decrypted_counter); return; } FURI_LOG_E(TAG, "Both BF1 and BF2 brute force FAILED"); @@ -951,11 +1082,11 @@ static void psa_decrypt_router(SubGhzProtocolDecoderPSA* instance) { FURI_LOG_I(TAG, "Direct XOR decryption SUCCESS"); return; } - + FURI_LOG_I(TAG, "Direct XOR failed - trying brute force..."); uint32_t w0, w1; psa_prepare_tea_data(buffer, &w0, &w1); - + if(psa_brute_force_decrypt_bf1(instance, buffer, w0, w1)) { instance->mode_serialize = 0x36; instance->decrypted = 0x50; @@ -969,7 +1100,7 @@ static void psa_decrypt_router(SubGhzProtocolDecoderPSA* instance) { return; } } - + FURI_LOG_E(TAG, "=== ALL DECRYPTION ATTEMPTS FAILED ==="); instance->decrypted = 0x00; } @@ -1017,19 +1148,19 @@ void subghz_protocol_decoder_psa_reset(void* context) { void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t duration) { furi_assert(context); SubGhzProtocolDecoderPSA* instance = context; - + uint32_t tolerance; uint32_t new_state = instance->state; uint32_t prev_dur = instance->prev_duration; uint32_t te_short = subghz_protocol_psa_const.te_short; uint32_t te_long = subghz_protocol_psa_const.te_long; - + switch(instance->state) { case PSADecoderState0: if(!level) { return; } - + if(duration < te_short) { tolerance = te_short - duration; if(tolerance > PSA_TOLERANCE_99) { @@ -1055,7 +1186,7 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } new_state = PSADecoderState1; } - + instance->decode_data_low = 0; instance->decode_data_high = 0; instance->pattern_counter = 0; @@ -1069,15 +1200,15 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati instance->decrypted_crc = 0; instance->decrypted_seed = 0; instance->decrypted = 0x00; - manchester_advance(instance->manchester_state, ManchesterEventReset, - &instance->manchester_state, NULL); + manchester_advance( + instance->manchester_state, ManchesterEventReset, &instance->manchester_state, NULL); break; - + case PSADecoderState1: if(level) { return; } - + if(duration < te_short) { tolerance = te_short - duration; if(tolerance < PSA_TOLERANCE_100) { @@ -1106,14 +1237,19 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } if(long_diff < 100) { if(instance->pattern_counter > PSA_PATTERN_THRESHOLD_1) { - FURI_LOG_I(TAG, "[State1->State2] Transition detected with pattern_cnt=%lu", - (unsigned long)instance->pattern_counter); + FURI_LOG_I( + TAG, + "[State1->State2] Transition detected with pattern_cnt=%lu", + (unsigned long)instance->pattern_counter); new_state = PSADecoderState2; instance->decode_data_low = 0; instance->decode_data_high = 0; instance->decode_count_bit = 0; - manchester_advance(instance->manchester_state, ManchesterEventReset, - &instance->manchester_state, NULL); + manchester_advance( + instance->manchester_state, + ManchesterEventReset, + &instance->manchester_state, + NULL); instance->state = new_state; } instance->pattern_counter = 0; @@ -1122,17 +1258,17 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } } } - + new_state = PSADecoderState0; instance->pattern_counter = 0; break; - + case PSADecoderState2: if(instance->decode_count_bit >= PSA_MAX_BITS) { new_state = PSADecoderState0; break; } - + if(level && instance->decode_count_bit == PSA_KEY2_BITS) { if(duration >= 800) { uint32_t end_diff; @@ -1150,10 +1286,10 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati instance->state = new_state; return; } - + uint32_t new_key2_low = instance->decode_data_low; instance->validation_field = (uint16_t)(instance->decode_data_low & 0xFFFF); - + instance->decrypted_type = 0; instance->decrypted_button = 0; instance->decrypted_serial = 0; @@ -1161,33 +1297,44 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati instance->decrypted_crc = 0; instance->decrypted_seed = 0; instance->decrypted = 0x00; - + instance->key2_low = new_key2_low; instance->key2_high = instance->decode_data_high; instance->mode_serialize = 1; instance->status_flag = 0x80; - - FURI_LOG_I(TAG, "Signal decoded - Key1:%08lX%08lX Key2:%04X ValField:%04X", - (unsigned long)instance->key1_high, (unsigned long)instance->key1_low, - (unsigned int)(instance->key2_low & 0xFFFF), (unsigned int)instance->validation_field); - - uint8_t buffer[48] = {0}; - psa_setup_byte_buffer(buffer, instance->key1_low, instance->key1_high, instance->key2_low); - if(psa_direct_xor_decrypt(instance, buffer)) { - instance->mode_serialize = 0x23; - instance->decrypted = 0x50; - FURI_LOG_I(TAG, "Direct XOR decryption SUCCESS - Type:0x23 Btn:%02X Ser:%06lX Cnt:%08lX", - (unsigned int)instance->decrypted_button, (unsigned long)instance->decrypted_serial, (unsigned long)instance->decrypted_counter); - } else { - instance->decrypted = 0x00; - instance->mode_serialize = 0x36; - FURI_LOG_I(TAG, "Direct XOR decryption FAILED - marked for brute force (Type:0x36) - deferred to get_string"); - } - - if(instance->base.callback) { - instance->base.callback(&instance->base, instance->base.context); - } - + + FURI_LOG_I( + TAG, + "Signal decoded - Key1:%08lX%08lX Key2:%04X ValField:%04X", + (unsigned long)instance->key1_high, + (unsigned long)instance->key1_low, + (unsigned int)(instance->key2_low & 0xFFFF), + (unsigned int)instance->validation_field); + + uint8_t buffer[48] = {0}; + psa_setup_byte_buffer( + buffer, instance->key1_low, instance->key1_high, instance->key2_low); + if(psa_direct_xor_decrypt(instance, buffer)) { + instance->mode_serialize = 0x23; + instance->decrypted = 0x50; + FURI_LOG_I( + TAG, + "Direct XOR decryption SUCCESS - Type:0x23 Btn:%02X Ser:%06lX Cnt:%08lX", + (unsigned int)instance->decrypted_button, + (unsigned long)instance->decrypted_serial, + (unsigned long)instance->decrypted_counter); + } else { + instance->decrypted = 0x00; + instance->mode_serialize = 0x36; + FURI_LOG_I( + TAG, + "Direct XOR decryption FAILED - marked for brute force (Type:0x36) - deferred to get_string"); + } + + if(instance->base.callback) { + instance->base.callback(&instance->base, instance->base.context); + } + instance->decode_data_low = 0; instance->decode_data_high = 0; instance->decode_count_bit = 0; @@ -1197,10 +1344,10 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } } } - + uint8_t manchester_input = 0; bool should_process = false; - + if(duration < te_short) { tolerance = te_short - duration; if(tolerance >= PSA_TOLERANCE_100) { @@ -1216,7 +1363,7 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } else if(duration < te_long) { uint32_t diff_from_250 = duration - te_short; uint32_t diff_from_500 = te_long - duration; - + if(diff_from_500 < 150 || diff_from_250 > diff_from_500) { if(level == 0) { manchester_input = 6; @@ -1266,19 +1413,21 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } } } - + if(should_process && instance->decode_count_bit < PSA_KEY2_BITS) { bool decoded_bit = false; - - if(manchester_advance(instance->manchester_state, - (ManchesterEvent)manchester_input, - &instance->manchester_state, - &decoded_bit)) { + + if(manchester_advance( + instance->manchester_state, + (ManchesterEvent)manchester_input, + &instance->manchester_state, + &decoded_bit)) { uint32_t carry = (instance->decode_data_low >> 31) & 1; - instance->decode_data_low = (instance->decode_data_low << 1) | (decoded_bit ? 1 : 0); + instance->decode_data_low = (instance->decode_data_low << 1) | + (decoded_bit ? 1 : 0); instance->decode_data_high = (instance->decode_data_high << 1) | carry; instance->decode_count_bit++; - + if(instance->decode_count_bit == PSA_KEY1_BITS) { instance->key1_low = instance->decode_data_low; instance->key1_high = instance->decode_data_high; @@ -1287,11 +1436,11 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } } } - + if(!level) { return; } - + if(!should_process) { uint32_t end_diff; if(duration < PSA_TE_END_1000) { @@ -1303,11 +1452,11 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati if(instance->decode_count_bit != PSA_KEY2_BITS) { return; } - + if(((instance->key1_high >> 16) & 0xF) == 0xA) { uint32_t new_key2_low = instance->decode_data_low; instance->validation_field = (uint16_t)(instance->decode_data_low & 0xFFFF); - + instance->decrypted_type = 0; instance->decrypted_button = 0; instance->decrypted_serial = 0; @@ -1315,32 +1464,43 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati instance->decrypted_crc = 0; instance->decrypted_seed = 0; instance->decrypted = 0x00; - + instance->key2_low = new_key2_low; instance->key2_high = instance->decode_data_high; instance->status_flag = 0x80; - - FURI_LOG_I(TAG, "Signal decoded (alt path) - Key1:%08lX%08lX Key2:%04X ValField:%04X", - (unsigned long)instance->key1_high, (unsigned long)instance->key1_low, - (unsigned int)(instance->key2_low & 0xFFFF), (unsigned int)instance->validation_field); - + + FURI_LOG_I( + TAG, + "Signal decoded (alt path) - Key1:%08lX%08lX Key2:%04X ValField:%04X", + (unsigned long)instance->key1_high, + (unsigned long)instance->key1_low, + (unsigned int)(instance->key2_low & 0xFFFF), + (unsigned int)instance->validation_field); + uint8_t buffer[48] = {0}; - psa_setup_byte_buffer(buffer, instance->key1_low, instance->key1_high, instance->key2_low); + psa_setup_byte_buffer( + buffer, instance->key1_low, instance->key1_high, instance->key2_low); if(psa_direct_xor_decrypt(instance, buffer)) { instance->mode_serialize = 0x23; instance->decrypted = 0x50; - FURI_LOG_I(TAG, "Direct XOR decryption SUCCESS - Type:0x23 Btn:%02X Ser:%06lX Cnt:%08lX", - (unsigned int)instance->decrypted_button, (unsigned long)instance->decrypted_serial, (unsigned long)instance->decrypted_counter); + FURI_LOG_I( + TAG, + "Direct XOR decryption SUCCESS - Type:0x23 Btn:%02X Ser:%06lX Cnt:%08lX", + (unsigned int)instance->decrypted_button, + (unsigned long)instance->decrypted_serial, + (unsigned long)instance->decrypted_counter); } else { instance->decrypted = 0x00; - FURI_LOG_I(TAG, "Direct XOR decryption FAILED - marked for brute force (Type:0x36) - deferred to get_string"); + FURI_LOG_I( + TAG, + "Direct XOR decryption FAILED - marked for brute force (Type:0x36) - deferred to get_string"); instance->mode_serialize = 0x36; } - + if(instance->base.callback) { instance->base.callback(&instance->base, instance->base.context); } - + instance->decode_data_low = 0; instance->decode_data_high = 0; instance->decode_count_bit = 0; @@ -1353,19 +1513,24 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } } break; - + case PSADecoderState3: if(duration >= 250) { if(duration >= PSA_TE_LONG_250 && duration < 0x12c) { if(instance->pattern_counter > PSA_PATTERN_THRESHOLD_2) { - FURI_LOG_I(TAG, "[State3->State4] Transition detected with pattern_cnt=%lu", - (unsigned long)instance->pattern_counter); + FURI_LOG_I( + TAG, + "[State3->State4] Transition detected with pattern_cnt=%lu", + (unsigned long)instance->pattern_counter); new_state = PSADecoderState4; instance->decode_data_low = 0; instance->decode_data_high = 0; instance->decode_count_bit = 0; - manchester_advance(instance->manchester_state, ManchesterEventReset, - &instance->manchester_state, NULL); + manchester_advance( + instance->manchester_state, + ManchesterEventReset, + &instance->manchester_state, + NULL); instance->state = new_state; instance->pattern_counter = 0; instance->prev_duration = duration; @@ -1376,13 +1541,13 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati instance->pattern_counter = 0; break; } - + if(duration < PSA_TE_SHORT_125) { tolerance = PSA_TE_SHORT_125 - duration; } else { tolerance = duration - PSA_TE_SHORT_125; } - + if(tolerance < PSA_TOLERANCE_50) { uint32_t prev_diff = psa_abs_diff(prev_dur, PSA_TE_SHORT_125); if(prev_diff <= PSA_TOLERANCE_49) { @@ -1393,21 +1558,21 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati instance->prev_duration = duration; return; } - + new_state = PSADecoderState0; instance->pattern_counter = 0; break; - + case PSADecoderState4: if(instance->decode_count_bit >= PSA_MAX_BITS) { new_state = PSADecoderState0; break; } - + if(!level) { uint8_t manchester_input; bool decoded_bit = false; - + if(duration < PSA_TE_SHORT_125) { tolerance = PSA_TE_SHORT_125 - duration; if(tolerance > PSA_TOLERANCE_49) { @@ -1428,16 +1593,18 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati return; } } - - if(manchester_advance(instance->manchester_state, - (ManchesterEvent)manchester_input, - &instance->manchester_state, - &decoded_bit)) { + + if(manchester_advance( + instance->manchester_state, + (ManchesterEvent)manchester_input, + &instance->manchester_state, + &decoded_bit)) { uint32_t carry = (instance->decode_data_low >> 31) & 1; - instance->decode_data_low = (instance->decode_data_low << 1) | (decoded_bit ? 1 : 0); + instance->decode_data_low = (instance->decode_data_low << 1) | + (decoded_bit ? 1 : 0); instance->decode_data_high = (instance->decode_data_high << 1) | carry; instance->decode_count_bit++; - + if(instance->decode_count_bit == PSA_KEY1_BITS) { instance->key1_low = instance->decode_data_low; instance->key1_high = instance->decode_data_high; @@ -1456,7 +1623,7 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati if(instance->decode_count_bit != PSA_KEY2_BITS) { return; } - + if(((instance->key1_high >> 16) & 0xF) != 0xA) { instance->decode_data_low = 0; instance->decode_data_high = 0; @@ -1465,10 +1632,10 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati instance->state = new_state; return; } - + uint32_t new_key2_low = instance->decode_data_low; instance->validation_field = (uint16_t)(instance->decode_data_low & 0xFFFF); - + instance->decrypted_type = 0; instance->decrypted_button = 0; instance->decrypted_serial = 0; @@ -1476,33 +1643,44 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati instance->decrypted_crc = 0; instance->decrypted_seed = 0; instance->decrypted = 0x00; - + instance->key2_low = new_key2_low; instance->key2_high = instance->decode_data_high; instance->mode_serialize = 2; instance->status_flag = 0x80; - - FURI_LOG_I(TAG, "Signal decoded (state4) - Key1:%08lX%08lX Key2:%04X ValField:%04X", - (unsigned long)instance->key1_high, (unsigned long)instance->key1_low, - (unsigned int)(instance->key2_low & 0xFFFF), (unsigned int)instance->validation_field); - + + FURI_LOG_I( + TAG, + "Signal decoded (state4) - Key1:%08lX%08lX Key2:%04X ValField:%04X", + (unsigned long)instance->key1_high, + (unsigned long)instance->key1_low, + (unsigned int)(instance->key2_low & 0xFFFF), + (unsigned int)instance->validation_field); + uint8_t buffer[48] = {0}; - psa_setup_byte_buffer(buffer, instance->key1_low, instance->key1_high, instance->key2_low); + psa_setup_byte_buffer( + buffer, instance->key1_low, instance->key1_high, instance->key2_low); if(psa_direct_xor_decrypt(instance, buffer)) { instance->mode_serialize = 0x23; instance->decrypted = 0x50; - FURI_LOG_I(TAG, "Direct XOR decryption SUCCESS - Type:0x23 Btn:%02X Ser:%06lX Cnt:%08lX", - (unsigned int)instance->decrypted_button, (unsigned long)instance->decrypted_serial, (unsigned long)instance->decrypted_counter); + FURI_LOG_I( + TAG, + "Direct XOR decryption SUCCESS - Type:0x23 Btn:%02X Ser:%06lX Cnt:%08lX", + (unsigned int)instance->decrypted_button, + (unsigned long)instance->decrypted_serial, + (unsigned long)instance->decrypted_counter); } else { instance->decrypted = 0x00; instance->mode_serialize = 0x36; - FURI_LOG_I(TAG, "Direct XOR decryption FAILED - marked for brute force (Type:0x36) - deferred to get_string"); + FURI_LOG_I( + TAG, + "Direct XOR decryption FAILED - marked for brute force (Type:0x36) - deferred to get_string"); } - + if(instance->base.callback) { instance->base.callback(&instance->base, instance->base.context); } - + instance->decode_data_low = 0; instance->decode_data_high = 0; instance->decode_count_bit = 0; @@ -1515,7 +1693,7 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } break; } - + instance->state = new_state; instance->prev_duration = duration; } @@ -1524,10 +1702,7 @@ uint8_t subghz_protocol_decoder_psa_get_hash_data(void* context) { furi_assert(context); SubGhzProtocolDecoderPSA* instance = context; uint64_t combined_data = ((uint64_t)instance->key1_high << 32) | instance->key1_low; - SubGhzBlockDecoder decoder = { - .decode_data = combined_data, - .decode_count_bit = 64 - }; + SubGhzBlockDecoder decoder = {.decode_data = combined_data, .decode_count_bit = 64}; return subghz_protocol_blocks_get_hash_data(&decoder, 16); } @@ -1537,77 +1712,78 @@ SubGhzProtocolStatus subghz_protocol_decoder_psa_serialize( SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderPSA* instance = context; - + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) break; - + if(!flipper_format_write_string_cstr( flipper_format, "Preset", furi_string_get_cstr(preset->name))) break; - + if(!flipper_format_write_string_cstr( flipper_format, "Protocol", instance->base.protocol->name)) break; - + uint32_t bits = 128; if(!flipper_format_write_uint32(flipper_format, "Bit", &bits, 1)) break; - + char key1_str[20]; uint64_t key1 = ((uint64_t)instance->key1_high << 32) | instance->key1_low; snprintf(key1_str, sizeof(key1_str), "%016llX", key1); if(!flipper_format_write_string_cstr(flipper_format, "Key", key1_str)) break; - + char key2_str[20]; uint64_t key2 = ((uint64_t)instance->key2_high << 32) | instance->key2_low; snprintf(key2_str, sizeof(key2_str), "%016llX", key2); if(!flipper_format_write_string_cstr(flipper_format, "Key_2", key2_str)) break; - + uint32_t val_field = instance->validation_field; flipper_format_write_uint32(flipper_format, "ValidationField", &val_field, 1); - + if(instance->decrypted == 0x50 && instance->decrypted_type != 0) { flipper_format_write_uint32(flipper_format, "Serial", &instance->decrypted_serial, 1); - + uint32_t btn_temp = instance->decrypted_button; flipper_format_write_uint32(flipper_format, "Btn", &btn_temp, 1); - + flipper_format_write_uint32(flipper_format, "Cnt", &instance->decrypted_counter, 1); - + uint32_t crc_temp = instance->decrypted_crc; flipper_format_write_uint32(flipper_format, "CRC", &crc_temp, 1); - + uint32_t type_temp = instance->decrypted_type; flipper_format_write_uint32(flipper_format, "Type", &type_temp, 1); - + flipper_format_write_uint32(flipper_format, "Seed", &instance->decrypted_seed, 1); } - + ret = SubGhzProtocolStatusOk; } while(false); - + return ret; } -SubGhzProtocolStatus subghz_protocol_decoder_psa_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_psa_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderPSA* instance = context; - + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; FuriString* temp_str = furi_string_alloc(); - + do { if(!flipper_format_read_string(flipper_format, "Key", temp_str)) { break; } - + const char* key1_str = furi_string_get_cstr(temp_str); uint64_t key1 = 0; size_t str_len = strlen(key1_str); for(size_t i = 0; i < str_len && i < 16; i++) { char c = key1_str[i]; if(c == ' ') continue; - + uint8_t nibble; if(c >= '0' && c <= '9') { nibble = c - '0'; @@ -1622,18 +1798,18 @@ SubGhzProtocolStatus subghz_protocol_decoder_psa_deserialize(void* context, Flip } instance->key1_low = (uint32_t)(key1 & 0xFFFFFFFF); instance->key1_high = (uint32_t)((key1 >> 32) & 0xFFFFFFFF); - + if(!flipper_format_read_string(flipper_format, "Key_2", temp_str)) { break; } - + const char* key2_str = furi_string_get_cstr(temp_str); uint64_t key2 = 0; str_len = strlen(key2_str); for(size_t i = 0; i < str_len && i < 16; i++) { char c = key2_str[i]; if(c == ' ') continue; - + uint8_t nibble; if(c >= '0' && c <= '9') { nibble = c - '0'; @@ -1648,14 +1824,14 @@ SubGhzProtocolStatus subghz_protocol_decoder_psa_deserialize(void* context, Flip } instance->key2_low = (uint32_t)(key2 & 0xFFFFFFFF); instance->key2_high = (uint32_t)((key2 >> 32) & 0xFFFFFFFF); - + instance->status_flag = 0x80; - + psa_decrypt_router(instance); - + ret = SubGhzProtocolStatusOk; } while(false); - + furi_string_free(temp_str); return ret; } @@ -1663,19 +1839,21 @@ SubGhzProtocolStatus subghz_protocol_decoder_psa_deserialize(void* context, Flip void subghz_protocol_decoder_psa_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderPSA* instance = context; - - if(instance->status_flag == 0x80 && - (instance->key1_low != 0 || instance->key1_high != 0) && + + if(instance->status_flag == 0x80 && (instance->key1_low != 0 || instance->key1_high != 0) && instance->decrypted_type == 0) { FURI_LOG_I(TAG, "get_string: Calling decryption router (decrypted_type=0)"); psa_decrypt_router(instance); } else { - FURI_LOG_D(TAG, "get_string: Skipping router - status_flag=0x%08lX decrypted_type=0x%02X", - (unsigned long)instance->status_flag, (unsigned int)instance->decrypted_type); + FURI_LOG_D( + TAG, + "get_string: Skipping router - status_flag=0x%08lX decrypted_type=0x%02X", + (unsigned long)instance->status_flag, + (unsigned int)instance->decrypted_type); } - + uint16_t key2_value = (uint16_t)(instance->key2_low & 0xFFFF); - + if(instance->decrypted == 0x50 && instance->decrypted_type != 0) { if(instance->decrypted_type == 0x23) { furi_string_printf( diff --git a/protocols/psa.h b/protocols/psa.h index 4bd6d17..df55b02 100644 --- a/protocols/psa.h +++ b/protocols/psa.h @@ -38,4 +38,3 @@ SubGhzProtocolStatus subghz_protocol_encoder_psa_deserialize(void* context, FlipperFormat* flipper_format); void subghz_protocol_encoder_psa_stop(void* context); LevelDuration subghz_protocol_encoder_psa_yield(void* context); - diff --git a/protocols/vag.c b/protocols/vag.c index 41acea7..3d66508 100644 --- a/protocols/vag.c +++ b/protocols/vag.c @@ -125,7 +125,7 @@ static void vag_tea_decrypt(uint32_t* v0, uint32_t* v1, const uint32_t* key_sche *v0 -= (((*v1 << 4) ^ (*v1 >> 5)) + *v1) ^ (sum + key_schedule[sum & 3]); } } - +#ifdef ENABLE_EMULATE_FEATURE static void vag_tea_encrypt(uint32_t* v0, uint32_t* v1, const uint32_t* key_schedule) { uint32_t sum = 0; for(int i = 0; i < VAG_TEA_ROUNDS; i++) { @@ -134,7 +134,7 @@ static void vag_tea_encrypt(uint32_t* v0, uint32_t* v1, const uint32_t* key_sche *v1 += (((*v0 << 4) ^ (*v0 >> 5)) + *v0) ^ (sum + key_schedule[(sum >> 11) & 3]); } } - +#endif static bool vag_dispatch_type_1_2(uint8_t dispatch) { return (dispatch == 0x2A || dispatch == 0x1C || dispatch == 0x46); } @@ -449,7 +449,7 @@ const SubGhzProtocolDecoder subghz_protocol_vag_decoder = { .deserialize = subghz_protocol_decoder_vag_deserialize, .get_string = subghz_protocol_decoder_vag_get_string, }; - +#ifdef ENABLE_EMULATE_FEATURE const SubGhzProtocolEncoder subghz_protocol_vag_encoder = { .alloc = subghz_protocol_encoder_vag_alloc, .free = subghz_protocol_encoder_vag_free, @@ -457,6 +457,15 @@ const SubGhzProtocolEncoder subghz_protocol_vag_encoder = { .stop = subghz_protocol_encoder_vag_stop, .yield = subghz_protocol_encoder_vag_yield, }; +#else +const SubGhzProtocolEncoder subghz_protocol_vag_encoder = { + .alloc = NULL, + .free = NULL, + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; +#endif const SubGhzProtocol vag_protocol = { .name = VAG_PROTOCOL_NAME, @@ -1030,6 +1039,8 @@ SubGhzProtocolStatus return ret; } +#ifdef ENABLE_EMULATE_FEATURE + typedef struct SubGhzProtocolEncoderVAG { SubGhzProtocolEncoderBase base; SubGhzBlockGeneric generic; @@ -1599,6 +1610,7 @@ static void vag_encoder_build_type3_4(SubGhzProtocolEncoderVAG* instance) { FURI_LOG_W(TAG, "WARNING: Pulse count %zu != expected 518!", index); } } +#endif void subghz_protocol_decoder_vag_get_string(void* context, FuriString* output) { furi_assert(context); @@ -1665,6 +1677,7 @@ void subghz_protocol_decoder_vag_get_string(void* context, FuriString* output) { #define VAG_ENCODER_UPLOAD_MAX_SIZE 680 +#ifdef ENABLE_EMULATE_FEATURE void* subghz_protocol_encoder_vag_alloc(SubGhzEnvironment* environment) { UNUSED(environment); FURI_LOG_I(TAG, "VAG encoder alloc"); @@ -2003,3 +2016,4 @@ SubGhzProtocolStatus return ret; } +#endif