diff --git a/protocols/fiat_v0.h b/protocols/fiat_v0.h index 0018770..98dd232 100644 --- a/protocols/fiat_v0.h +++ b/protocols/fiat_v0.h @@ -37,4 +37,4 @@ void subghz_protocol_encoder_fiat_v0_free(void* context); SubGhzProtocolStatus subghz_protocol_encoder_fiat_v0_deserialize(void* context, FlipperFormat* flipper_format); void subghz_protocol_encoder_fiat_v0_stop(void* context); -LevelDuration subghz_protocol_encoder_fiat_v0_yield(void* context); \ No newline at end of file +LevelDuration subghz_protocol_encoder_fiat_v0_yield(void* context); diff --git a/protocols/psa.c b/protocols/psa.c index f85e926..4c6fb99 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; @@ -93,7 +93,7 @@ struct SubGhzProtocolEncoderPSA { SubGhzProtocolEncoderBase base; SubGhzProtocolBlockEncoder encoder; SubGhzBlockGeneric generic; - + uint32_t key1_low; uint32_t key1_high; uint16_t validation_field; @@ -136,17 +136,20 @@ 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); 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 +157,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 +173,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 +195,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 +203,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 +233,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 +248,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 +280,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 +288,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 +444,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 +483,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 +495,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 +526,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 +539,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 +557,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 +598,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 +625,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 +637,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 +657,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 +665,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 +673,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 +681,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 +690,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 +731,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,7 +747,7 @@ LevelDuration subghz_protocol_encoder_psa_yield(void* context) { instance->is_running = false; } } - + return ret; } @@ -669,7 +759,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 +835,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 +876,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 +886,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 +927,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 +939,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 +957,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 +971,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 +987,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 +1033,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 +1072,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 +1090,7 @@ static void psa_decrypt_router(SubGhzProtocolDecoderPSA* instance) { return; } } - + FURI_LOG_E(TAG, "=== ALL DECRYPTION ATTEMPTS FAILED ==="); instance->decrypted = 0x00; } @@ -1017,19 +1138,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 +1176,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 +1190,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 +1227,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 +1248,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 +1276,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 +1287,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 +1334,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 +1353,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 +1403,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 +1426,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 +1442,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 +1454,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 +1503,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 +1531,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 +1548,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 +1583,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 +1613,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 +1622,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 +1633,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 +1683,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 +1692,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 +1702,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 +1788,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 +1814,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 +1829,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/subaru.c b/protocols/subaru.c index d4c559d..96a0b7c 100644 --- a/protocols/subaru.c +++ b/protocols/subaru.c @@ -10,11 +10,11 @@ static const SubGhzBlockConst subghz_protocol_subaru_const = { .min_count_bit_for_found = 64, }; -#define SUBARU_PREAMBLE_PAIRS 80 -#define SUBARU_GAP_US 2800 -#define SUBARU_SYNC_US 2800 -#define SUBARU_TOTAL_BURSTS 3 -#define SUBARU_INTER_BURST_GAP 25000 +#define SUBARU_PREAMBLE_PAIRS 80 +#define SUBARU_GAP_US 2800 +#define SUBARU_SYNC_US 2800 +#define SUBARU_TOTAL_BURSTS 3 +#define SUBARU_INTER_BURST_GAP 25000 typedef struct SubGhzProtocolDecoderSubaru { SubGhzProtocolDecoderBase base; @@ -357,8 +357,12 @@ SubGhzProtocolStatus subghz_protocol_encoder_subaru_get_upload(instance); instance->encoder.is_running = true; - FURI_LOG_I(TAG, "Encoder ready: key=0x%016llX, serial=0x%06lX, btn=0x%X", - instance->key, instance->serial, instance->btn); + FURI_LOG_I( + TAG, + "Encoder ready: key=0x%016llX, serial=0x%06lX, btn=0x%X", + instance->key, + instance->serial, + instance->btn); ret = SubGhzProtocolStatusOk; } while(false); @@ -563,9 +567,11 @@ SubGhzProtocolStatus subghz_protocol_decoder_subaru_serialize( 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; + flipper_format, "Preset", furi_string_get_cstr(preset->name))) + break; if(!flipper_format_write_string_cstr( - flipper_format, "Protocol", instance->generic.protocol_name)) break; + flipper_format, "Protocol", instance->generic.protocol_name)) + break; uint32_t bits = 64; if(!flipper_format_write_uint32(flipper_format, "Bit", &bits, 1)) break; @@ -623,4 +629,4 @@ void subghz_protocol_decoder_subaru_get_string(void* context, FuriString* output instance->serial, instance->btn, instance->cnt); -} \ No newline at end of file +} diff --git a/protocols/subaru.h b/protocols/subaru.h index bf21386..7b45bd6 100644 --- a/protocols/subaru.h +++ b/protocols/subaru.h @@ -34,4 +34,4 @@ void subghz_protocol_encoder_subaru_free(void* context); SubGhzProtocolStatus subghz_protocol_encoder_subaru_deserialize(void* context, FlipperFormat* flipper_format); void subghz_protocol_encoder_subaru_stop(void* context); -LevelDuration subghz_protocol_encoder_subaru_yield(void* context); \ No newline at end of file +LevelDuration subghz_protocol_encoder_subaru_yield(void* context);