From 297cb061cbf76038d9367833f8be888c7dee9b49 Mon Sep 17 00:00:00 2001 From: turbocool3r Date: Fri, 5 Jul 2024 16:30:38 +0300 Subject: [PATCH] Add support for custom version and signature data for MF0 / NTAG emulator. --- docs/protocol.md | 16 ++ firmware/application/src/app_cmd.c | 38 ++++ firmware/application/src/data_cmd.h | 4 + .../src/rfid/nfctag/hf/nfc_mf0_ntag.c | 178 +++++++++++++----- .../src/rfid/nfctag/hf/nfc_mf0_ntag.h | 25 ++- software/script/chameleon_cli_unit.py | 50 ++++- software/script/chameleon_cmd.py | 24 +++ software/script/chameleon_enum.py | 6 +- 8 files changed, 284 insertions(+), 57 deletions(-) diff --git a/docs/protocol.md b/docs/protocol.md index 0b41523..4c5e05c 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -404,6 +404,22 @@ Notes: * Command: 2 + `n * 4` bytes: one for first page index, one for count of pages to be read, `n * 4` for `n` pages data. * Response: no data * CLI: unused +### 4023: MF0_NTAG_GET_VERSION_DATA +* Command: no data +* Response: 8 version data bytes. +* CLI: cf `hf mfu econfig` +### 4024: MF0_NTAG_SET_VERSION_DATA +* Command: 8 version data bytes. +* Response: no data +* CLI: cf `hf mfu econfig --set-version ` +### 4025: MF0_NTAG_GET_SIGNATURE_DATA +* Command: no data +* Response: 32 signature data bytes. +* CLI: cf `hf mfu econfig` +### 4026: MF0_NTAG_SET_SIGNATURE_DATA +* Command: 32 signature data bytes. +* Response: no data +* CLI: cf `hf mfu econfig --set-signature ` ### 5000: EM410X_SET_EMU_ID * Command: 5 bytes. `id[5]`. ID as 5 bytes. * Response: no data diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index e6bdae5..93d74df 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -849,6 +849,40 @@ static data_frame_tx_t *cmd_processor_mf0_ntag_read_emu_page_data(uint16_t cmd, return data_frame_make(cmd, STATUS_SUCCESS, pages_count * NFC_TAG_MF0_NTAG_DATA_SIZE, &info->memory[page_index][0]); } +static data_frame_tx_t *cmd_processor_mf0_ntag_get_version_data(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { + uint8_t *version_data = nfc_tag_mf0_ntag_get_version_data(); + if (version_data == NULL) return data_frame_make(cmd, STATUS_INVALID_SLOT_TYPE, 0, NULL); + + return data_frame_make(cmd, STATUS_SUCCESS, NFC_TAG_MF0_NTAG_VER_SIZE, version_data); +} + +static data_frame_tx_t *cmd_processor_mf0_ntag_set_version_data(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { + if (length != 8) return data_frame_make(cmd, STATUS_INVALID_PARAMS, 0, NULL); + + uint8_t *version_data = nfc_tag_mf0_ntag_get_version_data(); + if (version_data == NULL) return data_frame_make(cmd, STATUS_INVALID_SLOT_TYPE, 0, NULL); + memcpy(version_data, data, NFC_TAG_MF0_NTAG_VER_SIZE); + + return data_frame_make(cmd, STATUS_SUCCESS, 0, NULL); +} + +static data_frame_tx_t *cmd_processor_mf0_ntag_get_signature_data(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { + uint8_t *signature_data = nfc_tag_mf0_ntag_get_signature_data(); + if (signature_data == NULL) return data_frame_make(cmd, STATUS_INVALID_SLOT_TYPE, 0, NULL); + + return data_frame_make(cmd, STATUS_SUCCESS, NFC_TAG_MF0_NTAG_SIG_SIZE, signature_data); +} + +static data_frame_tx_t *cmd_processor_mf0_ntag_set_signature_data(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { + if (length != NFC_TAG_MF0_NTAG_SIG_SIZE) return data_frame_make(cmd, STATUS_INVALID_PARAMS, 0, NULL); + + uint8_t *signature_data = nfc_tag_mf0_ntag_get_signature_data(); + if (signature_data == NULL) return data_frame_make(cmd, STATUS_INVALID_SLOT_TYPE, 0, NULL); + memcpy(signature_data, data, NFC_TAG_MF0_NTAG_SIG_SIZE); + + return data_frame_make(cmd, STATUS_SUCCESS, 0, NULL); +} + static data_frame_tx_t *cmd_processor_hf14a_set_anti_coll_data(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { // uidlen[1]|uid[uidlen]|atqa[2]|sak[1]|atslen[1]|ats[atslen] // dynamic length, so no struct @@ -1190,6 +1224,10 @@ static cmd_data_map_t m_data_cmd_map[] = { { DATA_CMD_MF0_NTAG_SET_UID_MAGIC_MODE, NULL, cmd_processor_mf0_ntag_set_uid_mode, NULL }, { DATA_CMD_MF0_NTAG_READ_EMU_PAGE_DATA, NULL, cmd_processor_mf0_ntag_read_emu_page_data, NULL }, { DATA_CMD_MF0_NTAG_WRITE_EMU_PAGE_DATA, NULL, cmd_processor_mf0_ntag_write_emu_page_data, NULL }, + { DATA_CMD_MF0_NTAG_GET_VERSION_DATA, NULL, cmd_processor_mf0_ntag_get_version_data, NULL }, + { DATA_CMD_MF0_NTAG_SET_VERSION_DATA, NULL, cmd_processor_mf0_ntag_set_version_data, NULL }, + { DATA_CMD_MF0_NTAG_GET_SIGNATURE_DATA, NULL, cmd_processor_mf0_ntag_get_signature_data, NULL }, + { DATA_CMD_MF0_NTAG_SET_SIGNATURE_DATA, NULL, cmd_processor_mf0_ntag_set_signature_data, NULL }, { DATA_CMD_EM410X_SET_EMU_ID, NULL, cmd_processor_em410x_set_emu_id, NULL }, { DATA_CMD_EM410X_GET_EMU_ID, NULL, cmd_processor_em410x_get_emu_id, NULL }, diff --git a/firmware/application/src/data_cmd.h b/firmware/application/src/data_cmd.h index 2f5b7c9..fae143a 100644 --- a/firmware/application/src/data_cmd.h +++ b/firmware/application/src/data_cmd.h @@ -110,6 +110,10 @@ #define DATA_CMD_MF0_NTAG_SET_UID_MAGIC_MODE (4020) #define DATA_CMD_MF0_NTAG_READ_EMU_PAGE_DATA (4021) #define DATA_CMD_MF0_NTAG_WRITE_EMU_PAGE_DATA (4022) +#define DATA_CMD_MF0_NTAG_GET_VERSION_DATA (4023) +#define DATA_CMD_MF0_NTAG_SET_VERSION_DATA (4024) +#define DATA_CMD_MF0_NTAG_GET_SIGNATURE_DATA (4025) +#define DATA_CMD_MF0_NTAG_SET_SIGNATURE_DATA (4026) // // ****************************************************************** diff --git a/firmware/application/src/rfid/nfctag/hf/nfc_mf0_ntag.c b/firmware/application/src/rfid/nfctag/hf/nfc_mf0_ntag.c index db4f68a..8411552 100644 --- a/firmware/application/src/rfid/nfctag/hf/nfc_mf0_ntag.c +++ b/firmware/application/src/rfid/nfctag/hf/nfc_mf0_ntag.c @@ -100,6 +100,7 @@ NRF_LOG_MODULE_REGISTER(); // SIGNATURE Length #define SIGNATURE_LENGTH 32 +#define PAGES_PER_VERSION (NFC_TAG_MF0_NTAG_VER_SIZE / NFC_TAG_MF0_NTAG_DATA_SIZE) // Since all counters are 24-bit and each currently supported tag that supports counters // has password authentication we store the auth attempts counter in the last bit of the @@ -174,7 +175,7 @@ static int get_nr_pages_by_tag_type(tag_specific_type_t tag_type) { return nr_pages; } -static int get_nr_mem_pages_by_tag_type(tag_specific_type_t tag_type) { +static int get_total_pages_by_tag_type(tag_specific_type_t tag_type) { int nr_pages = 0; switch (tag_type) { @@ -185,19 +186,19 @@ static int get_nr_mem_pages_by_tag_type(tag_specific_type_t tag_type) { nr_pages = MF0ICU2_PAGES; break; case TAG_TYPE_MF0UL11: - nr_pages = MF0UL11_PAGES_WITH_CTRS; + nr_pages = MF0UL11_TOTAL_PAGES; break; case TAG_TYPE_MF0UL21: - nr_pages = MF0UL21_PAGES_WITH_CTRS; + nr_pages = MF0UL21_TOTAL_PAGES; break; case TAG_TYPE_NTAG_213: - nr_pages = NTAG213_PAGES_WITH_CTR; + nr_pages = NTAG213_TOTAL_PAGES; break; case TAG_TYPE_NTAG_215: - nr_pages = NTAG215_PAGES_WITH_CTR; + nr_pages = NTAG215_TOTAL_PAGES; break; case TAG_TYPE_NTAG_216: - nr_pages = NTAG216_PAGES_WITH_CTR; + nr_pages = NTAG216_TOTAL_PAGES; break; default: ASSERT(false); @@ -260,51 +261,98 @@ static bool is_ntag() { } } -static void handle_get_version_command() { - NRF_LOG_DEBUG("handling GET_VERSION"); +int get_version_page_by_tag_type(tag_specific_type_t tag_type) { + int version_page_off; + + switch (tag_type) { + case TAG_TYPE_MF0UL11: + version_page_off = MF0UL11_PAGES + MF0ULx1_NUM_CTRS; + break; + case TAG_TYPE_MF0UL21: + version_page_off = MF0UL21_PAGES + MF0ULx1_NUM_CTRS; + break; + case TAG_TYPE_NTAG_213: + version_page_off = NTAG213_PAGES + NTAG_NUM_CTRS; + break; + case TAG_TYPE_NTAG_215: + version_page_off = NTAG215_PAGES + NTAG_NUM_CTRS; + break; + case TAG_TYPE_NTAG_216: + version_page_off = NTAG216_PAGES + NTAG_NUM_CTRS; + break; + default: + version_page_off = -1; + break; + } + + return version_page_off; +} + +int get_signature_page_by_tag_type(tag_specific_type_t tag_type) { + int version_page_off; switch (m_tag_type) { case TAG_TYPE_MF0UL11: - m_tag_tx_buffer.tx_buffer[6] = MF0UL11_VERSION_STORAGE_SIZE; - m_tag_tx_buffer.tx_buffer[2] = MF0ULx1_VERSION_PRODUCT_TYPE; + version_page_off = MF0UL11_PAGES + MF0ULx1_NUM_CTRS + PAGES_PER_VERSION; break; case TAG_TYPE_MF0UL21: - m_tag_tx_buffer.tx_buffer[6] = MF0UL21_VERSION_STORAGE_SIZE; - m_tag_tx_buffer.tx_buffer[2] = MF0ULx1_VERSION_PRODUCT_TYPE; + version_page_off = MF0UL21_PAGES + MF0ULx1_NUM_CTRS + PAGES_PER_VERSION; break; case TAG_TYPE_NTAG_213: - m_tag_tx_buffer.tx_buffer[6] = NTAG213_VERSION_STORAGE_SIZE; - m_tag_tx_buffer.tx_buffer[2] = NTAG_VERSION_PRODUCT_TYPE; + version_page_off = NTAG213_PAGES + NTAG_NUM_CTRS + PAGES_PER_VERSION; break; case TAG_TYPE_NTAG_215: - m_tag_tx_buffer.tx_buffer[6] = NTAG215_VERSION_STORAGE_SIZE; - m_tag_tx_buffer.tx_buffer[2] = NTAG_VERSION_PRODUCT_TYPE; + version_page_off = NTAG215_PAGES + NTAG_NUM_CTRS + PAGES_PER_VERSION; break; case TAG_TYPE_NTAG_216: - m_tag_tx_buffer.tx_buffer[6] = NTAG216_VERSION_STORAGE_SIZE; - m_tag_tx_buffer.tx_buffer[2] = NTAG_VERSION_PRODUCT_TYPE; + version_page_off = NTAG216_PAGES + NTAG_NUM_CTRS + PAGES_PER_VERSION; break; default: - NRF_LOG_WARNING("current card type does not support GET_VERSION"); - // MF0ICU1 and MF0ICU2 do not support GET_VERSION - nfc_tag_14a_tx_nbit(NAK_INVALID_OPERATION_TBIV, 4); - return; + version_page_off = -1; + break; } - m_tag_tx_buffer.tx_buffer[0] = VERSION_FIXED_HEADER; - m_tag_tx_buffer.tx_buffer[1] = VERSION_VENDOR_ID; - m_tag_tx_buffer.tx_buffer[3] = VERSION_PRODUCT_SUBTYPE_50pF; // TODO: make configurable for MF0ULx1 - m_tag_tx_buffer.tx_buffer[4] = VERSION_MAJOR_PRODUCT; - m_tag_tx_buffer.tx_buffer[5] = VERSION_MINOR_PRODUCT; - m_tag_tx_buffer.tx_buffer[7] = VERSION_PROTOCOL_TYPE; + return version_page_off; +} - NRF_LOG_INFO( - "replying with %08x%08x", - U32HTONL(*(uint32_t *)&m_tag_tx_buffer.tx_buffer[0]), - U32HTONL(*(uint32_t *)&m_tag_tx_buffer.tx_buffer[1]) - ); +uint8_t *nfc_tag_mf0_ntag_get_version_data() { + int version_page = get_version_page_by_tag_type(m_tag_type); - nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, 8, true); + if (version_page > 0) return &m_tag_information->memory[version_page][0]; + else return NULL; +} + +uint8_t *nfc_tag_mf0_ntag_get_signature_data() { + int signature_page = get_signature_page_by_tag_type(m_tag_type); + + if (signature_page > 0) return &m_tag_information->memory[signature_page][0]; + else return NULL; +} + +static void handle_get_version_command() { + int version_page = get_version_page_by_tag_type(m_tag_type); + + if (version_page > 0) { + memcpy(m_tag_tx_buffer.tx_buffer, &m_tag_information->memory[version_page][0], NFC_TAG_MF0_NTAG_VER_SIZE); + nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, NFC_TAG_MF0_NTAG_VER_SIZE, true); + } else { + NRF_LOG_WARNING("current card type does not support GET_VERSION"); + // MF0ICU1 and MF0ICU2 do not support GET_VERSION + nfc_tag_14a_tx_nbit(NAK_INVALID_OPERATION_TBIV, 4); + } +} + +static void handle_read_sig_command() { + int signature_page = get_signature_page_by_tag_type(m_tag_type); + + if (signature_page > 0) { + memcpy(m_tag_tx_buffer.tx_buffer, &m_tag_information->memory[signature_page][0], NFC_TAG_MF0_NTAG_SIG_SIZE); + nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, NFC_TAG_MF0_NTAG_SIG_SIZE, true); + } else { + NRF_LOG_WARNING("current card type does not support READ_SIG"); + // MF0ICU1 and MF0ICU2 do not support READ_SIG + nfc_tag_14a_tx_nbit(NAK_INVALID_OPERATION_TBIV, 4); + } } static int mirror_size_for_mode(uint8_t mirror_mode) { @@ -360,23 +408,23 @@ static uint8_t *get_counter_data_by_index(uint8_t index) { switch (m_tag_type) { case TAG_TYPE_MF0UL11: ctr_page_off = MF0UL11_PAGES; - ctr_page_end = MF0UL11_PAGES_WITH_CTRS; + ctr_page_end = ctr_page_off + MF0ULx1_NUM_CTRS; break; case TAG_TYPE_MF0UL21: ctr_page_off = MF0UL21_PAGES; - ctr_page_end = MF0UL21_PAGES_WITH_CTRS; + ctr_page_end = ctr_page_off + MF0ULx1_NUM_CTRS; break; case TAG_TYPE_NTAG_213: ctr_page_off = NTAG213_PAGES; - ctr_page_end = NTAG213_PAGES_WITH_CTR; + ctr_page_end = ctr_page_off + NTAG_NUM_CTRS; break; case TAG_TYPE_NTAG_215: ctr_page_off = NTAG215_PAGES; - ctr_page_end = NTAG215_PAGES_WITH_CTR; + ctr_page_end = ctr_page_off + NTAG_NUM_CTRS; break; case TAG_TYPE_NTAG_216: ctr_page_off = NTAG216_PAGES; - ctr_page_end = NTAG216_PAGES_WITH_CTR; + ctr_page_end = ctr_page_off + NTAG_NUM_CTRS; break; default: nfc_tag_14a_tx_nbit(NAK_INVALID_OPERATION_TBIV, 4); @@ -723,11 +771,11 @@ static void handle_incr_cnt_command(uint8_t block_num, uint8_t *p_data) { switch (m_tag_type) { case TAG_TYPE_MF0UL11: ctr_page_off = MF0UL11_PAGES; - ctr_page_end = MF0UL11_PAGES_WITH_CTRS; + ctr_page_end = ctr_page_off + MF0ULx1_NUM_CTRS; break; case TAG_TYPE_MF0UL21: ctr_page_off = MF0UL21_PAGES; - ctr_page_end = MF0UL21_PAGES_WITH_CTRS; + ctr_page_end = ctr_page_off + MF0ULx1_NUM_CTRS; break; default: nfc_tag_14a_tx_nbit(NAK_INVALID_OPERATION_TBIV, 4); @@ -823,8 +871,7 @@ static void nfc_tag_mf0_ntag_state_handler(uint8_t *p_data, uint16_t szDataBits) break; } case CMD_READ_SIG: - memset(m_tag_tx_buffer.tx_buffer, 0xCA, SIGNATURE_LENGTH); - nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, SIGNATURE_LENGTH, true); + handle_read_sig_command(); break; case CMD_READ_CNT: handle_read_cnt_command(block_num); @@ -875,7 +922,7 @@ static void nfc_tag_mf0_ntag_reset_handler() { } static int get_information_size_by_tag_type(tag_specific_type_t type) { - return sizeof(nfc_tag_14a_coll_res_entity_t) + sizeof(nfc_tag_mf0_ntag_configure_t) + (get_nr_mem_pages_by_tag_type(type) * NFC_TAG_MF0_NTAG_DATA_SIZE); + return sizeof(nfc_tag_14a_coll_res_entity_t) + sizeof(nfc_tag_mf0_ntag_configure_t) + (get_total_pages_by_tag_type(type) * NFC_TAG_MF0_NTAG_DATA_SIZE); } /** @brief MF0/NTAG callback before saving data @@ -980,6 +1027,49 @@ bool nfc_tag_mf0_ntag_data_factory(uint8_t slot, tag_specific_type_t tag_type) { } } + int version_page = get_version_page_by_tag_type(tag_type); + if (version_page > 0) { + uint8_t *version_data = &p_ntag_information->memory[version_page][0]; + + switch (m_tag_type) { + case TAG_TYPE_MF0UL11: + version_data[6] = MF0UL11_VERSION_STORAGE_SIZE; + version_data[2] = MF0ULx1_VERSION_PRODUCT_TYPE; + break; + case TAG_TYPE_MF0UL21: + version_data[6] = MF0UL21_VERSION_STORAGE_SIZE; + version_data[2] = MF0ULx1_VERSION_PRODUCT_TYPE; + break; + case TAG_TYPE_NTAG_213: + version_data[6] = NTAG213_VERSION_STORAGE_SIZE; + version_data[2] = NTAG_VERSION_PRODUCT_TYPE; + break; + case TAG_TYPE_NTAG_215: + version_data[6] = NTAG215_VERSION_STORAGE_SIZE; + version_data[2] = NTAG_VERSION_PRODUCT_TYPE; + break; + case TAG_TYPE_NTAG_216: + version_data[6] = NTAG216_VERSION_STORAGE_SIZE; + version_data[2] = NTAG_VERSION_PRODUCT_TYPE; + break; + default: + ASSERT(false); + break; + } + + version_data[0] = VERSION_FIXED_HEADER; + version_data[1] = VERSION_VENDOR_ID; + version_data[3] = VERSION_PRODUCT_SUBTYPE_50pF; // TODO: make configurable for MF0ULx1 + version_data[4] = VERSION_MAJOR_PRODUCT; + version_data[5] = VERSION_MINOR_PRODUCT; + version_data[7] = VERSION_PROTOCOL_TYPE; + } + + int signature_page = get_signature_page_by_tag_type(tag_type); + if (signature_page > 0) { + memset(&p_ntag_information->memory[signature_page][0], 0, NFC_TAG_MF0_NTAG_SIG_SIZE); + } + // default ntag auto ant-collision res p_ntag_information->res_coll.atqa[0] = 0x44; p_ntag_information->res_coll.atqa[1] = 0x00; diff --git a/firmware/application/src/rfid/nfctag/hf/nfc_mf0_ntag.h b/firmware/application/src/rfid/nfctag/hf/nfc_mf0_ntag.h index e23bb47..b851802 100644 --- a/firmware/application/src/rfid/nfctag/hf/nfc_mf0_ntag.h +++ b/firmware/application/src/rfid/nfctag/hf/nfc_mf0_ntag.h @@ -4,29 +4,36 @@ #include "nfc_14a.h" #define NFC_TAG_MF0_NTAG_DATA_SIZE 4 - -#define NFC_TAG_NTAG_FRAME_SIZE 64 -#define NFC_TAG_NTAG_BLOCK_MAX 231 + 1 +#define NFC_TAG_MF0_NTAG_SIG_SIZE 32 +#define NFC_TAG_MF0_NTAG_VER_SIZE 8 +#define NFC_TAG_MF0_NTAG_SIG_PAGES (NFC_TAG_MF0_NTAG_SIG_SIZE / NFC_TAG_MF0_NTAG_DATA_SIZE) +#define NFC_TAG_MF0_NTAG_VER_PAGES (NFC_TAG_MF0_NTAG_VER_SIZE / NFC_TAG_MF0_NTAG_DATA_SIZE) #define NFC_TAG_MF0_FRAME_SIZE (16 + NFC_TAG_14A_CRC_LENGTH) #define NFC_TAG_MF0_BLOCK_MAX 41 #define MF0ULx1_NUM_CTRS 3 // number of Ultralight EV1 one-way counters +#define NTAG_NUM_CTRS 1 // number of NTAG one-way counters + +#define MF0ULx1_EXTRA_PAGES (MF0ULx1_NUM_CTRS + NFC_TAG_MF0_NTAG_VER_PAGES + NFC_TAG_MF0_NTAG_SIG_PAGES) +#define NTAG_EXTRA_PAGES (NTAG_NUM_CTRS + NFC_TAG_MF0_NTAG_VER_PAGES + NFC_TAG_MF0_NTAG_SIG_PAGES) #define NTAG213_PAGES 45 //45 pages total for ntag213, from 0 to 44 -#define NTAG213_PAGES_WITH_CTR (NTAG213_PAGES + 1) // 1 more page for the counter +#define NTAG213_TOTAL_PAGES (NTAG213_PAGES + NTAG_EXTRA_PAGES) // 1 more page for the counter #define NTAG215_PAGES 135 //135 pages total for ntag215, from 0 to 134 -#define NTAG215_PAGES_WITH_CTR (NTAG215_PAGES + 1) // 1 more page for the counter +#define NTAG215_TOTAL_PAGES (NTAG215_PAGES + NTAG_EXTRA_PAGES) // 1 more page for the counter #define NTAG216_PAGES 231 //231 pages total for ntag216, from 0 to 230 -#define NTAG216_PAGES_WITH_CTR (NTAG216_PAGES + 1) // 1 more page for the counter +#define NTAG216_TOTAL_PAGES (NTAG216_PAGES + NTAG_EXTRA_PAGES) // 1 more page for the counter #define MF0ICU1_PAGES 16 //16 pages total for MF0ICU1 (the original UL), from 0 to 15 #define MF0ICU2_PAGES 36 //16 pages total for MF0ICU2 (UL C), from 0 to 35 #define MF0UL11_PAGES 20 //20 pages total for MF0UL11 (UL EV1), from 0 to 19 -#define MF0UL11_PAGES_WITH_CTRS (MF0UL11_PAGES + MF0ULx1_NUM_CTRS) // 3 more pages for 3 one way counters +#define MF0UL11_TOTAL_PAGES (MF0UL11_PAGES + MF0ULx1_EXTRA_PAGES) // 3 more pages for 3 one way counters #define MF0UL21_PAGES 41 //231 pages total for MF0UL21 (UL EV1), from 0 to 40 -#define MF0UL21_PAGES_WITH_CTRS (MF0UL21_PAGES + MF0ULx1_NUM_CTRS) // 3 more pages for 3 one way counters +#define MF0UL21_TOTAL_PAGES (MF0UL21_PAGES + MF0ULx1_EXTRA_PAGES) // 3 more pages for 3 one way counters +#define NFC_TAG_NTAG_FRAME_SIZE 64 +#define NFC_TAG_NTAG_BLOCK_MAX NTAG216_TOTAL_PAGES typedef struct { uint8_t mode_uid_magic: 1; @@ -53,6 +60,8 @@ int nfc_tag_mf0_ntag_data_loadcb(tag_specific_type_t type, tag_data_buffer_t *bu int nfc_tag_mf0_ntag_data_savecb(tag_specific_type_t type, tag_data_buffer_t *buffer); bool nfc_tag_mf0_ntag_data_factory(uint8_t slot, tag_specific_type_t tag_type); int nfc_tag_mf0_ntag_get_nr_pages_by_tag_type(tag_specific_type_t tag_type); +uint8_t *nfc_tag_mf0_ntag_get_version_data(void); +uint8_t *nfc_tag_mf0_ntag_get_signature_data(void); int nfc_tag_mf0_ntag_get_uid_mode(void); bool nfc_tag_mf0_ntag_set_uid_mode(bool enabled); diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index f5593a4..8fb7f6f 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -1934,9 +1934,9 @@ class HFMFUDUMP(MFUAuthArgsUnit): @hf_mfu.command('version') -class HFMFUVERSION(MFUAuthArgsUnit): +class HFMFUVERSION(ReaderRequiredUnit): def args_parser(self) -> ArgumentParserNoExit: - parser = super().args_parser() + parser = ArgumentParserNoExit() parser.description = 'Request MIFARE Ultralight / NTAG version data.' return parser @@ -1985,9 +1985,39 @@ class HFMFUEConfig(SlotIndexArgsAndGoUnit, HF14AAntiCollArgsUnit, DeviceRequired uid_magic_group = parser.add_mutually_exclusive_group() uid_magic_group.add_argument('--enable-uid-magic', action='store_true', help="Enable UID magic mode") uid_magic_group.add_argument('--disable-uid-magic', action='store_true', help="Disable UID magic mode") + parser.add_argument('--set-version', type=bytes.fromhex, help="Set data to be returned by the GET_VERSION command.") + parser.add_argument('--set-signature', type=bytes.fromhex, help="Set data to be returned by the READ_SIG command.") return parser def on_exec(self, args: argparse.Namespace): + aux_data_changed = False + + if args.set_version is not None: + aux_data_changed = True + + if len(args.set_version) != 8: + print(f"{CR}Version data should be 8 bytes long.{C0}") + return + + try: + self.cmd.mf0_ntag_set_version_data(args.set_version) + except: + print(f"{CR}Tag type does not support GET_VERSION command.{C0}") + return + + if args.set_signature is not None: + aux_data_changed = True + + if len(args.set_signature) != 32: + print(f"{CR}Signature data should be 32 bytes long.{C0}") + return + + try: + self.cmd.mf0_ntag_set_signature_data(args.set_signature) + except: + print(f"{CR}Tag type does not support READ_SIG command.{C0}") + return + # collect current settings anti_coll_data = self.cmd.hf14a_get_anti_coll_data() if len(anti_coll_data) == 0: @@ -2024,9 +2054,9 @@ class HFMFUEConfig(SlotIndexArgsAndGoUnit, HF14AAntiCollArgsUnit, DeviceRequired else: magic_mode = self.cmd.mf0_ntag_get_uid_magic_mode() - if change_done: + if change_done or aux_data_changed: print(' - MFU/NTAG Emulator settings updated') - if not change_requested: + if not (change_requested or aux_data_changed): print(f'- {"Type:":40}{CY}{hf_tag_type}{C0}') print(f'- {"UID:":40}{CY}{uid.hex().upper()}{C0}') print(f'- {"ATQA:":40}{CY}{atqa.hex().upper()} ' @@ -2038,6 +2068,18 @@ class HFMFUEConfig(SlotIndexArgsAndGoUnit, HF14AAntiCollArgsUnit, DeviceRequired print(f'- {"UID Magic:":40}{CY}enabled{C0}') else: print(f'- {"UID Magic:":40}{CY}disabled{C0}') + + try: + version = self.cmd.mf0_ntag_get_version_data() + print(f'- {"Version:":40}{CY}{version.hex().upper()}{C0}') + except: + pass + + try: + signature = self.cmd.mf0_ntag_get_signature_data() + print(f'- {"Signature:":40}{CY}{signature.hex().upper()}{C0}') + except: + pass @lf_em_410x.command('read') diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index c38208e..af5d21d 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -951,6 +951,30 @@ class ChameleonCMD: def mf0_ntag_set_uid_magic_mode(self, enabled: bool): return self.device.send_cmd_sync(Command.MF0_NTAG_SET_UID_MAGIC_MODE, struct.pack('?', enabled)) + @expect_response(Status.SUCCESS) + def mf0_ntag_get_version_data(self): + resp = self.device.send_cmd_sync(Command.MF0_NTAG_GET_VERSION_DATA) + if resp.status == Status.SUCCESS: + resp.parsed = resp.data[:8] + return resp + + @expect_response(Status.SUCCESS) + def mf0_ntag_set_version_data(self, data: bytes): + assert len(data) == 8 + return self.device.send_cmd_sync(Command.MF0_NTAG_SET_VERSION_DATA, data) + + @expect_response(Status.SUCCESS) + def mf0_ntag_get_signature_data(self): + resp = self.device.send_cmd_sync(Command.MF0_NTAG_GET_SIGNATURE_DATA) + if resp.status == Status.SUCCESS: + resp.parsed = resp.data[:32] + return resp + + @expect_response(Status.SUCCESS) + def mf0_ntag_set_signature_data(self, data: bytes): + assert len(data) == 32 + return self.device.send_cmd_sync(Command.MF0_NTAG_SET_SIGNATURE_DATA, data) + @expect_response(Status.SUCCESS) def get_ble_pairing_enable(self): """ diff --git a/software/script/chameleon_enum.py b/software/script/chameleon_enum.py index 221ca8a..c88bd54 100644 --- a/software/script/chameleon_enum.py +++ b/software/script/chameleon_enum.py @@ -98,7 +98,11 @@ class Command(enum.IntEnum): MF0_NTAG_GET_UID_MAGIC_MODE = 4019 MF0_NTAG_SET_UID_MAGIC_MODE = 4020 MF0_NTAG_READ_EMU_PAGE_DATA = 4021 - MF0_NTAG_WRITE_EMU_PAGE_DATA = 4023 + MF0_NTAG_WRITE_EMU_PAGE_DATA = 4022 + MF0_NTAG_GET_VERSION_DATA = 4023 + MF0_NTAG_SET_VERSION_DATA = 4024 + MF0_NTAG_GET_SIGNATURE_DATA = 4025 + MF0_NTAG_SET_SIGNATURE_DATA = 4026 EM410X_SET_EMU_ID = 5000 EM410X_GET_EMU_ID = 5001