From 384f365cffe14eaa1519c1166491cfdd05b276ba Mon Sep 17 00:00:00 2001 From: Willy-JL <49810075+Willy-JL@users.noreply.github.com> Date: Sat, 15 Mar 2025 03:08:24 +0000 Subject: [PATCH] Refactor CC parsing and dumping --- lib/nfc/protocols/type_4_tag/type_4_tag_i.c | 84 +++++++++++++++++++ lib/nfc/protocols/type_4_tag/type_4_tag_i.h | 5 ++ .../type_4_tag/type_4_tag_listener_i.c | 36 +------- .../type_4_tag/type_4_tag_poller_i.c | 42 +--------- 4 files changed, 93 insertions(+), 74 deletions(-) diff --git a/lib/nfc/protocols/type_4_tag/type_4_tag_i.c b/lib/nfc/protocols/type_4_tag/type_4_tag_i.c index d90911212..d0b0bf22e 100644 --- a/lib/nfc/protocols/type_4_tag/type_4_tag_i.c +++ b/lib/nfc/protocols/type_4_tag/type_4_tag_i.c @@ -1,5 +1,7 @@ #include "type_4_tag_i.h" +#include + #define TAG "Type4Tag" #define TYPE_4_TAG_FFF_NDEF_DATA_SIZE_KEY "NDEF Data Size" @@ -20,6 +22,88 @@ Type4TagError type_4_tag_process_error(Iso14443_4aError error) { } } +void type_4_tag_cc_dump(const Type4TagData* data, uint8_t* buf, size_t len) { + furi_check(len >= TYPE_4_TAG_T4T_CC_MIN_SIZE); + Type4TagCc* cc = (Type4TagCc*)buf; + + bit_lib_num_to_bytes_be(TYPE_4_TAG_T4T_CC_MIN_SIZE, sizeof(cc->len), (void*)&cc->len); + cc->t4t_vno = TYPE_4_TAG_T4T_CC_VNO; + bit_lib_num_to_bytes_be( + data->is_tag_specific ? MIN(data->chunk_max_read, TYPE_4_TAG_CHUNK_LEN) : + TYPE_4_TAG_CHUNK_LEN, + sizeof(cc->mle), + (void*)&cc->mle); + bit_lib_num_to_bytes_be( + data->is_tag_specific ? MIN(data->chunk_max_write, TYPE_4_TAG_CHUNK_LEN) : + TYPE_4_TAG_CHUNK_LEN, + sizeof(cc->mlc), + (void*)&cc->mlc); + + cc->tlv[0].type = Type4TagCcTlvTypeNdefFileCtrl; + cc->tlv[0].len = sizeof(cc->tlv[0].value.ndef_file_ctrl); + + bit_lib_num_to_bytes_be( + data->is_tag_specific ? data->ndef_file_id : TYPE_4_TAG_T4T_DEFAULT_FILE_ID, + sizeof(cc->tlv[0].value.ndef_file_ctrl.file_id), + (void*)&cc->tlv[0].value.ndef_file_ctrl.file_id); + bit_lib_num_to_bytes_be( + data->is_tag_specific ? data->ndef_max_len : TYPE_4_TAG_DEFAULT_SIZE, + sizeof(cc->tlv[0].value.ndef_file_ctrl.max_len), + (void*)&cc->tlv[0].value.ndef_file_ctrl.max_len); + cc->tlv[0].value.ndef_file_ctrl.read_perm = + data->is_tag_specific ? data->ndef_read_lock : TYPE_4_TAG_T4T_CC_RW_LOCK_NONE; + cc->tlv[0].value.ndef_file_ctrl.write_perm = + data->is_tag_specific ? data->ndef_write_lock : TYPE_4_TAG_T4T_CC_RW_LOCK_NONE; +} + +Type4TagError type_4_tag_cc_parse(Type4TagData* data, const BitBuffer* buf) { + const size_t cc_len = bit_buffer_get_size_bytes(buf); + if(cc_len < TYPE_4_TAG_T4T_CC_MIN_SIZE) { + FURI_LOG_E(TAG, "Unsupported T4T version"); + return Type4TagErrorWrongFormat; + } + + const Type4TagCc* cc = (const Type4TagCc*)bit_buffer_get_data(buf); + if(cc->t4t_vno != TYPE_4_TAG_T4T_CC_VNO) { + FURI_LOG_E(TAG, "Unsupported T4T version"); + return Type4TagErrorNotSupported; + } + + const Type4TagCcTlv* tlv = cc->tlv; + const Type4TagCcTlvNdefFileCtrl* ndef_file_ctrl = NULL; + const void* end = MIN((void*)cc + cc->len, (void*)cc + cc_len); + while((void*)tlv < end) { + if(tlv->type == Type4TagCcTlvTypeNdefFileCtrl) { + ndef_file_ctrl = &tlv->value.ndef_file_ctrl; + break; + } + + if(tlv->len < 0xFF) { + tlv = (void*)&tlv->value + tlv->len; + } else { + uint16_t len = bit_lib_bytes_to_num_be((void*)&tlv->len + 1, sizeof(uint16_t)); + tlv = (void*)&tlv->value + sizeof(len) + len; + } + } + if(!ndef_file_ctrl) { + FURI_LOG_E(TAG, "No NDEF file ctrl TLV"); + return Type4TagErrorWrongFormat; + } + + data->t4t_version.value = cc->t4t_vno; + data->chunk_max_read = bit_lib_bytes_to_num_be((void*)&cc->mle, sizeof(cc->mle)); + data->chunk_max_write = bit_lib_bytes_to_num_be((void*)&cc->mlc, sizeof(cc->mlc)); + data->ndef_file_id = + bit_lib_bytes_to_num_be((void*)&ndef_file_ctrl->file_id, sizeof(ndef_file_ctrl->file_id)); + data->ndef_max_len = + bit_lib_bytes_to_num_be((void*)&ndef_file_ctrl->max_len, sizeof(ndef_file_ctrl->max_len)) - + sizeof(uint16_t); + data->ndef_read_lock = ndef_file_ctrl->read_perm; + data->ndef_write_lock = ndef_file_ctrl->write_perm; + + return Type4TagErrorNone; +} + bool type_4_tag_ndef_data_load(Type4TagData* data, FlipperFormat* ff) { uint32_t ndef_data_size; if(!flipper_format_read_uint32(ff, TYPE_4_TAG_FFF_NDEF_DATA_SIZE_KEY, &ndef_data_size, 1)) { 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 cde715faa..35f8f6a2b 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 @@ -34,6 +34,7 @@ #define TYPE_4_TAG_T4T_CC_VNO (0x20) #define TYPE_4_TAG_T4T_DEFAULT_FILE_ID 0xE104 #define TYPE_4_TAG_T4T_CC_RW_LOCK_NONE 0x00 +#define TYPE_4_TAG_T4T_CC_MIN_SIZE (sizeof(Type4TagCc) + sizeof(Type4TagCcTlv)) // 4a layer adds 1..3 byte prefix, 3a layer adds 2 byte suffix and has 256 byte buffer #define TYPE_4_TAG_BUF_SIZE (256U - 3U - 2U) @@ -77,6 +78,10 @@ typedef struct FURI_PACKED { Type4TagError type_4_tag_process_error(Iso14443_4aError error); +void type_4_tag_cc_dump(const Type4TagData* data, uint8_t* buf, size_t len); + +Type4TagError type_4_tag_cc_parse(Type4TagData* data, const BitBuffer* buf); + // Load internal Type4Tag structures bool type_4_tag_ndef_data_load(Type4TagData* data, FlipperFormat* ff); 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 880769629..f8e799f59 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 @@ -104,7 +104,7 @@ static Type4TagError type_4_tag_listener_iso_read( } if(instance->state == Type4TagListenerStateSelectedCapabilityContainer) { - uint8_t cc_buf[sizeof(Type4TagCc) + sizeof(Type4TagCcTlv)]; + uint8_t cc_buf[TYPE_4_TAG_T4T_CC_MIN_SIZE]; if(offset >= sizeof(cc_buf)) { bit_buffer_append_bytes( instance->tx_buffer, @@ -112,39 +112,7 @@ static Type4TagError type_4_tag_listener_iso_read( sizeof(type_4_tag_offset_error_apdu)); return Type4TagErrorWrongFormat; } - Type4TagCc* cc = (Type4TagCc*)cc_buf; - bit_lib_num_to_bytes_be(sizeof(cc_buf), sizeof(cc->len), (void*)&cc->len); - cc->t4t_vno = TYPE_4_TAG_T4T_CC_VNO; - bit_lib_num_to_bytes_be( - instance->data->is_tag_specific ? - MIN(instance->data->chunk_max_read, TYPE_4_TAG_CHUNK_LEN) : - TYPE_4_TAG_CHUNK_LEN, - sizeof(cc->mle), - (void*)&cc->mle); - bit_lib_num_to_bytes_be( - instance->data->is_tag_specific ? - MIN(instance->data->chunk_max_write, TYPE_4_TAG_CHUNK_LEN) : - TYPE_4_TAG_CHUNK_LEN, - sizeof(cc->mlc), - (void*)&cc->mlc); - cc->tlv[0].type = Type4TagCcTlvTypeNdefFileCtrl; - cc->tlv[0].len = sizeof(cc->tlv[0].value.ndef_file_ctrl); - bit_lib_num_to_bytes_be( - instance->data->is_tag_specific ? instance->data->ndef_file_id : - TYPE_4_TAG_T4T_DEFAULT_FILE_ID, - sizeof(cc->tlv[0].value.ndef_file_ctrl.file_id), - (void*)&cc->tlv[0].value.ndef_file_ctrl.file_id); - bit_lib_num_to_bytes_be( - instance->data->is_tag_specific ? instance->data->ndef_max_len : - TYPE_4_TAG_DEFAULT_SIZE, - sizeof(cc->tlv[0].value.ndef_file_ctrl.max_len), - (void*)&cc->tlv[0].value.ndef_file_ctrl.max_len); - cc->tlv[0].value.ndef_file_ctrl.read_perm = instance->data->is_tag_specific ? - instance->data->ndef_read_lock : - TYPE_4_TAG_T4T_CC_RW_LOCK_NONE; - cc->tlv[0].value.ndef_file_ctrl.write_perm = instance->data->is_tag_specific ? - instance->data->ndef_write_lock : - TYPE_4_TAG_T4T_CC_RW_LOCK_NONE; + type_4_tag_cc_dump(instance->data, cc_buf, sizeof(cc_buf)); bit_buffer_append_bytes( instance->tx_buffer, cc_buf + offset, MIN(sizeof(cc_buf) - offset, le)); diff --git a/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.c b/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.c index 09f1febaf..cf0d14861 100644 --- a/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.c +++ b/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.c @@ -93,47 +93,9 @@ Type4TagError type_4_tag_poller_read_cc(Type4TagPoller* instance) { error = type_4_tag_apdu_trx(instance, instance->tx_buffer, instance->rx_buffer); if(error != Type4TagErrorNone) break; - const Type4TagCc* cc = (const Type4TagCc*)bit_buffer_get_data(instance->rx_buffer); - if(cc->t4t_vno != TYPE_4_TAG_T4T_CC_VNO) { - FURI_LOG_E(TAG, "Unsupported T4T version"); - error = Type4TagErrorNotSupported; - break; - } - - const Type4TagCcTlv* tlv = cc->tlv; - const Type4TagCcTlvNdefFileCtrl* ndef_file_ctrl = NULL; - while((void*)tlv < (void*)cc + cc->len) { - if(tlv->type == Type4TagCcTlvTypeNdefFileCtrl) { - ndef_file_ctrl = &tlv->value.ndef_file_ctrl; - break; - } - - if(tlv->len < 0xFF) { - tlv = (void*)&tlv->value + tlv->len; - } else { - uint16_t len = bit_lib_bytes_to_num_be((void*)&tlv->len + 1, sizeof(uint16_t)); - tlv = (void*)&tlv->value + sizeof(len) + len; - } - } - if(!ndef_file_ctrl) { - FURI_LOG_E(TAG, "No NDEF file ctrl TLV"); - error = Type4TagErrorWrongFormat; - break; - } - + error = type_4_tag_cc_parse(instance->data, instance->rx_buffer); + if(error != Type4TagErrorNone) break; instance->data->is_tag_specific = true; - instance->data->t4t_version.value = cc->t4t_vno; - instance->data->chunk_max_read = bit_lib_bytes_to_num_be((void*)&cc->mle, sizeof(cc->mle)); - instance->data->chunk_max_write = - bit_lib_bytes_to_num_be((void*)&cc->mlc, sizeof(cc->mlc)); - instance->data->ndef_file_id = bit_lib_bytes_to_num_be( - (void*)&ndef_file_ctrl->file_id, sizeof(ndef_file_ctrl->file_id)); - instance->data->ndef_max_len = - bit_lib_bytes_to_num_be( - (void*)&ndef_file_ctrl->max_len, sizeof(ndef_file_ctrl->max_len)) - - sizeof(uint16_t); - instance->data->ndef_read_lock = ndef_file_ctrl->read_perm; - instance->data->ndef_write_lock = ndef_file_ctrl->write_perm; FURI_LOG_D(TAG, "Detected NDEF file ID 0x%04X", instance->data->ndef_file_id); } while(false);