Electra intercom

I meant decoding on reader side. It gets something, but not the key data. I’ll recheck now, thanks for reporting your success.

Updated the patch to allow user selection of the tag dump from the available *.ask.raw files.

Note: I’ve tried 2 different keys and 9/10 dumps worked ok. Interesting that some of the dumps, event if not correctly recognized as valid EM4100 (using CLI rfid raw_analyze), were replayed ok and recognized by the Electra reader.

From 7748f70e2ae02185af752714139e80b3a6771bef Mon Sep 17 00:00:00 2001
From: Dan Caprita <[email protected]>
Date: Tue, 18 Apr 2023 23:32:41 +0300
Subject: [PATCH] Add Emulate RAW RFID data to "125 kHz RFID->Extra Actions"

NOTES:
* works also with Electra raw dumps
  (use "125 kHz RFID->Extra Actions->Read RAW RFID data")
* need to activate Debug from "Settings->System" for RAW options

Signed-off-by: Dan Caprita <[email protected]>
---
 applications/main/lfrfid/lfrfid.c             | 20 +++++
 applications/main/lfrfid/lfrfid_i.h           |  2 +
 .../main/lfrfid/scenes/lfrfid_scene_config.h  |  2 +
 .../scenes/lfrfid_scene_extra_actions.c       | 13 +++
 .../lfrfid/scenes/lfrfid_scene_raw_emulate.c  | 86 +++++++++++++++++++
 .../scenes/lfrfid_scene_select_raw_key.c      | 23 +++++
 6 files changed, 146 insertions(+)
 create mode 100644 applications/main/lfrfid/scenes/lfrfid_scene_raw_emulate.c
 create mode 100644 applications/main/lfrfid/scenes/lfrfid_scene_select_raw_key.c

diff --git a/applications/main/lfrfid/lfrfid.c b/applications/main/lfrfid/lfrfid.c
index 85a00eea..f78393d6 100644
--- a/applications/main/lfrfid/lfrfid.c
+++ b/applications/main/lfrfid/lfrfid.c
@@ -243,6 +243,26 @@ bool lfrfid_load_key_from_file_select(LfRfid* app) {
     return result;
 }
 
+bool lfrfid_load_raw_key_from_file_select(LfRfid* app) {
+    furi_assert(app);
+
+    DialogsFileBrowserOptions browser_options;
+    dialog_file_browser_set_basic_options(&browser_options, LFRFID_APP_RAW_ASK_EXTENSION, &I_125_10px);
+    browser_options.base_path = LFRFID_APP_FOLDER;
+
+    // Input events and views are managed by file_browser
+    bool result =
+        dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options);
+
+    if(result) {
+        // Extract .raw and then .ask
+        path_extract_filename(app->file_path, app->file_name, true);
+        path_extract_filename(app->file_name, app->file_name, true);
+    }
+
+    return result;
+}
+
 bool lfrfid_delete_key(LfRfid* app) {
     furi_assert(app);
 
diff --git a/applications/main/lfrfid/lfrfid_i.h b/applications/main/lfrfid/lfrfid_i.h
index 72b06193..86929a14 100644
--- a/applications/main/lfrfid/lfrfid_i.h
+++ b/applications/main/lfrfid/lfrfid_i.h
@@ -125,6 +125,8 @@ bool lfrfid_save_key(LfRfid* app);
 
 bool lfrfid_load_key_from_file_select(LfRfid* app);
 
+bool lfrfid_load_raw_key_from_file_select(LfRfid* app);
+
 bool lfrfid_delete_key(LfRfid* app);
 
 bool lfrfid_load_key_data(LfRfid* app, FuriString* path, bool show_dialog);
diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_config.h b/applications/main/lfrfid/scenes/lfrfid_scene_config.h
index b77ade82..4ca78d7e 100644
--- a/applications/main/lfrfid/scenes/lfrfid_scene_config.h
+++ b/applications/main/lfrfid/scenes/lfrfid_scene_config.h
@@ -22,3 +22,5 @@ ADD_SCENE(lfrfid, raw_name, RawName)
 ADD_SCENE(lfrfid, raw_read, RawRead)
 ADD_SCENE(lfrfid, raw_success, RawSuccess)
 ADD_SCENE(lfrfid, rpc, Rpc)
+ADD_SCENE(lfrfid, raw_emulate, RawEmulate)
+ADD_SCENE(lfrfid, select_raw_key, SelectRawKey)
diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c b/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c
index fac2ebce..2af12466 100644
--- a/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c
+++ b/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c
@@ -5,6 +5,7 @@ typedef enum {
     SubmenuIndexASK,
     SubmenuIndexPSK,
     SubmenuIndexRAW,
+    SubmenuIndexRAWEMULATE,
 } SubmenuIndex;
 
 static void lfrfid_scene_extra_actions_submenu_callback(void* context, uint32_t index) {
@@ -39,6 +40,15 @@ void lfrfid_scene_extra_actions_on_enter(void* context) {
             app);
     }
 
+    if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
+        submenu_add_item(
+            submenu,
+            "Emulate RAW RFID data",
+            SubmenuIndexRAWEMULATE,
+            lfrfid_scene_extra_actions_submenu_callback,
+            app);
+    }
+
     submenu_set_selected_item(
         submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneExtraActions));
 
@@ -68,6 +78,9 @@ bool lfrfid_scene_extra_actions_on_event(void* context, SceneManagerEvent event)
         } else if(event.event == SubmenuIndexRAW) {
             scene_manager_next_scene(app->scene_manager, LfRfidSceneRawName);
             consumed = true;
+        } else if(event.event == SubmenuIndexRAWEMULATE) {
+            scene_manager_next_scene(app->scene_manager, LfRfidSceneSelectRawKey);
+            consumed = true;
         }
         scene_manager_set_scene_state(app->scene_manager, LfRfidSceneExtraActions, event.event);
     }
diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_raw_emulate.c b/applications/main/lfrfid/scenes/lfrfid_scene_raw_emulate.c
new file mode 100644
index 00000000..a9c441a1
--- /dev/null
+++ b/applications/main/lfrfid/scenes/lfrfid_scene_raw_emulate.c
@@ -0,0 +1,86 @@
+#include "../lfrfid_i.h"
+
+#define TAG "ADC"
+
+typedef struct {
+    FuriString* string_file_name;
+    bool error;
+} LfRfidEmulateRawState;
+
+static void lfrfid_raw_emulate_callback(LFRFIDWorkerEmulateRawResult result, void* context) {
+    LfRfid* app = context;
+
+    if(result == LFRFIDWorkerEmulateRawFileError) {
+        view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadError);
+    } else if(result == LFRFIDWorkerEmulateRawOverrun) {
+        view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadOverrun);
+    }
+}
+
+void lfrfid_scene_raw_emulate_on_enter(void* context) {
+    LfRfid* app = context;
+    Popup* popup = app->popup;
+
+    LfRfidEmulateRawState* state = malloc(sizeof(LfRfidEmulateRawState));
+    scene_manager_set_scene_state(app->scene_manager, LfRfidSceneRawEmulate, (uint32_t)state);
+    state->string_file_name = furi_string_alloc();
+
+    popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
+    view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
+    lfrfid_worker_start_thread(app->lfworker);
+    lfrfid_make_app_folder(app);
+
+    furi_string_printf(
+        state->string_file_name,
+        "%s/%s%s",
+        LFRFID_SD_FOLDER,
+        furi_string_get_cstr(app->file_name),
+        LFRFID_APP_RAW_ASK_EXTENSION);
+    FURI_LOG_D(TAG, "raw_emulate->file_name=%s", furi_string_get_cstr(state->string_file_name));
+    popup_set_header(popup, "Emulating\nRAW RFID\nASK", 89, 30, AlignCenter, AlignTop);
+    lfrfid_worker_emulate_raw_start(
+        app->lfworker,
+        furi_string_get_cstr(state->string_file_name),
+        lfrfid_raw_emulate_callback,
+        app);
+
+    notification_message(app->notifications, &sequence_blink_start_cyan);
+
+    state->error = false;
+}
+
+bool lfrfid_scene_raw_emulate_on_event(void* context, SceneManagerEvent event) {
+    LfRfid* app = context;
+    Popup* popup = app->popup;
+    LfRfidEmulateRawState* state =
+        (LfRfidEmulateRawState*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneRawEmulate);
+    bool consumed = false;
+
+    furi_assert(state);
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == LfRfidEventReadError) {
+            consumed = true;
+            state->error = true;
+            popup_set_header(
+                popup, "Reading\nRAW RFID\nFile error", 89, 30, AlignCenter, AlignTop);
+            notification_message(app->notifications, &sequence_blink_start_red);
+        }
+    }
+
+    return consumed;
+}
+
+void lfrfid_scene_raw_emulate_on_exit(void* context) {
+    LfRfid* app = context;
+    LfRfidEmulateRawState* state =
+        (LfRfidEmulateRawState*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneRawEmulate);
+
+    notification_message(app->notifications, &sequence_blink_stop);
+    popup_reset(app->popup);
+    lfrfid_worker_stop(app->lfworker);
+    lfrfid_worker_stop_thread(app->lfworker);
+
+    furi_string_free(state->string_file_name);
+    free(state);
+}
diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_select_raw_key.c b/applications/main/lfrfid/scenes/lfrfid_scene_select_raw_key.c
new file mode 100644
index 00000000..f12d280a
--- /dev/null
+++ b/applications/main/lfrfid/scenes/lfrfid_scene_select_raw_key.c
@@ -0,0 +1,23 @@
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_select_raw_key_on_enter(void* context) {
+    LfRfid* app = context;
+
+    if(lfrfid_load_raw_key_from_file_select(app)) {
+        scene_manager_next_scene(app->scene_manager, LfRfidSceneRawEmulate);
+
+    } else {
+        scene_manager_previous_scene(app->scene_manager);
+    }
+}
+
+bool lfrfid_scene_select_raw_key_on_event(void* context, SceneManagerEvent event) {
+    UNUSED(context);
+    UNUSED(event);
+    bool consumed = false;
+    return consumed;
+}
+
+void lfrfid_scene_select_raw_key_on_exit(void* context) {
+    UNUSED(context);
+}
-- 
2.34.1
1 Like
  1. Is the reading using Proxmark3 (having the Electra commit mentioned above) the same as flipper zero?
  2. Can you dump the whole 64bits (including the 9 ones from the header, row and column parity bits and stop bit 0), not just the 40bits data payload

How exactly is it possible to dump the header with the Proxmark?

EM4100 protocol description

So on my proxmark i can detect 7 blocks. Where should the 9 header pairity bits be dumped? Or am I doing this corectly?

I don’t know Proxmark but I guess it has some debug options.

For flipperzero, you can for example update the display info showed in 125 kHz RFID->Saved->“your_key”->Info

lib/lfrfid/protocols/protocol_em4100.c
@@ -274,6 +280,8 @@ void protocol_em4100_render_data(ProtocolEM4100* protocol, FuriString* result) {
     uint8_t* data = protocol->data;
     furi_string_printf(
         result, "FC: %03u, Card: %05u", data[2], (uint16_t)((data[3] << 8) | (data[4])));
+    furi_string_printf(
+        result, "ed: %llX", protocol->encoded_data);
 };

I have tried to raw emulate an Electra tag, but the reader is not responding… How did you manage to emulate that?
Thanks!

  1. Initially I’ve tested it using and Android app called “Serial USB Terminal” and connecting the phone through a OTG cable to flipper and running:
    $ rfid raw_emulate /ext/lfrfid/RfidRecord.ask.raw
    where RfidRecord.ask.raw was the name of the ASK raw file dump of my tag

  2. Then I’ve created a patch for the “125 kHz RFID” app that added “Emulate RAW RFID data” to the "125 kHz RFID->Extra Actions” so that we can select directly from the GUI the raw dump to emulate

Analyzing several dumps of the Electra tags, it seems they are adding 42 bits extra after the standard EM4100. So, you need a 128 bits card (e.g. an EM4200 that is backward compatible with older EM4100) in order to clone an Electra tag.

The raw emulation works as it’s not parsing the content in order to extract only the 64 bits (from which only 40bits are useful data, the rest being 9 ones header+10 rows and 4 columns parity bits+1 zero stop bit) but replays the original content.

1 Like

I 've followed the above steps mentioned by you (downloaded the firmware, patched the files, compiled the firmware), made raw recordings of 2 of my tags and replay them to the reader, but there is no reaction from the reader.
What software do you use for analysing the raw files? I want to be sure that they are consistent (not empty).

As written above, the standard firmware, “125 kHz RFID” app command line interface:
$ rfid raw_analyze /ext/lfrfid/RfidRecord.ask.raw

My tag dumps are around 19KiB (note that there could be some dumps that don’t work - probably some synchronization issues, but majority of them works ok - more then 75%).

I’ve made several dumps using the same rfid tag and most of them are around 22kB. After analyzing them, the result is almost the same as the one below.
I tried to emulate them using the serial console and directly from flipper (using your modified scripts), but the Electra reader is not reading them.
I’m not able to attach the raw file here (Permission denied)

>: rfid raw_analyze /ext/lfrfid/RfidRecord.ask.raw
[32 131]        [32 99]
[316 511]       [316 195]
[316 512]       [316 196]
[316 510]       [316 194]
[317 511]       [317 194]
[317 511]       [317 194]
[317 511]       [317 194]
[316 511]       [316 195]
[317 512]       [317 195]
[316 510]       [316 194]
[317 511]       [317 194]
[317 512]       [317 195]
[315 511]       [315 196]
[316 510]       [316 194]
[316 511]       [316 195]
[316 511]       [316 195]
[315 511]       [315 196]
[316 511]       [316 195]
[315 510]       [315 195]
[316 510]       [316 194]
[316 510]       [316 194]
[315 511]       [315 196]
[572 767]       [572 195]
[316 511]       [316 195]
[316 511]       [316 195]
[316 511]       [316 195]
[316 511]       [316 195]
[315 511]       [315 196]
[315 511]       [315 196]
[315 511]       [315 196]
[315 791]       [315 476]
[288 487]       [288 199]
[314 511]       [314 197]
[314 511]       [314 197]
[314 511]       [314 197]
[314 511]       [314 197]
[315 511]       [315 196]
[570 767]       [570 197]
[314 791]       [314 477]
[547 743]       [547 196]
[315 511]       [315 196]
[315 791]       [315 476]
[547 743]       [547 196]
[316 790]       [316 474]
[289 487]       [289 198]
[315 511]       [315 196]
[571 1047]      [571 476]
[547 1022]      [547 475]
[549 1023]      [549 474]
[291 488]       [291 197]
[571 766]       [571 195]
[317 790]       [317 473]
[290 488]       [290 198]
[572 1046]      [572 474]
[291 488]       [291 197]
[316 510]       [316 194]
[573 1046]      [573 473]
[291 488]       [291 197]
[572 1046]      [572 474]
[550 743]       [550 193]
[318 511]       [318 193]
[318 791]       [318 473]
[291 487]       [291 196]
[316 510]       [316 194]
[574 1047]      [574 473]
[291 487]       [291 196]
[575 1047]      [575 472]
[550 1023]      [550 473]
[292 487]       [292 195]
[575 1046]      [575 471]        <FOUND EM4100>
   Frequency: 125000.000000
  Duty Cycle: 0.500000
       Warns: 0
   Pulse sum: 25554
Duration sum: 43597
     Average: 0.586141
    Protocol: EM4100 [03 E8 56 82 C9]
FC: 086, Card: 33481

Maybe it matters and newer hw from Electra has additional security mechanism (though I doubt), but I’ve tested on 3 different Electra readers PES.A255 (https://www.electra.ro/en/produse/video-and-audio-door-phones/pass-analog-system/pes-a255) and worked ok:

  • ACC when using the right tag dump
  • ERR when using an incorrect tag dump (from another location)
  • no message when using a corrupted tag dump (though I could notice some reaction from the reader - for the PES.A255, the dots disappears from the display meaning it was reading but waiting for the additional Electra specific bits)

I get no reaction from both readers - the main unit which looks like the PES.A255 and the extension which looks like this one: Kit extensie control acces videointerfon/interfon Electra, EXTENSIE CA - A2t.ro.

As mentioned above, Electra adds some extra bits to the standard EM4100. For the dumps I’ve analyses, they add the same bits, no-matter the actual data. I’ve found 2 variants:

  • 16 bits: 0x7E1E (0b111111000011110)
  • 64 bits: 0x7E1EAAAAAAAAAAAA
    Tested Emulate with the patch bellow and works ok (Electra reader PES.A255).

Fixes:
a. short time workaround is to alternate between actual data and Electra data (see PoC patch bellow)
b. long time implementation would be to add an Electra EM4100 protocol option.

From a4736d395efaeb328849a2cf0b6327faa764bc34 Mon Sep 17 00:00:00 2001
From: Dan Caprita <[email protected]>
Date: Thu, 3 May 2023 22:29:09 +0300
Subject: [PATCH] [RFID] Add ELECTRA extra data: 0x7E1E[AAAAAAAAAAAA]

Signed-off-by: Dan Caprita <[email protected]>
---
 lib/lfrfid/protocols/protocol_em4100.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/lib/lfrfid/protocols/protocol_em4100.c b/lib/lfrfid/protocols/protocol_em4100.c
index 4b720dff..a3be54f2 100644
--- a/lib/lfrfid/protocols/protocol_em4100.c
+++ b/lib/lfrfid/protocols/protocol_em4100.c
@@ -35,10 +35,13 @@ typedef uint64_t EM4100DecodedData;
 #define EM_READ_LONG_TIME_LOW (EM_READ_LONG_TIME - EM_READ_JITTER_TIME)
 #define EM_READ_LONG_TIME_HIGH (EM_READ_LONG_TIME + EM_READ_JITTER_TIME)
.
+#define EM_ELECTRA_DATA 0x7E1EAAAAAAAAAAAA
+
 typedef struct {
     uint8_t data[EM4100_DECODED_DATA_SIZE];
.
     EM4100DecodedData encoded_data;
+    EM4100DecodedData encoded_data_old;
     uint8_t encoded_data_index;
     bool encoded_polarity;
.
@@ -237,6 +240,13 @@ LevelDuration protocol_em4100_encoder_yield(ProtocolEM4100* proto) {
         proto->encoded_polarity = true;
         proto->encoded_data_index++;
         if(proto->encoded_data_index >= 64) {
+            // alternate between actual data and Electra data
+            if (proto->encoded_data != EM_ELECTRA_DATA) {
+                proto->encoded_data_old = proto->encoded_data;
+                proto->encoded_data = EM_ELECTRA_DATA;
+            } else {
+                proto->encoded_data = proto->encoded_data_old;
+            }
             proto->encoded_data_index = 0;
         }
     }
--.
2.17.1
1 Like

CrazyClara from github can help us to

Do you have more details?

1 Like

ClaraCrazy is admin of a GitHub repo with a forked Flipper firmware by a person named… I bet you can guess… Clara.
I’m not sure it’s relevant to the conversation though. @Catalin_Constantinescu did she offer to help with this?

I know who she is and I appreciate her work, but I didn’t see the connection with the current topic, that’s why I asked for more details

1 Like

Tested patch above with Electra extra bits and works also with the PASS Digital range (P4S.A91I) → https://www.electra.ro/en/produse/video-and-audio-door-phones/pass-digital-system/p4s-a91i

Universal master key: 0XFFFFFFFFFF

1 Like

I don’t either.