Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/flipperzero-firmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgornekich <n.gorbadey@gmail.com>2021-06-15 17:54:09 +0300
committerGitHub <noreply@github.com>2021-06-15 17:54:09 +0300
commita0fdc559c971a48a5ca58d0dc2ecdc1fce0be3fb (patch)
tree5626dbd6190f8fa79f81b81772f7b2f7139dd02b /applications/nfc
parent0b14db4fb33d4466a02c0c85b01321bece5d6537 (diff)
[FL-662] Read Mifare Ultralight (#518)
* nfc: add read mifare ultralight to menu * emv_decoder: add pragma once * nfc: add mifare ultralight reader * nfc: add mifare ultralight read draw * nfc: add mifare ultralight type checker * nfc: rework menu callback * mifare ultralight: change type names Co-authored-by: あく <alleteam@gmail.com>
Diffstat (limited to 'applications/nfc')
-rwxr-xr-xapplications/nfc/nfc.c56
-rw-r--r--applications/nfc/nfc_i.h1
-rw-r--r--applications/nfc/nfc_types.h14
-rwxr-xr-x[-rw-r--r--]applications/nfc/nfc_views.c53
-rw-r--r--applications/nfc/nfc_views.h2
-rwxr-xr-x[-rw-r--r--]applications/nfc/nfc_worker.c123
-rw-r--r--applications/nfc/nfc_worker_i.h2
7 files changed, 234 insertions, 17 deletions
diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c
index cecd1544..eb2c3f74 100755
--- a/applications/nfc/nfc.c
+++ b/applications/nfc/nfc.c
@@ -22,17 +22,7 @@ uint32_t nfc_view_exit(void* context) {
void nfc_menu_callback(void* context, uint32_t index) {
furi_assert(message_queue);
NfcMessage message;
- if(index == 0) {
- message.type = NfcMessageTypeDetect;
- } else if(index == 1) {
- message.type = NfcMessageTypeReadEMV;
- } else if(index == 2) {
- message.type = NfcMessageTypeEmulateEMV;
- } else if(index == 3) {
- message.type = NfcMessageTypeEmulate;
- } else if(index == 4) {
- message.type = NfcMessageTypeField;
- }
+ message.type = index;
furi_check(osMessageQueuePut(message_queue, &message, 0, osWaitForever) == osOK);
}
@@ -52,11 +42,15 @@ Nfc* nfc_alloc() {
// Menu
nfc->submenu = submenu_alloc();
- submenu_add_item(nfc->submenu, "Detect", 0, nfc_menu_callback, nfc);
- submenu_add_item(nfc->submenu, "Read EMV", 1, nfc_menu_callback, nfc);
- submenu_add_item(nfc->submenu, "Emulate EMV", 2, nfc_menu_callback, nfc);
- submenu_add_item(nfc->submenu, "Emulate", 3, nfc_menu_callback, nfc);
- submenu_add_item(nfc->submenu, "Field", 4, nfc_menu_callback, nfc);
+ submenu_add_item(nfc->submenu, "Detect", NfcMessageTypeDetect, nfc_menu_callback, nfc);
+ submenu_add_item(nfc->submenu, "Read EMV", NfcMessageTypeReadEMV, nfc_menu_callback, nfc);
+ submenu_add_item(
+ nfc->submenu, "Emulate EMV", NfcMessageTypeEmulateEMV, nfc_menu_callback, nfc);
+ submenu_add_item(nfc->submenu, "Emulate", NfcMessageTypeEmulate, nfc_menu_callback, nfc);
+ submenu_add_item(nfc->submenu, "Field", NfcMessageTypeField, nfc_menu_callback, nfc);
+ submenu_add_item(
+ nfc->submenu, "Read MfUltralight", NfcMessageTypeReadMfUltralight, nfc_menu_callback, nfc);
+
View* submenu_view = submenu_get_view(nfc->submenu);
view_set_previous_callback(submenu_view, nfc_view_exit);
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewMenu, submenu_view);
@@ -98,6 +92,16 @@ Nfc* nfc_alloc() {
view_set_previous_callback(nfc->view_field, nfc_view_stop);
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewField, nfc->view_field);
+ // Read Mifare Ultralight
+ nfc->view_read_mf_ultralight = view_alloc();
+ view_set_context(nfc->view_read_mf_ultralight, nfc);
+ view_set_draw_callback(nfc->view_read_mf_ultralight, nfc_view_read_mf_ultralight_draw);
+ view_set_previous_callback(nfc->view_read_mf_ultralight, nfc_view_stop);
+ view_allocate_model(
+ nfc->view_read_mf_ultralight, ViewModelTypeLocking, sizeof(NfcViewReadModel));
+ view_dispatcher_add_view(
+ nfc->view_dispatcher, NfcViewReadMfUltralight, nfc->view_read_mf_ultralight);
+
// Error
nfc->view_error = view_alloc();
view_set_context(nfc->view_error, nfc);
@@ -144,6 +148,10 @@ void nfc_free(Nfc* nfc) {
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewField);
view_free(nfc->view_field);
+ // Read Mifare Ultralight
+ view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewReadMfUltralight);
+ view_free(nfc->view_read_mf_ultralight);
+
// Error
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewError);
view_free(nfc->view_error);
@@ -180,6 +188,7 @@ int32_t nfc_task(void* p) {
NfcMessage message;
while(1) {
furi_check(osMessageQueueGet(message_queue, &message, NULL, osWaitForever) == osOK);
+
if(message.type == NfcMessageTypeDetect) {
with_view_model(
nfc->view_detect, (NfcViewReadModel * model) {
@@ -200,6 +209,8 @@ int32_t nfc_task(void* p) {
nfc_start(nfc, NfcViewEmulate, NfcWorkerStateEmulate);
} else if(message.type == NfcMessageTypeField) {
nfc_start(nfc, NfcViewField, NfcWorkerStateField);
+ } else if(message.type == NfcMessageTypeReadMfUltralight) {
+ nfc_start(nfc, NfcViewReadMfUltralight, NfcWorkerStateReadMfUltralight);
} else if(message.type == NfcMessageTypeStop) {
nfc_worker_stop(nfc->worker);
} else if(message.type == NfcMessageTypeDeviceFound) {
@@ -228,6 +239,19 @@ int32_t nfc_task(void* p) {
model->found = false;
return true;
});
+ } else if(message.type == NfcMessageTypeMfUlFound) {
+ with_view_model(
+ nfc->view_read_mf_ultralight, (NfcViewReadModel * model) {
+ model->found = true;
+ model->device = message.device;
+ return true;
+ });
+ } else if(message.type == NfcMessageTypeMfUlNotFound) {
+ with_view_model(
+ nfc->view_read_mf_ultralight, (NfcViewReadModel * model) {
+ model->found = false;
+ return true;
+ });
} else if(message.type == NfcMessageTypeExit) {
nfc_free(nfc);
break;
diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h
index 0ade0471..3cac404c 100644
--- a/applications/nfc/nfc_i.h
+++ b/applications/nfc/nfc_i.h
@@ -31,6 +31,7 @@ struct Nfc {
View* view_emulate_emv;
View* view_emulate;
View* view_field;
+ View* view_read_mf_ultralight;
View* view_cli;
View* view_error;
ViewDispatcher* view_dispatcher;
diff --git a/applications/nfc/nfc_types.h b/applications/nfc/nfc_types.h
index 4cf46e97..8787c38f 100644
--- a/applications/nfc/nfc_types.h
+++ b/applications/nfc/nfc_types.h
@@ -44,8 +44,8 @@ typedef enum {
NfcDeviceTypeNfcb,
NfcDeviceTypeNfcf,
NfcDeviceTypeNfcv,
- NfcDeviceTypeNfcMifare,
NfcDeviceTypeEMV,
+ NfcDeviceTypeMfUltralight,
} NfcDeviceType;
typedef struct {
@@ -54,6 +54,12 @@ typedef struct {
} EMVCard;
typedef struct {
+ uint8_t uid[7];
+ uint8_t man_block[12];
+ uint8_t otp[4];
+} MfUlCard;
+
+typedef struct {
NfcDeviceType type;
union {
rfalNfcaListenDevice nfca;
@@ -61,6 +67,7 @@ typedef struct {
rfalNfcfListenDevice nfcf;
rfalNfcvListenDevice nfcv;
EMVCard emv_card;
+ MfUlCard mf_ul_card;
};
} NfcDevice;
@@ -75,16 +82,19 @@ typedef enum {
NfcWorkerStateEmulateEMV,
NfcWorkerStateEmulate,
NfcWorkerStateField,
+ NfcWorkerStateReadMfUltralight,
// Transition
NfcWorkerStateStop,
} NfcWorkerState;
typedef enum {
+ // From Menu
NfcMessageTypeDetect,
NfcMessageTypeReadEMV,
NfcMessageTypeEmulateEMV,
NfcMessageTypeEmulate,
NfcMessageTypeField,
+ NfcMessageTypeReadMfUltralight,
NfcMessageTypeStop,
NfcMessageTypeExit,
// From Worker
@@ -92,6 +102,8 @@ typedef enum {
NfcMessageTypeDeviceNotFound,
NfcMessageTypeEMVFound,
NfcMessageTypeEMVNotFound,
+ NfcMessageTypeMfUlFound,
+ NfcMessageTypeMfUlNotFound,
} NfcMessageType;
typedef struct {
diff --git a/applications/nfc/nfc_views.c b/applications/nfc/nfc_views.c
index c3c7feee..769656b2 100644..100755
--- a/applications/nfc/nfc_views.c
+++ b/applications/nfc/nfc_views.c
@@ -150,6 +150,59 @@ void nfc_view_emulate_draw(Canvas* canvas, void* model) {
canvas_draw_str(canvas, 2, 52, "SAK: 20 ATQA: 00/04");
}
+void nfc_view_read_mf_ultralight_draw(Canvas* canvas, void* model) {
+ NfcViewReadModel* m = model;
+ canvas_clear(canvas);
+ canvas_set_font(canvas, FontPrimary);
+ char buffer[32];
+
+ if(m->found) {
+ canvas_draw_str(canvas, 0, 12, "Found Mifare Ultralight");
+ canvas_set_font(canvas, FontSecondary);
+ canvas_draw_str(canvas, 2, 22, "UID:");
+ for(uint8_t i = 0; i < sizeof(m->device.mf_ul_card.uid); i++) {
+ snprintf(
+ buffer + (i * 2), sizeof(buffer) - (i * 2), "%02X", m->device.mf_ul_card.uid[i]);
+ }
+ buffer[sizeof(m->device.mf_ul_card.uid) * 2] = 0;
+ canvas_draw_str(canvas, 18, 22, buffer);
+
+ uint8_t man_bl_size = sizeof(m->device.mf_ul_card.man_block);
+ canvas_draw_str(canvas, 2, 32, "Manufacturer block:");
+ for(uint8_t i = 0; i < man_bl_size / 2; i++) {
+ snprintf(
+ buffer + (i * 2),
+ sizeof(buffer) - (i * 2),
+ "%02X",
+ m->device.mf_ul_card.man_block[i]);
+ }
+ buffer[man_bl_size] = 0;
+ canvas_draw_str(canvas, 2, 42, buffer);
+
+ for(uint8_t i = 0; i < man_bl_size / 2; i++) {
+ snprintf(
+ buffer + (i * 2),
+ sizeof(buffer) - (i * 2),
+ "%02X",
+ m->device.mf_ul_card.man_block[man_bl_size / 2 + i]);
+ }
+ buffer[man_bl_size] = 0;
+ canvas_draw_str(canvas, 2, 52, buffer);
+
+ canvas_draw_str(canvas, 2, 62, "OTP: ");
+ for(uint8_t i = 0; i < sizeof(m->device.mf_ul_card.otp); i++) {
+ snprintf(
+ buffer + (i * 2), sizeof(buffer) - (i * 2), "%02X", m->device.mf_ul_card.otp[i]);
+ }
+ buffer[sizeof(m->device.mf_ul_card.otp) * 2] = 0;
+ canvas_draw_str(canvas, 22, 62, buffer);
+ } else {
+ canvas_draw_str(canvas, 0, 12, "Searching");
+ canvas_set_font(canvas, FontSecondary);
+ canvas_draw_str(canvas, 2, 22, "Place card to the back");
+ }
+}
+
void nfc_view_field_draw(Canvas* canvas, void* model) {
canvas_clear(canvas);
canvas_set_font(canvas, FontPrimary);
diff --git a/applications/nfc/nfc_views.h b/applications/nfc/nfc_views.h
index 9a4dbc0c..5ba990e7 100644
--- a/applications/nfc/nfc_views.h
+++ b/applications/nfc/nfc_views.h
@@ -14,6 +14,7 @@ typedef enum {
NfcViewEmulateEMV,
NfcViewEmulate,
NfcViewField,
+ NfcViewReadMfUltralight,
NfcViewError,
} NfcView;
@@ -31,6 +32,7 @@ void nfc_view_read_emv_draw(Canvas* canvas, void* model);
void nfc_view_emulate_emv_draw(Canvas* canvas, void* model);
void nfc_view_emulate_draw(Canvas* canvas, void* model);
+void nfc_view_read_mf_ultralight_draw(Canvas* canvas, void* model);
void nfc_view_field_draw(Canvas* canvas, void* model);
diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c
index 78825789..b2957608 100644..100755
--- a/applications/nfc/nfc_worker.c
+++ b/applications/nfc/nfc_worker.c
@@ -1,6 +1,7 @@
#include "nfc_worker_i.h"
#include <api-hal.h>
#include "nfc_protocols/emv_decoder.h"
+#include "nfc_protocols/mifare_ultralight.h"
#define NFC_WORKER_TAG "nfc worker"
@@ -71,6 +72,8 @@ void nfc_worker_task(void* context) {
nfc_worker_emulate(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateField) {
nfc_worker_field(nfc_worker);
+ } else if(nfc_worker->state == NfcWorkerStateReadMfUltralight) {
+ nfc_worker_read_mf_ultralight(nfc_worker);
}
api_hal_nfc_deactivate();
nfc_worker_change_state(nfc_worker, NfcWorkerStateReady);
@@ -306,6 +309,126 @@ void nfc_worker_poll(NfcWorker* nfc_worker) {
}
}
+void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker) {
+ ReturnCode err;
+ rfalNfcDevice* dev_list;
+ uint8_t dev_cnt = 0;
+ uint8_t tx_buff[255] = {};
+ uint16_t tx_len = 0;
+ uint8_t* rx_buff;
+ uint16_t* rx_len;
+ MfUltralightRead mf_ul_read;
+
+ // Update screen before start searching
+ NfcMessage message = {.type = NfcMessageTypeMfUlNotFound};
+ while(nfc_worker->state == NfcWorkerStateReadMfUltralight) {
+ furi_check(
+ osMessageQueuePut(nfc_worker->message_queue, &message, 0, osWaitForever) == osOK);
+ api_hal_nfc_deactivate();
+ memset(&mf_ul_read, 0, sizeof(mf_ul_read));
+ if(api_hal_nfc_detect(&dev_list, &dev_cnt, 100, false)) {
+ if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCA &&
+ mf_ul_check_card_type(
+ dev_list[0].dev.nfca.sensRes.anticollisionInfo,
+ dev_list[0].dev.nfca.sensRes.platformInfo,
+ dev_list[0].dev.nfca.selRes.sak)) {
+ // Get Mifare Ultralight version
+ FURI_LOG_I(
+ NFC_WORKER_TAG, "Found Mifare Ultralight tag. Trying to get tag version");
+ tx_len = mf_ul_prepare_get_version(tx_buff);
+ err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
+ if(err == ERR_NONE) {
+ mf_ul_parse_get_version_response(rx_buff, &mf_ul_read);
+ FURI_LOG_I(
+ NFC_WORKER_TAG,
+ "Mifare Ultralight Type: %d, Pages: %d",
+ mf_ul_read.type,
+ mf_ul_read.pages_to_read);
+ } else if(err == ERR_TIMEOUT) {
+ FURI_LOG_W(
+ NFC_WORKER_TAG,
+ "Card doesn't respond to GET VERSION command. Reinit card and set default read parameters");
+ err = ERR_NONE;
+ mf_ul_set_default_version(&mf_ul_read);
+ // Reinit device
+ api_hal_nfc_deactivate();
+ if(!api_hal_nfc_detect(&dev_list, &dev_cnt, 100, false)) {
+ FURI_LOG_E(NFC_WORKER_TAG, "Lost connection. Restarting search");
+ message.type = NfcMessageTypeMfUlNotFound;
+ continue;
+ }
+ } else {
+ FURI_LOG_E(
+ NFC_WORKER_TAG,
+ "Error getting Mifare Ultralight version. Error code: %d",
+ err);
+ message.type = NfcMessageTypeMfUlNotFound;
+ continue;
+ }
+
+ // Dump Mifare Ultralight card
+ FURI_LOG_I(NFC_WORKER_TAG, "Trying to read pages");
+ if(mf_ul_read.support_fast_read) {
+ // Read card with FAST_READ command
+ tx_len = mf_ul_prepare_fast_read(tx_buff, 0x00, mf_ul_read.pages_to_read - 1);
+ err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
+ if(err == ERR_NONE) {
+ FURI_LOG_I(
+ NFC_WORKER_TAG,
+ "Fast read pages %d - %d succeed",
+ 0,
+ mf_ul_read.pages_to_read - 1);
+ memcpy(mf_ul_read.dump, rx_buff, mf_ul_read.pages_to_read * 4);
+ mf_ul_read.pages_readed = mf_ul_read.pages_to_read;
+ } else {
+ FURI_LOG_E(NFC_WORKER_TAG, "Fast read failed");
+ message.type = NfcMessageTypeMfUlNotFound;
+ continue;
+ }
+ } else {
+ // READ card with READ command (4 pages at a time)
+ for(uint8_t page = 0; page < mf_ul_read.pages_to_read; page += 4) {
+ tx_len = mf_ul_prepare_read(tx_buff, page);
+ err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
+ if(err == ERR_NONE) {
+ FURI_LOG_I(
+ NFC_WORKER_TAG, "Read pages %d - %d succeed", page, page + 3);
+ memcpy(&mf_ul_read.dump[page * 4], rx_buff, 4 * 4);
+ mf_ul_read.pages_readed += 4;
+ } else {
+ FURI_LOG_W(
+ NFC_WORKER_TAG, "Read pages %d - %d failed", page, page + 3);
+ }
+ }
+ }
+
+ // Fill message for nfc application
+ message.type = NfcMessageTypeMfUlFound;
+ memcpy(
+ message.device.mf_ul_card.uid,
+ dev_list[0].dev.nfca.nfcId1,
+ sizeof(message.device.mf_ul_card.uid));
+ memcpy(message.device.mf_ul_card.man_block, mf_ul_read.dump, 4 * 3);
+ memcpy(message.device.mf_ul_card.otp, &mf_ul_read.dump[4 * 3], 4);
+ for(uint8_t i = 0; i < mf_ul_read.pages_readed * 4; i += 4) {
+ printf("Page %2d: ", i / 4);
+ for(uint8_t j = 0; j < 4; j++) {
+ printf("%02X ", mf_ul_read.dump[i + j]);
+ }
+ printf("\r\n");
+ }
+ } else {
+ message.type = NfcMessageTypeMfUlNotFound;
+ FURI_LOG_W(NFC_WORKER_TAG, "Tag does not support Mifare Ultralight");
+ }
+ } else {
+ message.type = NfcMessageTypeMfUlNotFound;
+ FURI_LOG_W(NFC_WORKER_TAG, "Can't find any tags");
+ }
+ osDelay(100);
+ }
+}
+
void nfc_worker_emulate(NfcWorker* nfc_worker) {
while(nfc_worker->state == NfcWorkerStateEmulate) {
if(api_hal_nfc_listen(100)) {
diff --git a/applications/nfc/nfc_worker_i.h b/applications/nfc/nfc_worker_i.h
index ba85f4b6..a3ae0b48 100644
--- a/applications/nfc/nfc_worker_i.h
+++ b/applications/nfc/nfc_worker_i.h
@@ -38,3 +38,5 @@ void nfc_worker_poll(NfcWorker* nfc_worker);
void nfc_worker_emulate(NfcWorker* nfc_worker);
void nfc_worker_field(NfcWorker* nfc_worker);
+
+void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker);