NFC: Detect Type 4 Tag platform (eg DESFire)

This commit is contained in:
Willy-JL
2025-03-18 06:28:04 +00:00
parent 0af703d5ee
commit 121ce315c1
6 changed files with 104 additions and 6 deletions

View File

@@ -251,8 +251,7 @@ static bool mf_desfire_poller_detect(NfcGenericEvent event, void* context) {
MfDesfireError error = mf_desfire_poller_read_key_version(instance, 0, &key_version);
if(error != MfDesfireErrorNone) break;
MfDesfireVersion version = {};
error = mf_desfire_poller_read_version(instance, &version);
error = mf_desfire_poller_read_version(instance, &instance->data->version);
if(error != MfDesfireErrorNone) break;
protocol_detected = true;

View File

@@ -1,6 +1,7 @@
#include "type_4_tag_i.h"
#define TYPE_4_TAG_PROTOCOL_NAME "Type 4 Tag"
#define TYPE_4_TAG_SHORT_NAME "T4T"
const NfcDeviceBase nfc_device_type_4_tag = {
.protocol_name = TYPE_4_TAG_PROTOCOL_NAME,
@@ -21,6 +22,9 @@ const NfcDeviceBase nfc_device_type_4_tag = {
Type4TagData* type_4_tag_alloc(void) {
Type4TagData* data = malloc(sizeof(Type4TagData));
data->iso14443_4a_data = iso14443_4a_alloc();
data->device_name = furi_string_alloc();
data->platform_name_full = furi_string_alloc();
data->platform_name_short = furi_string_alloc();
data->ndef_data = simple_array_alloc(&simple_array_config_uint8_t);
return data;
}
@@ -30,6 +34,9 @@ void type_4_tag_free(Type4TagData* data) {
type_4_tag_reset(data);
simple_array_free(data->ndef_data);
furi_string_free(data->platform_name_short);
furi_string_free(data->platform_name_full);
furi_string_free(data->device_name);
iso14443_4a_free(data->iso14443_4a_data);
free(data);
}
@@ -40,6 +47,9 @@ void type_4_tag_reset(Type4TagData* data) {
iso14443_4a_reset(data->iso14443_4a_data);
data->is_tag_specific = false;
furi_string_reset(data->device_name);
furi_string_reset(data->platform_name_full);
furi_string_reset(data->platform_name_short);
data->t4t_version.value = 0;
data->chunk_max_read = 0;
data->chunk_max_write = 0;
@@ -60,6 +70,9 @@ void type_4_tag_copy(Type4TagData* data, const Type4TagData* other) {
iso14443_4a_copy(data->iso14443_4a_data, other->iso14443_4a_data);
data->is_tag_specific = other->is_tag_specific;
furi_string_set(data->device_name, other->device_name);
furi_string_set(data->platform_name_full, other->platform_name_full);
furi_string_set(data->platform_name_short, other->platform_name_short);
data->t4t_version.value = other->t4t_version.value;
data->chunk_max_read = other->chunk_max_read;
data->chunk_max_write = other->chunk_max_write;
@@ -137,9 +150,19 @@ bool type_4_tag_is_equal(const Type4TagData* data, const Type4TagData* other) {
}
const char* type_4_tag_get_device_name(const Type4TagData* data, NfcDeviceNameType name_type) {
UNUSED(data);
UNUSED(name_type);
return TYPE_4_TAG_PROTOCOL_NAME;
FuriString* platform_name = name_type == NfcDeviceNameTypeFull ? data->platform_name_full :
data->platform_name_short;
if(furi_string_empty(platform_name)) {
return TYPE_4_TAG_PROTOCOL_NAME;
}
furi_string_printf(
data->device_name,
"%s%c(%s)",
name_type == NfcDeviceNameTypeFull ? TYPE_4_TAG_PROTOCOL_NAME : TYPE_4_TAG_SHORT_NAME,
name_type == NfcDeviceNameTypeFull ? '\n' : ' ',
furi_string_get_cstr(platform_name));
furi_string_replace_str(data->device_name, "Mifare", "MIFARE");
return furi_string_get_cstr(data->device_name);
}
const uint8_t* type_4_tag_get_uid(const Type4TagData* data, size_t* uid_len) {

View File

@@ -19,10 +19,20 @@ typedef enum {
Type4TagErrorCustomCommand,
} Type4TagError;
typedef enum {
Type4TagPlatformUnknown,
Type4TagPlatformNtag4xx,
Type4TagPlatformMfDesfire,
} Type4TagPlatform;
typedef struct {
Iso14443_4aData* iso14443_4a_data;
FuriString* device_name;
// Tag specific data
bool is_tag_specific;
Type4TagPlatform platform;
FuriString* platform_name_full;
FuriString* platform_name_short;
union {
struct {
uint8_t minor : 4;

View File

@@ -62,10 +62,23 @@ static NfcCommand type_4_tag_poller_handler_request_mode(Type4TagPoller* instanc
type_4_tag_copy(instance->data, instance->type_4_tag_event.data->poller_mode.data);
}
instance->state = Type4TagPollerStateSelectApplication;
instance->state = Type4TagPollerStateDetectPlatform;
return command;
}
static NfcCommand type_4_tag_poller_handler_detect_platform(Type4TagPoller* instance) {
instance->error = type_4_tag_poller_detect_platform(instance);
iso14443_4a_poller_halt(instance->iso14443_4a_poller);
if(instance->error == Type4TagErrorNone) {
FURI_LOG_D(TAG, "Detect platform success");
} else {
FURI_LOG_W(TAG, "Failed to detect platform");
}
instance->state = Type4TagPollerStateSelectApplication;
return NfcCommandContinue;
}
static NfcCommand type_4_tag_poller_handler_select_app(Type4TagPoller* instance) {
instance->error = type_4_tag_poller_select_app(instance);
if(instance->error == Type4TagErrorNone) {
@@ -199,6 +212,7 @@ static NfcCommand type_4_tag_poller_handler_success(Type4TagPoller* instance) {
static const Type4TagPollerReadHandler type_4_tag_poller_read_handler[Type4TagPollerStateNum] = {
[Type4TagPollerStateIdle] = type_4_tag_poller_handler_idle,
[Type4TagPollerStateRequestMode] = type_4_tag_poller_handler_request_mode,
[Type4TagPollerStateDetectPlatform] = type_4_tag_poller_handler_detect_platform,
[Type4TagPollerStateSelectApplication] = type_4_tag_poller_handler_select_app,
[Type4TagPollerStateReadCapabilityContainer] = type_4_tag_poller_handler_read_cc,
[Type4TagPollerStateReadNdefMessage] = type_4_tag_poller_handler_read_ndef,

View File

@@ -3,6 +3,9 @@
#include <bit_lib/bit_lib.h>
#include <nfc/nfc_device.h>
#include <nfc/protocols/mf_desfire/mf_desfire_poller_defs.h>
#define TAG "Type4TagPoller"
Type4TagError type_4_tag_apdu_trx(Type4TagPoller* instance, BitBuffer* tx_buf, BitBuffer* rx_buf) {
@@ -178,6 +181,52 @@ static Type4TagError type_5_tag_poller_iso_write(
return Type4TagErrorNone;
}
Type4TagError type_4_tag_poller_detect_platform(Type4TagPoller* instance) {
furi_check(instance);
Iso14443_4aPollerEvent iso14443_4a_event = {
.type = Iso14443_4aPollerEventTypeReady,
.data = NULL,
};
NfcGenericEvent event = {
.protocol = NfcProtocolIso14443_4a,
.instance = instance->iso14443_4a_poller,
.event_data = &iso14443_4a_event,
};
Type4TagPlatform platform = Type4TagPlatformUnknown;
NfcDevice* device = nfc_device_alloc();
do {
FURI_LOG_D(TAG, "Detect DESFire");
NfcGenericInstance* mf_des = mf_desfire_poller.alloc(instance->iso14443_4a_poller);
if(mf_desfire_poller.detect(event, mf_des)) {
platform = Type4TagPlatformMfDesfire;
nfc_device_set_data(device, NfcProtocolMfDesfire, mf_desfire_poller.get_data(mf_des));
}
mf_desfire_poller.free(mf_des);
if(platform != Type4TagPlatformUnknown) break;
// FIXME: detect NTAG4xx
} while(false);
if(platform != Type4TagPlatformUnknown) {
furi_string_set(
instance->data->platform_name_full,
nfc_device_get_name(device, NfcDeviceNameTypeFull));
furi_string_set(
instance->data->platform_name_short,
nfc_device_get_name(device, NfcDeviceNameTypeShort));
} else {
furi_string_reset(instance->data->platform_name_full);
furi_string_reset(instance->data->platform_name_short);
}
instance->data->platform = platform;
nfc_device_free(device);
return platform != Type4TagPlatformUnknown ? Type4TagErrorNone : Type4TagErrorNotSupported;
}
Type4TagError type_4_tag_poller_select_app(Type4TagPoller* instance) {
furi_check(instance);

View File

@@ -11,6 +11,7 @@ extern "C" {
typedef enum {
Type4TagPollerStateIdle,
Type4TagPollerStateRequestMode,
Type4TagPollerStateDetectPlatform,
Type4TagPollerStateSelectApplication,
Type4TagPollerStateReadCapabilityContainer,
Type4TagPollerStateReadNdefMessage,
@@ -41,6 +42,8 @@ struct Type4TagPoller {
const Type4TagData* type_4_tag_poller_get_data(Type4TagPoller* instance);
Type4TagError type_4_tag_poller_detect_platform(Type4TagPoller* instance);
Type4TagError type_4_tag_poller_select_app(Type4TagPoller* instance);
Type4TagError type_4_tag_poller_read_cc(Type4TagPoller* instance);