From 1489e3e676b482e12bc55cccb21ac32cce7d6b8f Mon Sep 17 00:00:00 2001 From: g3gg0 Date: Tue, 29 Nov 2022 02:15:20 +0100 Subject: [PATCH] better layer separation for ISO15693 --- lib/nfc/nfc_worker.c | 16 ++++++------- lib/nfc/protocols/nfcv.c | 52 +++++++++++++++++++++------------------- lib/nfc/protocols/nfcv.h | 26 +++++++++++--------- lib/nfc/protocols/slix.c | 34 +++++++++++++------------- lib/nfc/protocols/slix.h | 4 ++-- 5 files changed, 69 insertions(+), 63 deletions(-) diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 2d2df759f..5b26a6cf1 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -181,7 +181,7 @@ void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) { furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCV); furi_hal_console_printf("Detect presence\r\n"); - ReturnCode ret = slix_l_get_random(nfcv_data); + ReturnCode ret = slix_get_random(nfcv_data); if(ret == ERR_NONE) { /* there is some chip, responding with a RAND */ @@ -207,13 +207,13 @@ void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) { nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); } - while(slix_l_get_random(NULL) == ERR_NONE) { + while(slix_get_random(NULL) == ERR_NONE) { furi_delay_ms(100); } furi_hal_console_printf(" => chip is already visible, wait for chip to disappear.\r\n"); nfc_worker->callback(NfcWorkerEventAborted, nfc_worker->context); - while(slix_l_get_random(NULL) == ERR_NONE) { + while(slix_get_random(NULL) == ERR_NONE) { furi_delay_ms(100); } @@ -233,14 +233,14 @@ void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) { key |= key_data[2] << 8; key |= key_data[3] << 0; - ret = slix_l_unlock(nfcv_data, 4); + ret = slix_unlock(nfcv_data, 4); } else { key = 0x7FFD6E5B; key_data[0] = key >> 24; key_data[1] = key >> 16; key_data[2] = key >> 8; key_data[3] = key >> 0; - ret = slix_l_unlock(nfcv_data, 4); + ret = slix_unlock(nfcv_data, 4); if(ret != ERR_NONE) { /* main key failed, trying second one */ @@ -251,7 +251,7 @@ void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) { furi_delay_ms(20); furi_hal_nfc_ll_txrx_on(); - if(slix_l_get_random(nfcv_data) != ERR_NONE) { + if(slix_get_random(nfcv_data) != ERR_NONE) { furi_hal_console_printf(" reset failed\r\n"); } @@ -260,7 +260,7 @@ void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) { key_data[1] = key >> 16; key_data[2] = key >> 8; key_data[3] = key >> 0; - ret = slix_l_unlock(nfcv_data, 4); + ret = slix_unlock(nfcv_data, 4); } } if(ret != ERR_NONE) { @@ -275,7 +275,7 @@ void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) { furi_hal_nfc_ll_txrx_on(); /* wait for disappearing */ - while(slix_l_get_random(NULL) == ERR_NONE) { + while(slix_get_random(NULL) == ERR_NONE) { furi_delay_ms(100); } } diff --git a/lib/nfc/protocols/nfcv.c b/lib/nfc/protocols/nfcv.c index 88fd7894e..b7a8dd7cb 100644 --- a/lib/nfc/protocols/nfcv.c +++ b/lib/nfc/protocols/nfcv.c @@ -310,40 +310,40 @@ static int nfcv_uidcmp(uint8_t *dst, uint8_t *src) { return 0; } -void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint8_t* payload, uint32_t payload_length) { +void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in, uint8_t* payload, uint32_t payload_length) { if(!payload_length) { return; } + NfcVData* nfcv_data = (NfcVData*)nfcv_data_in; NfcVEmuProtocolCtx* ctx = &nfcv_data->emu_protocol_ctx; - ctx->payload = payload; - ctx->flags = ctx->payload[0]; - ctx->command = ctx->payload[1]; + ctx->frame = payload; + ctx->frame_length = payload_length; + ctx->flags = ctx->frame[0]; + ctx->command = ctx->frame[1]; ctx->addressed = !(ctx->flags & RFAL_NFCV_REQ_FLAG_INVENTORY) && (ctx->flags & RFAL_NFCV_REQ_FLAG_ADDRESS); ctx->advanced = (ctx->command >= 0xA0); ctx->address_offset = 2 + (ctx->advanced ? 1 : 0); ctx->payload_offset = ctx->address_offset + (ctx->addressed ? 8 : 0); - ctx->address = &ctx->payload[ctx->address_offset]; ctx->response_flags = NfcVSendFlagsNormal; - bool handled = false; - /* first give control to the card specific protocol handler */ - if(nfcv_data->emu_protocol_handler != NULL) { - handled = nfcv_data->emu_protocol_handler(tx_rx, nfc_data, nfcv_data); + if(nfcv_data->emu_protocol_filter != NULL) { + if(nfcv_data->emu_protocol_filter(tx_rx, nfc_data, nfcv_data)) { + return; + } } - if(handled) { - return; - } - - if(ctx->addressed && nfcv_uidcmp(ctx->address, nfc_data->uid)) { - FURI_LOG_D(TAG, "addressed command 0x%02X, but not for us:", ctx->command); - FURI_LOG_D(TAG, " dest: %02X%02X%02X%02X%02X%02X%02X%02X", ctx->address[7], ctx->address[6], ctx->address[5], ctx->address[4], ctx->address[3], ctx->address[2], ctx->address[1], ctx->address[0]); - FURI_LOG_D(TAG, " our UID: %02X%02X%02X%02X%02X%02X%02X%02X", nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3], nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]); - return; + if(ctx->addressed) { + uint8_t* address = &ctx->frame[ctx->address_offset]; + if(nfcv_uidcmp(address, nfc_data->uid)) { + FURI_LOG_D(TAG, "addressed command 0x%02X, but not for us:", ctx->command); + FURI_LOG_D(TAG, " dest: %02X%02X%02X%02X%02X%02X%02X%02X", address[7], address[6], address[5], address[4], address[3], address[2], address[1], address[0]); + FURI_LOG_D(TAG, " our UID: %02X%02X%02X%02X%02X%02X%02X%02X", nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3], nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]); + return; + } } /* unfortunately our response is quicker than the original NFC tag which causes frame misses */ @@ -379,11 +379,11 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc case ISO15693_READ_MULTI_BLOCK: case ISO15693_READBLOCK: { - uint8_t block = ctx->payload[ctx->payload_offset]; + uint8_t block = ctx->frame[ctx->payload_offset]; uint8_t blocks = 1; if(ctx->command == ISO15693_READ_MULTI_BLOCK) { - blocks = ctx->payload[ctx->payload_offset + 1] + 1; + blocks = ctx->frame[ctx->payload_offset + 1] + 1; } if(block + blocks > nfcv_data->block_num) { @@ -400,23 +400,23 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc case ISO15693_WRITE_MULTI_BLOCK: case ISO15693_WRITEBLOCK: { - uint8_t block = ctx->payload[ctx->payload_offset]; + uint8_t block = ctx->frame[ctx->payload_offset]; uint8_t blocks = 1; uint8_t data_pos = 1; if(ctx->command == ISO15693_WRITE_MULTI_BLOCK) { - blocks = ctx->payload[ctx->payload_offset + 1] + 1; + blocks = ctx->frame[ctx->payload_offset + 1] + 1; data_pos++; } - uint8_t *data = &ctx->payload[ctx->payload_offset + data_pos]; + uint8_t *data = &ctx->frame[ctx->payload_offset + data_pos]; uint32_t data_len = nfcv_data->block_size * blocks; if(block + blocks > nfcv_data->block_num || ctx->payload_offset + data_len + 2 > payload_length) { ctx->response_buffer[0] = ISO15693_ERROR_CMD_NOT_REC; } else { ctx->response_buffer[0] = ISO15693_NOERROR; - memcpy(&nfcv_data->data[nfcv_data->block_size * block], &ctx->payload[ctx->payload_offset + data_pos], data_len); + memcpy(&nfcv_data->data[nfcv_data->block_size * block], &ctx->frame[ctx->payload_offset + data_pos], data_len); } nfcv_emu_send(tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags); @@ -464,6 +464,8 @@ void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) { furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_nfc); + nfcv_data->emu_protocol_handler = &nfcv_emu_handle_packet; + FURI_LOG_D(TAG, "Starting NfcV emulation"); FURI_LOG_D(TAG, " UID: %02X %02X %02X %02X %02X %02X %02X %02X", nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3], @@ -650,7 +652,7 @@ bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, Nf if(tx_rx->sniff_rx) { tx_rx->sniff_rx(frame_payload, frame_pos * 8, false, tx_rx->sniff_context); } - nfcv_emu_handle_packet(tx_rx, nfc_data, nfcv_data, frame_payload, frame_pos); + nfcv_data->emu_protocol_handler(tx_rx, nfc_data, nfcv_data, frame_payload, frame_pos); pulse_reader_start(nfcv_data->emu_air.reader_signal); ret = true; } diff --git a/lib/nfc/protocols/nfcv.h b/lib/nfc/protocols/nfcv.h index 14d9b1ed6..86f75b19e 100644 --- a/lib/nfc/protocols/nfcv.h +++ b/lib/nfc/protocols/nfcv.h @@ -122,19 +122,22 @@ typedef struct { typedef struct { - uint8_t* payload; - uint8_t flags; - uint8_t command; - bool addressed; - bool advanced; - uint8_t address_offset; - uint8_t payload_offset; - uint8_t* address; - uint8_t response_buffer[128]; - NfcVSendFlags response_flags; + uint8_t* frame; /* ISO15693-2 incoming raw data from air layer */ + uint8_t frame_length; /* ISO15693-2 length of incoming data */ + + uint8_t flags; /* ISO15693-3 flags of the header as specified */ + uint8_t command; /* ISO15693-3 command at offset 1 as specified */ + bool addressed; /* ISO15693-3 flags: addressed frame */ + bool advanced; /* ISO15693-3 command: advanced command */ + uint8_t address_offset; /* ISO15693-3 offset of the address in frame, if addressed is set */ + uint8_t payload_offset; /* ISO15693-3 offset of the payload in frame */ + + uint8_t response_buffer[128]; /* pre-allocated response buffer */ + NfcVSendFlags response_flags; /* flags to use when sending response */ } NfcVEmuProtocolCtx; -typedef bool (*NfcVEmuProtocolHandler) (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data); +typedef void (*NfcVEmuProtocolHandler) (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data, uint8_t* payload, uint32_t payload_length); +typedef bool (*NfcVEmuProtocolFilter) (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data); typedef struct { /* common ISO15693 fields */ @@ -151,6 +154,7 @@ typedef struct { NfcVEmuAir emu_air; NfcVEmuProtocolCtx emu_protocol_ctx; NfcVEmuProtocolHandler emu_protocol_handler; + NfcVEmuProtocolFilter emu_protocol_filter; /* runtime data */ char last_command[128]; diff --git a/lib/nfc/protocols/slix.c b/lib/nfc/protocols/slix.c index 49bc12e0e..abd76ee81 100644 --- a/lib/nfc/protocols/slix.c +++ b/lib/nfc/protocols/slix.c @@ -63,7 +63,7 @@ bool slix_l_check_card_type(FuriHalNfcDevData* nfc_data) { } -ReturnCode slix_l_get_random(NfcVData* data) { +ReturnCode slix_get_random(NfcVData* data) { uint16_t received = 0; uint8_t rxBuf[32]; @@ -91,7 +91,7 @@ ReturnCode slix_l_get_random(NfcVData* data) { return ret; } -ReturnCode slix_l_unlock(NfcVData* data, uint32_t password_id) { +ReturnCode slix_unlock(NfcVData* data, uint32_t password_id) { furi_assert(rand); uint16_t received = 0; @@ -148,7 +148,7 @@ ReturnCode slix_l_unlock(NfcVData* data, uint32_t password_id) { } -bool slix_generic_protocol_handler (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in, uint32_t password_supported) { +bool slix_generic_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in, uint32_t password_supported) { furi_assert(tx_rx); furi_assert(nfc_data); furi_assert(nfcv_data_in); @@ -186,13 +186,13 @@ bool slix_generic_protocol_handler (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevD } case ISO15693_CMD_NXP_SET_PASSWORD: { - uint8_t password_id = ctx->payload[ctx->payload_offset]; + uint8_t password_id = ctx->frame[ctx->payload_offset]; if(!(password_id & password_supported)) { break; } - uint8_t *password_xored = &ctx->payload[ctx->payload_offset + 1]; + uint8_t *password_xored = &ctx->frame[ctx->payload_offset + 1]; uint8_t *rand = slix->rand; uint8_t *password = NULL; uint8_t password_rcv[4]; @@ -269,7 +269,7 @@ bool slix_generic_protocol_handler (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevD return handled; } -bool slix_l_protocol_handler (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in) { +bool slix_l_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in) { furi_assert(tx_rx); furi_assert(nfc_data); furi_assert(nfcv_data_in); @@ -277,7 +277,7 @@ bool slix_l_protocol_handler (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* n bool handled = false; /* many SLIX share some of the functions, place that in a generic handler */ - if(slix_generic_protocol_handler(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_PRIVACY | SLIX_PASS_DESTROY | SLIX_PASS_EASAFI)) { + if(slix_generic_protocol_filter(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_PRIVACY | SLIX_PASS_DESTROY | SLIX_PASS_EASAFI)) { return true; } @@ -290,10 +290,10 @@ void slix_l_prepare(NfcVData* nfcv_data) { FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4)); FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF"); - nfcv_data->emu_protocol_handler = &slix_l_protocol_handler; + nfcv_data->emu_protocol_filter = &slix_l_protocol_filter; } -bool slix_s_protocol_handler (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in) { +bool slix_s_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in) { furi_assert(tx_rx); furi_assert(nfc_data); furi_assert(nfcv_data_in); @@ -301,7 +301,7 @@ bool slix_s_protocol_handler (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* n bool handled = false; /* many SLIX share some of the functions, place that in a generic handler */ - if(slix_generic_protocol_handler(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_ALL)) { + if(slix_generic_protocol_filter(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_ALL)) { return true; } @@ -314,10 +314,10 @@ void slix_s_prepare(NfcVData* nfcv_data) { FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4)); FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF"); - nfcv_data->emu_protocol_handler = &slix_s_protocol_handler; + nfcv_data->emu_protocol_filter = &slix_s_protocol_filter; } -bool slix_protocol_handler (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in) { +bool slix_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in) { furi_assert(tx_rx); furi_assert(nfc_data); furi_assert(nfcv_data_in); @@ -325,7 +325,7 @@ bool slix_protocol_handler (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc bool handled = false; /* many SLIX share some of the functions, place that in a generic handler */ - if(slix_generic_protocol_handler(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_EASAFI)) { + if(slix_generic_protocol_filter(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_EASAFI)) { return true; } @@ -338,10 +338,10 @@ void slix_prepare(NfcVData* nfcv_data) { FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4)); FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF"); - nfcv_data->emu_protocol_handler = &slix_protocol_handler; + nfcv_data->emu_protocol_filter = &slix_protocol_filter; } -bool slix2_protocol_handler (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in) { +bool slix2_protocol_filter (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, void* nfcv_data_in) { furi_assert(tx_rx); furi_assert(nfc_data); furi_assert(nfcv_data_in); @@ -349,7 +349,7 @@ bool slix2_protocol_handler (FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nf bool handled = false; /* many SLIX share some of the functions, place that in a generic handler */ - if(slix_generic_protocol_handler(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_ALL)) { + if(slix_generic_protocol_filter(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_ALL)) { return true; } @@ -362,5 +362,5 @@ void slix2_prepare(NfcVData* nfcv_data) { FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4)); FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF"); - nfcv_data->emu_protocol_handler = &slix2_protocol_handler; + nfcv_data->emu_protocol_filter = &slix2_protocol_filter; } diff --git a/lib/nfc/protocols/slix.h b/lib/nfc/protocols/slix.h index f30efacc1..e3c0e2076 100644 --- a/lib/nfc/protocols/slix.h +++ b/lib/nfc/protocols/slix.h @@ -36,8 +36,8 @@ bool slix_check_card_type(FuriHalNfcDevData* nfc_data); bool slix2_check_card_type(FuriHalNfcDevData* nfc_data); bool slix_s_check_card_type(FuriHalNfcDevData* nfc_data); bool slix_l_check_card_type(FuriHalNfcDevData* nfc_data); -ReturnCode slix_l_get_random(NfcVData* data); -ReturnCode slix_l_unlock(NfcVData* data, uint32_t password_id); +ReturnCode slix_get_random(NfcVData* data); +ReturnCode slix_unlock(NfcVData* data, uint32_t password_id); void slix_prepare(NfcVData* nfcv_data); void slix_s_prepare(NfcVData* nfcv_data);