From 967eb06082b7f8cf6ca304a93a6bf5f7006dbaed Mon Sep 17 00:00:00 2001 From: Willy-JL <49810075+Willy-JL@users.noreply.github.com> Date: Sat, 15 Mar 2025 05:49:44 +0000 Subject: [PATCH] NFC: Handle writes to Type 4 Tag while emulating --- lib/nfc/protocols/type_4_tag/type_4_tag_i.h | 6 ++ .../type_4_tag/type_4_tag_listener_i.c | 79 +++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/lib/nfc/protocols/type_4_tag/type_4_tag_i.h b/lib/nfc/protocols/type_4_tag/type_4_tag_i.h index 35f8f6a2b..687728fc4 100644 --- a/lib/nfc/protocols/type_4_tag/type_4_tag_i.h +++ b/lib/nfc/protocols/type_4_tag/type_4_tag_i.h @@ -17,6 +17,12 @@ #define TYPE_4_TAG_ISO_READ_P_OFFSET_MAX (32767U) #define TYPE_4_TAG_ISO_READ_LE_FULL (0x00) +// ISO UPDATE BINARY command and parameters +#define TYPE_4_TAG_ISO_WRITE_CMD 0x00, 0xD6 +#define TYPE_4_TAG_ISO_WRITE_P1_ID_MASK (1 << 7) +#define TYPE_4_TAG_ISO_WRITE_P_BEGINNING 0x00, 0x00 +#define TYPE_4_TAG_ISO_WRITE_LE_EMPTY (0x00) + // Common APDU parameters and values #define TYPE_4_TAG_ISO_STATUS_LEN (2U) #define TYPE_4_TAG_ISO_STATUS_SUCCESS 0x90, 0x00 diff --git a/lib/nfc/protocols/type_4_tag/type_4_tag_listener_i.c b/lib/nfc/protocols/type_4_tag/type_4_tag_listener_i.c index f8e799f59..940aca9e1 100644 --- a/lib/nfc/protocols/type_4_tag/type_4_tag_listener_i.c +++ b/lib/nfc/protocols/type_4_tag/type_4_tag_listener_i.c @@ -161,6 +161,81 @@ static Type4TagError type_4_tag_listener_iso_read( return Type4TagErrorCustomCommand; } +static Type4TagError type_4_tag_listener_iso_write( + Type4TagListener* instance, + uint8_t p1, + uint8_t p2, + size_t lc, + const uint8_t* data, + size_t le) { + UNUSED(le); + + size_t offset; + if(p1 & TYPE_4_TAG_ISO_WRITE_P1_ID_MASK) { + bit_buffer_append_bytes( + instance->tx_buffer, type_4_tag_no_support_apdu, sizeof(type_4_tag_no_support_apdu)); + return Type4TagErrorCustomCommand; + } else { + offset = (p1 << 8) + p2; + } + + if(instance->state == Type4TagListenerStateSelectedCapabilityContainer) { + bit_buffer_append_bytes( + instance->tx_buffer, type_4_tag_no_support_apdu, sizeof(type_4_tag_no_support_apdu)); + return Type4TagErrorNotSupported; + } + + if(instance->state == Type4TagListenerStateSelectedNdefMessage) { + if(offset + lc > (instance->data->is_tag_specific ? instance->data->ndef_max_len : + TYPE_4_TAG_DEFAULT_SIZE)) { + bit_buffer_append_bytes( + instance->tx_buffer, + type_4_tag_offset_error_apdu, + sizeof(type_4_tag_offset_error_apdu)); + return Type4TagErrorWrongFormat; + } + + const size_t ndef_file_len = simple_array_get_count(instance->data->ndef_data); + size_t ndef_file_len_new = ndef_file_len; + if(offset < sizeof(uint16_t)) { + const uint8_t write_len = sizeof(uint16_t) - offset; + ndef_file_len_new = bit_lib_bytes_to_num_be(data, write_len); + offset = sizeof(uint16_t); + data += offset; + lc -= write_len; + } + offset -= sizeof(uint16_t); + + ndef_file_len_new = MAX(ndef_file_len_new, offset + lc); + if(ndef_file_len_new != ndef_file_len) { + SimpleArray* ndef_data_temp = simple_array_alloc(&simple_array_config_uint8_t); + if(ndef_file_len_new > 0) { + simple_array_init(ndef_data_temp, ndef_file_len_new); + if(ndef_file_len > 0) { + memcpy( + simple_array_get_data(ndef_data_temp), + simple_array_get_data(instance->data->ndef_data), + MIN(ndef_file_len_new, ndef_file_len)); + } + } + simple_array_copy(instance->data->ndef_data, ndef_data_temp); + simple_array_free(ndef_data_temp); + } + + if(ndef_file_len_new > 0 && lc > 0) { + uint8_t* ndef_data = simple_array_get_data(instance->data->ndef_data); + memcpy(&ndef_data[offset], data, lc); + } + bit_buffer_append_bytes( + instance->tx_buffer, type_4_tag_success_apdu, sizeof(type_4_tag_success_apdu)); + return Type4TagErrorNone; + } + + bit_buffer_append_bytes( + instance->tx_buffer, type_4_tag_not_found_apdu, sizeof(type_4_tag_not_found_apdu)); + return Type4TagErrorCustomCommand; +} + static const Type4TagListenerApduCommand type_4_tag_listener_commands[] = { { .cla_ins = {TYPE_4_TAG_ISO_SELECT_CMD}, @@ -170,6 +245,10 @@ static const Type4TagListenerApduCommand type_4_tag_listener_commands[] = { .cla_ins = {TYPE_4_TAG_ISO_READ_CMD}, .handler = type_4_tag_listener_iso_read, }, + { + .cla_ins = {TYPE_4_TAG_ISO_WRITE_CMD}, + .handler = type_4_tag_listener_iso_write, + }, }; Type4TagError