Add support for Ultralight emulation.

This version only emulates MF0ICU1 properly.
This commit is contained in:
turbocool3r
2024-06-19 22:55:43 +03:00
parent 3cadd47eeb
commit 248f3b2839
14 changed files with 639 additions and 353 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ SRC_FILES += \
$(PROJ_DIR)/rfid/nfctag/hf/crypto1_helper.c \
$(PROJ_DIR)/rfid/nfctag/hf/nfc_14a.c \
$(PROJ_DIR)/rfid/nfctag/hf/nfc_mf1.c \
$(PROJ_DIR)/rfid/nfctag/hf/nfc_ntag.c \
$(PROJ_DIR)/rfid/nfctag/hf/nfc_mf0_ntag.c \
$(PROJ_DIR)/rfid/nfctag/lf/lf_tag_em.c \
$(PROJ_DIR)/utils/dataframe.c \
$(PROJ_DIR)/utils/delayed_reset.c \
+20
View File
@@ -1026,6 +1026,24 @@ static data_frame_tx_t *after_hf_reader_run(uint16_t cmd, uint16_t status, uint1
// fct will be defined after m_data_cmd_map because we need to know its size
data_frame_tx_t *cmd_processor_get_device_capabilities(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data);
static data_frame_tx_t *cmd_processor_mf0_ntag_get_uid_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
int rc = nfc_tag_mf0_ntag_get_uid_mode();
if (rc < 0) return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL);
else {
uint8_t res = rc;
return data_frame_make(cmd, STATUS_SUCCESS, 1, &res);
}
}
static data_frame_tx_t *cmd_processor_mf0_ntag_set_uid_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (length != 1 || !nfc_tag_mf0_ntag_set_uid_mode(data[0] != 0)) {
return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL);
}
return data_frame_make(cmd, STATUS_SUCCESS, 0, NULL);
}
/**
* (cmd -> processor) function map, the map struct is:
* cmd code before process cmd processor after process
@@ -1109,6 +1127,8 @@ static cmd_data_map_t m_data_cmd_map[] = {
{ DATA_CMD_MF1_GET_WRITE_MODE, NULL, cmd_processor_mf1_get_write_mode, NULL },
{ DATA_CMD_MF1_SET_WRITE_MODE, NULL, cmd_processor_mf1_set_write_mode, NULL },
{ DATA_CMD_HF14A_GET_ANTI_COLL_DATA, NULL, cmd_processor_hf14a_get_anti_coll_data, NULL },
{ DATA_CMD_MF0_NTAG_GET_UID_MAGIC_MODE, NULL, cmd_processor_mf0_ntag_get_uid_mode, NULL },
{ DATA_CMD_MF0_NTAG_SET_UID_MAGIC_MODE, NULL, cmd_processor_mf0_ntag_set_uid_mode, 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 },
+6 -2
View File
@@ -653,8 +653,12 @@ static void btn_fn_copy_ic_uid(void) {
case TAG_TYPE_NTAG_213:
case TAG_TYPE_NTAG_215:
case TAG_TYPE_NTAG_216: {
nfc_tag_ntag_information_t *p_info = (nfc_tag_ntag_information_t *)buffer->buffer;
case TAG_TYPE_NTAG_216:
case TAG_TYPE_MF0ICU1:
case TAG_TYPE_MF0ICU2:
case TAG_TYPE_MF0UL11:
case TAG_TYPE_MF0UL21: {
nfc_tag_mf0_ntag_information_t *p_info = (nfc_tag_mf0_ntag_information_t *)buffer->buffer;
antres = &(p_info->res_coll);
break;
}
+2
View File
@@ -106,6 +106,8 @@
#define DATA_CMD_MF1_GET_WRITE_MODE (4016)
#define DATA_CMD_MF1_SET_WRITE_MODE (4017)
#define DATA_CMD_HF14A_GET_ANTI_COLL_DATA (4018)
#define DATA_CMD_MF0_NTAG_GET_UID_MAGIC_MODE (4019)
#define DATA_CMD_MF0_NTAG_SET_UID_MAGIC_MODE (4020)
//
// ******************************************************************
@@ -0,0 +1,492 @@
#include <stdlib.h>
#include "nfc_mf0_ntag.h"
#include "nfc_14a.h"
#include "fds_util.h"
#include "tag_persistence.h"
#define NRF_LOG_MODULE_NAME tag_mf0_ntag
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
NRF_LOG_MODULE_REGISTER();
#define VERSION_FIXED_HEADER 0x00
#define VERSION_VENDOR_ID 0x04
#define MF0ULx1_VERSION_PRODUCT_TYPE 0x03
#define NTAG_VERSION_PRODUCT_TYPE 0x04
#define VERSION_PRODUCT_SUBTYPE_17pF 0x01
#define VERSION_PRODUCT_SUBTYPE_50pF 0x02
#define VERSION_MAJOR_PRODUCT 0x01
#define VERSION_MINOR_PRODUCT 0x00
#define MF0UL11_VERSION_STORAGE_SIZE 0x0B
#define MF0UL21_VERSION_STORAGE_SIZE 0x0E
#define NTAG213_VERSION_STORAGE_SIZE 0x0F
#define NTAG215_VERSION_STORAGE_SIZE 0x11
#define NTAG216_VERSION_STORAGE_SIZE 0x13
#define VERSION_PROTOCOL_TYPE 0x03
// MF0 and NTAG COMMANDS
#define CMD_GET_VERSION 0x60
#define CMD_READ 0x30
#define CMD_FAST_READ 0x3A
#define CMD_WRITE 0xA2
#define CMD_COMPAT_WRITE 0xA0
#define CMD_READ_CNT 0x39
#define CMD_INCR_CNT 0x3A
#define CMD_PWD_AUTH 0x1B
#define CMD_READ_SIG 0x3C
#define CMD_CHECK_TEARING_EVENT 0x3E
#define CMD_VCSL 0x4B
// MEMORY LAYOUT STUFF, addresses and sizes in bytes
// UID stuff
#define UID_CL1_ADDRESS 0x00
#define UID_CL1_SIZE 3
#define UID_BCC1_ADDRESS 0x03
#define UID_CL2_ADDRESS 0x04
#define UID_CL2_SIZE 4
#define UID_BCC2_ADDRESS 0x08
// LockBytes stuff
#define STATIC_LOCKBYTE_0_ADDRESS 0x0A
#define STATIC_LOCKBYTE_1_ADDRESS 0x0B
// CONFIG stuff
#define MF0UL11_FIRST_CFG_PAGE 0x10
#define MF0UL21_FIRST_CFG_PAGE 0x25
#define NTAG213_FIRST_CFG_PAGE 0x29
#define NTAG215_FIRST_CFG_PAGE 0x83
#define NTAG216_FIRST_CFG_PAGE 0xE3
#define CONFIG_AREA_SIZE 8
// CONFIG offsets, relative to config start address
#define CONF_AUTH0_BYTE 0x03
#define CONF_ACCESS_OFFSET 0x04
#define CONF_PWD_PAGE_OFFSET 2
#define CONF_PACK_PAGE_OFFSET 3
// WRITE STUFF
#define BYTES_PER_WRITE 4
#define PAGE_WRITE_MIN 0x02
// CONFIG masks to check individual needed bits
#define CONF_ACCESS_PROT 0x80
#define VERSION_INFO_LENGTH 8 //8 bytes info length + crc
#define BYTES_PER_READ 16
// SIGNATURE Length
#define SIGNATURE_LENGTH 32
// NTAG215_Version[7] mean:
// 0x0F ntag213
// 0x11 ntag215
// 0x13 ntag216
const uint8_t ntagVersion[8] = {0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x11, 0x03};
/* pwd auth for amiibo */
uint8_t ntagPwdOK[2] = {0x80, 0x80};
// Data structure pointer to the label information
static nfc_tag_mf0_ntag_information_t *m_tag_information = NULL;
// Define and use shadow anti -collision resources
static nfc_tag_14a_coll_res_reference_t m_shadow_coll_res;
//Define and use MF0/NTAG special communication buffer
static nfc_tag_mf0_ntag_tx_buffer_t m_tag_tx_buffer;
// Save the specific type of MF0/NTAG currently being simulated
static tag_specific_type_t m_tag_type;
static bool m_tag_authenticated = false;
static uint8_t get_nr_pages_by_tag_type(tag_specific_type_t tag_type) {
uint8_t nr_pages;
switch (tag_type) {
case TAG_TYPE_MF0ICU1:
nr_pages = MF0ICU1_PAGES;
break;
case TAG_TYPE_MF0ICU2:
nr_pages = MF0ICU2_PAGES;
break;
case TAG_TYPE_MF0UL11:
nr_pages = MF0UL11_PAGES;
break;
case TAG_TYPE_MF0UL21:
nr_pages = MF0UL21_PAGES;
break;
case TAG_TYPE_NTAG_213:
nr_pages = NTAG213_PAGES;
break;
case TAG_TYPE_NTAG_215:
nr_pages = NTAG215_PAGES;
break;
case TAG_TYPE_NTAG_216:
nr_pages = NTAG216_PAGES;
break;
default:
nr_pages = 0;
break;
}
return nr_pages;
}
static uint8_t get_first_cfg_page_by_tag_type(tag_specific_type_t tag_type) {
uint8_t page;
switch (tag_type) {
case TAG_TYPE_MF0UL11:
page = MF0UL11_FIRST_CFG_PAGE;
break;
case TAG_TYPE_MF0UL21:
page = MF0UL21_FIRST_CFG_PAGE;
break;
case TAG_TYPE_NTAG_213:
page = NTAG213_FIRST_CFG_PAGE;
break;
case TAG_TYPE_NTAG_215:
page = NTAG215_FIRST_CFG_PAGE;
break;
case TAG_TYPE_NTAG_216:
page = NTAG216_FIRST_CFG_PAGE;
break;
default:
page = 0;
break;
}
return page;
}
static uint8_t get_block_max_by_tag_type(tag_specific_type_t tag_type) {
uint8_t max_pages = get_nr_pages_by_tag_type(tag_type);
uint8_t first_cfg_page = get_first_cfg_page_by_tag_type(tag_type);
if (first_cfg_page == 0 || m_tag_authenticated || m_tag_information->config.mode_uid_magic) return max_pages;
uint8_t auth0 = m_tag_information->memory[first_cfg_page][CONF_AUTH0_BYTE];
return (max_pages > auth0) ? auth0 : max_pages;
}
static bool is_ntag() {
switch (m_tag_type) {
case TAG_TYPE_NTAG_213:
case TAG_TYPE_NTAG_215:
case TAG_TYPE_NTAG_216:
return true;
default:
return false;
}
}
static void handle_get_version_command() {
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;
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;
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;
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;
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;
break;
default:
// MF0ICU1 and MF0ICU2 do not support GET_VERSION
nfc_tag_14a_tx_nbit(NAK_INVALID_OPERATION_TBIV, 4);
return;
}
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;
nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, 8, true);
}
static void handle_read_command(uint8_t block_num) {
int block_max = get_block_max_by_tag_type(m_tag_type);
if (block_num >= block_max) {
nfc_tag_14a_tx_nbit(NAK_INVALID_OPERATION_TBIV, 4);
return;
}
uint8_t pwd_page = get_first_cfg_page_by_tag_type(m_tag_type);
if (pwd_page != 0) pwd_page += CONF_PWD_PAGE_OFFSET;
for (int block = 0; block < 4; block++) {
// In case PWD or PACK pages are read we need to write zero to the output buffer. In UID magic mode we don't care.
if (m_tag_information->config.mode_uid_magic || (pwd_page == 0) || ((block - pwd_page) >= 2)) {
memcpy(m_tag_tx_buffer.tx_buffer + block * 4, m_tag_information->memory[(block_num + block) % block_max], NFC_TAG_MF0_NTAG_DATA_SIZE);
} else {
memset(m_tag_tx_buffer.tx_buffer + block * 4, 0, NFC_TAG_MF0_NTAG_DATA_SIZE);
}
}
nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, BYTES_PER_READ, true);
}
static bool check_ro_lock_on_page(int block_num) {
if (block_num < 3) return true;
else if (block_num == 3) return (m_tag_information->memory[2][2] & 1) == 1;
else if (block_num <= MF0ICU1_PAGES) {
bool locked = false;
// check block locking bits
if (block_num <= 9) locked |= (m_tag_information->memory[2][2] & 2) == 2;
else locked |= (m_tag_information->memory[2][2] & 4) == 4;
locked |= (((*(uint16_t *)&m_tag_information->memory[2][2]) >> block_num) & 1) == 1;
return locked;
} else {
// too large block number
return true;
}
}
static int handle_write_command(uint8_t block_num, uint8_t *p_data) {
int block_max = get_block_max_by_tag_type(m_tag_type);
if (block_num >= block_max) {
return NAK_INVALID_OPERATION_TBIV;
}
if (m_tag_information->config.mode_uid_magic) {
// anything can be written in this mode
memcpy(m_tag_information->memory[block_num], p_data, NFC_TAG_MF0_NTAG_DATA_SIZE);
return ACK_VALUE;
}
switch (block_num) {
case 0:
case 1:
return NAK_INVALID_OPERATION_TBIV;
case 2:
// Page 2 contains lock bytes for pages 3-15. These are OR'ed when not in the UID
// magic mode. First two bytes are ignored.
m_tag_information->memory[2][2] |= p_data[2];
m_tag_information->memory[2][3] |= p_data[3];
break;
case 3:
// Page 3 contains what's called OTP bits for Ultralight tags and CC bits for NTAG
// cards, these work in the same way.
if (!check_ro_lock_on_page(block_num)) {
// lock bit for OTP page is not set
for (int i = 0; i < NFC_TAG_MF0_NTAG_DATA_SIZE; i++) {
m_tag_information->memory[3][i] |= p_data[i];
}
}
break;
default:
if (!check_ro_lock_on_page(block_num)) {
memcpy(m_tag_information->memory[block_num], p_data, NFC_TAG_MF0_NTAG_DATA_SIZE);
}
break;
}
return ACK_VALUE;
}
static void nfc_tag_mf0_ntag_state_handler(uint8_t *p_data, uint16_t szDataBits) {
uint8_t command = p_data[0];
uint8_t block_num = p_data[1];
switch (command) {
case CMD_GET_VERSION:
handle_get_version_command();
break;
case CMD_READ: {
handle_read_command(block_num);
break;
}
case CMD_FAST_READ: {
uint8_t end_block_num = p_data[2];
// TODO: support ultralight
if (!is_ntag() || (block_num > end_block_num) || (block_num >= get_block_max_by_tag_type(m_tag_type)) || (end_block_num >= get_block_max_by_tag_type(m_tag_type))) {
nfc_tag_14a_tx_nbit(NAK_INVALID_OPERATION_TBV, 4);
break;
}
for (int block = block_num; block <= end_block_num; block++) {
memcpy(m_tag_tx_buffer.tx_buffer + (block - block_num) * 4, m_tag_information->memory[block], NFC_TAG_MF0_NTAG_DATA_SIZE);
}
nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, (end_block_num - block_num + 1) * NFC_TAG_MF0_NTAG_DATA_SIZE, true);
break;
}
case CMD_WRITE:
case CMD_COMPAT_WRITE: {
int resp = handle_write_command(block_num, &p_data[2]);
nfc_tag_14a_tx_nbit(resp, 4);
break;
}
/*case CMD_PWD_AUTH: {
// TODO: IMPLEMENT COUNTER AUTHLIM
uint8_t Password[4];
memcpy(Password, m_tag_information->memory[get_block_cfg_by_tag_type(m_tag_type) + CONF_PASSWORD_OFFSET], 4);
if (Password[0] != p_data[1] || Password[1] != p_data[2] || Password[2] != p_data[3] || Password[3] != p_data[4]) {
nfc_tag_14a_tx_nbit(NAK_INVALID_OPERATION_TBIV, 4);
break;
}
// Authenticate the user
//RESET AUTHLIM COUNTER, CURRENTLY NOT IMPLEMENTED
// TODO
// Send the PACK value back
if (m_tag_information->config.mode_uid_magic) {
nfc_tag_14a_tx_bytes(ntagPwdOK, 2, true);
} else {
nfc_tag_14a_tx_bytes(m_tag_information->memory[get_block_cfg_by_tag_type(m_tag_type) + CONF_PASSWORD_OFFSET], 2, true);
}
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);
break;
}
return;
}
static nfc_tag_14a_coll_res_reference_t *get_coll_res() {
// Use a separate anti -conflict information instead of using the information in the sector
m_shadow_coll_res.sak = m_tag_information->res_coll.sak;
m_shadow_coll_res.atqa = m_tag_information->res_coll.atqa;
m_shadow_coll_res.uid = m_tag_information->res_coll.uid;
m_shadow_coll_res.size = &(m_tag_information->res_coll.size);
m_shadow_coll_res.ats = &(m_tag_information->res_coll.ats);
// Finally, a shadow data structure pointer with only reference, no physical shadow,
return &m_shadow_coll_res;
}
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_pages_by_tag_type(type) * NFC_TAG_MF0_NTAG_DATA_SIZE);
}
/** @brief MF0/NTAG callback before saving data
* @param type detailed label type
* @param buffer data buffer
* @return to be saved, the length of the data that needs to be saved, it means not saved when 0
*/
int nfc_tag_mf0_ntag_data_savecb(tag_specific_type_t type, tag_data_buffer_t *buffer) {
if (m_tag_type != TAG_TYPE_UNDEFINED && m_tag_information != NULL) {
// Save the corresponding size data according to the current label type
return get_information_size_by_tag_type(type);
} else {
return 0;
}
}
int nfc_tag_mf0_ntag_data_loadcb(tag_specific_type_t type, tag_data_buffer_t *buffer) {
int info_size = get_information_size_by_tag_type(type);
if (buffer->length >= info_size) {
// Convert the data buffer to MF0/NTAG structure type
m_tag_information = (nfc_tag_mf0_ntag_information_t *)buffer->buffer;
// The specific type of MF0/NTAG tag that is simulated by the cache
m_tag_type = type;
// Register 14A communication management interface
nfc_tag_14a_handler_t handler_for_14a = {
.get_coll_res = get_coll_res,
.cb_state = nfc_tag_mf0_ntag_state_handler,
.cb_reset = nfc_tag_mf0_ntag_reset_handler,
};
nfc_tag_14a_set_handler(&handler_for_14a);
NRF_LOG_INFO("HF ntag data load finish.");
} else {
NRF_LOG_ERROR("nfc_tag_mf0_ntag_information_t too big.");
}
return info_size;
}
// Initialized NTAG factory data
bool nfc_tag_mf0_ntag_data_factory(uint8_t slot, tag_specific_type_t tag_type) {
// default ntag data
uint8_t default_p0[] = { 0x04, 0x68, 0x95, 0x71 };
uint8_t default_p1[] = { 0xFA, 0x5C, 0x64, 0x80 };
uint8_t default_p2[] = { 0x42, 0x48, 0x0F, 0xE0 };
if (!is_ntag()) {
default_p2[2] = 0;
default_p2[3] = 0;
}
// default ntag info
nfc_tag_mf0_ntag_information_t ntag_tmp_information;
nfc_tag_mf0_ntag_information_t *p_ntag_information;
p_ntag_information = &ntag_tmp_information;
int block_max = get_nr_pages_by_tag_type(tag_type);
for (int block = 0; block < block_max; block++) {
switch (block) {
case 0:
memcpy(p_ntag_information->memory[block], default_p0, NFC_TAG_MF0_NTAG_DATA_SIZE);
break;
case 1:
memcpy(p_ntag_information->memory[block], default_p1, NFC_TAG_MF0_NTAG_DATA_SIZE);
break;
case 2:
memcpy(p_ntag_information->memory[block], default_p2, NFC_TAG_MF0_NTAG_DATA_SIZE);
break;
default:
memset(p_ntag_information->memory[block], 0, NFC_TAG_MF0_NTAG_DATA_SIZE);
break;
}
}
// default ntag auto ant-collision res
p_ntag_information->res_coll.atqa[0] = 0x44;
p_ntag_information->res_coll.atqa[1] = 0x00;
p_ntag_information->res_coll.sak[0] = 0x00;
p_ntag_information->res_coll.uid[0] = 0x04;
p_ntag_information->res_coll.uid[1] = 0x68;
p_ntag_information->res_coll.uid[2] = 0x95;
p_ntag_information->res_coll.uid[3] = 0x71;
p_ntag_information->res_coll.uid[4] = 0xFA;
p_ntag_information->res_coll.uid[5] = 0x5C;
p_ntag_information->res_coll.uid[6] = 0x64;
p_ntag_information->res_coll.size = NFC_TAG_14A_UID_DOUBLE_SIZE;
p_ntag_information->res_coll.ats.length = 0;
// default ntag config
p_ntag_information->config.mode_uid_magic = false;
// save data to flash
tag_sense_type_t sense_type = get_sense_type_from_tag_type(tag_type);
fds_slot_record_map_t map_info;
get_fds_map_by_slot_sense_type_for_dump(slot, sense_type, &map_info);
int info_size = get_information_size_by_tag_type(tag_type);
NRF_LOG_INFO("MF0/NTAG info size: %d", info_size);
bool ret = fds_write_sync(map_info.id, map_info.key, info_size, p_ntag_information);
if (ret) {
NRF_LOG_INFO("Factory slot data success.");
} else {
NRF_LOG_ERROR("Factory slot data error.");
}
return ret;
}
int nfc_tag_mf0_ntag_get_uid_mode() {
if (m_tag_type == TAG_TYPE_UNDEFINED || m_tag_information == NULL) return -1;
return (int)m_tag_information->config.mode_uid_magic;
}
bool nfc_tag_mf0_ntag_set_uid_mode(bool enabled) {
if (m_tag_type == TAG_TYPE_UNDEFINED || m_tag_information == NULL) return false;
m_tag_information->config.mode_uid_magic = enabled;
return true;
}
@@ -0,0 +1,50 @@
#ifndef NFC_NTAG_H
#define NFC_NTAG_H
#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
#define NFC_TAG_MF0_FRAME_SIZE (16 + NFC_TAG_14A_CRC_LENGTH)
#define NFC_TAG_MF0_BLOCK_MAX 41
#define NTAG213_PAGES 45 //45 pages total for ntag213, from 0 to 44
#define NTAG215_PAGES 135 //135 pages total for ntag215, from 0 to 134
#define NTAG216_PAGES 231 //231 pages total for ntag216, from 0 to 230
#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 MF0UL21_PAGES 41 //231 pages total for MF0UL21 (UL EV1), from 0 to 40
typedef struct {
uint8_t mode_uid_magic: 1;
// reserve
uint8_t reserved1: 7;
uint8_t reserved2;
uint8_t reserved3;
} nfc_tag_mf0_ntag_configure_t;
typedef struct __attribute__((aligned(4))) {
nfc_tag_14a_coll_res_entity_t res_coll;
nfc_tag_mf0_ntag_configure_t config;
uint8_t memory[][NFC_TAG_MF0_NTAG_DATA_SIZE];
}
nfc_tag_mf0_ntag_information_t;
typedef struct {
uint8_t tx_buffer[NFC_TAG_NTAG_FRAME_SIZE];
} nfc_tag_mf0_ntag_tx_buffer_t;
int nfc_tag_mf0_ntag_data_loadcb(tag_specific_type_t type, tag_data_buffer_t *buffer);
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_uid_mode(void);
bool nfc_tag_mf0_ntag_set_uid_mode(bool enabled);
#endif
@@ -1,301 +0,0 @@
#include <stdlib.h>
#include "nfc_ntag.h"
#include "nfc_14a.h"
#include "fds_util.h"
#include "tag_persistence.h"
#define NRF_LOG_MODULE_NAME tag_ntag
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
NRF_LOG_MODULE_REGISTER();
#define NTAG213_VERSION 0x0F
#define NTAG215_VERSION 0x11
#define NTAG216_VERSION 0x13
// NTAG COMMANDS
#define CMD_GET_VERSION 0x60
#define CMD_READ 0x30
#define CMD_FAST_READ 0x3A
#define CMD_WRITE 0xA2
#define CMD_COMPAT_WRITE 0xA0
#define CMD_READ_CNT 0x39
#define CMD_PWD_AUTH 0x1B
#define CMD_READ_SIG 0x3C
// MEMORY LAYOUT STUFF, addresses and sizes in bytes
// UID stuff
#define UID_CL1_ADDRESS 0x00
#define UID_CL1_SIZE 3
#define UID_BCC1_ADDRESS 0x03
#define UID_CL2_ADDRESS 0x04
#define UID_CL2_SIZE 4
#define UID_BCC2_ADDRESS 0x08
// LockBytes stuff
#define STATIC_LOCKBYTE_0_ADDRESS 0x0A
#define STATIC_LOCKBYTE_1_ADDRESS 0x0B
// CONFIG stuff
#define NTAG213_CONFIG_AREA_START_ADDRESS 0xA4 // 4 * 0x29
#define NTAG215_CONFIG_AREA_START_ADDRESS 0x20C // 4 * 0x83
#define NTAG216_CONFIG_AREA_START_ADDRESS 0x38C // 4 * 0xE3
#define CONFIG_AREA_SIZE 8
// CONFIG offsets, relative to config start address
#define CONF_AUTH0_OFFSET 0x03
#define CONF_ACCESS_OFFSET 0x04
#define CONF_PASSWORD_OFFSET 0x08
#define CONF_PACK_OFFSET 0x0C
// WRITE STUFF
#define BYTES_PER_WRITE 4
#define PAGE_WRITE_MIN 0x02
// CONFIG masks to check individual needed bits
#define CONF_ACCESS_PROT 0x80
#define VERSION_INFO_LENGTH 8 //8 bytes info length + crc
#define BYTES_PER_READ 16
// SIGNATURE Length
#define SIGNATURE_LENGTH 32
// NTAG215_Version[7] mean:
// 0x0F ntag213
// 0x11 ntag215
// 0x13 ntag216
const uint8_t ntagVersion[8] = {0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x11, 0x03};
/* pwd auth for amiibo */
uint8_t ntagPwdOK[2] = {0x80, 0x80};
// Data structure pointer to the label information
static nfc_tag_ntag_information_t *m_tag_information = NULL;
// Define and use shadow anti -collision resources
static nfc_tag_14a_coll_res_reference_t m_shadow_coll_res;
//Define and use NTAG special communication buffer
static nfc_tag_ntag_tx_buffer_t m_tag_tx_buffer;
// Save the specific type of NTAG currently being simulated
static tag_specific_type_t m_tag_type;
static int get_block_max_by_tag_type(tag_specific_type_t tag_type) {
int block_max;
switch (tag_type) {
case TAG_TYPE_NTAG_213:
block_max = NTAG213_PAGES;
break;
default:
case TAG_TYPE_NTAG_215:
block_max = NTAG215_PAGES;
break;
case TAG_TYPE_NTAG_216:
block_max = NTAG216_PAGES;
break;
}
return block_max;
}
static int get_block_cfg_by_tag_type(tag_specific_type_t tag_type) {
int block_max;
switch (tag_type) {
case TAG_TYPE_NTAG_213:
block_max = NTAG213_CONFIG_AREA_START_ADDRESS;
break;
default:
case TAG_TYPE_NTAG_215:
block_max = NTAG215_CONFIG_AREA_START_ADDRESS;
break;
case TAG_TYPE_NTAG_216:
block_max = NTAG216_CONFIG_AREA_START_ADDRESS;
break;
}
return block_max;
}
void nfc_tag_ntag_state_handler(uint8_t *p_data, uint16_t szDataBits) {
uint8_t command = p_data[0];
uint8_t block_num = p_data[1];
switch (command) {
case CMD_GET_VERSION:
memcpy(m_tag_tx_buffer.tx_buffer, ntagVersion, 8);
switch (m_tag_type) {
case TAG_TYPE_NTAG_213:
m_tag_tx_buffer.tx_buffer[6] = NTAG213_VERSION;
break;
default:
case TAG_TYPE_NTAG_215:
m_tag_tx_buffer.tx_buffer[6] = NTAG215_VERSION;
break;
case TAG_TYPE_NTAG_216:
m_tag_tx_buffer.tx_buffer[6] = NTAG216_VERSION;
break;
}
nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, 8, true);
break;
case CMD_READ:
if (block_num < get_block_max_by_tag_type(m_tag_type)) {
for (int block = 0; block < 4; block++) {
memcpy(m_tag_tx_buffer.tx_buffer + block * 4, m_tag_information->memory[block_num + block], NFC_TAG_NTAG_DATA_SIZE);
}
nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, BYTES_PER_READ, true);
} else {
nfc_tag_14a_tx_nbit(NAK_INVALID_OPERATION_TBIV, 4);
}
break;
case CMD_FAST_READ: {
uint8_t end_block_num = p_data[2];
if ((block_num > end_block_num) || (block_num >= get_block_max_by_tag_type(m_tag_type)) || (end_block_num >= get_block_max_by_tag_type(m_tag_type))) {
nfc_tag_14a_tx_nbit(NAK_INVALID_OPERATION_TBV, 4);
break;
}
for (int block = block_num; block <= end_block_num; block++) {
memcpy(m_tag_tx_buffer.tx_buffer + (block - block_num) * 4, m_tag_information->memory[block], NFC_TAG_NTAG_DATA_SIZE);
}
nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, (end_block_num - block_num + 1) * NFC_TAG_NTAG_DATA_SIZE, true);
break;
}
case CMD_WRITE:
// TODO
nfc_tag_14a_tx_nbit(ACK_VALUE, 4);
break;
case CMD_COMPAT_WRITE:
// TODO
break;
case CMD_PWD_AUTH: {
/* TODO: IMPLEMENT COUNTER AUTHLIM */
uint8_t Password[4];
memcpy(Password, m_tag_information->memory[get_block_cfg_by_tag_type(m_tag_type) + CONF_PASSWORD_OFFSET], 4);
if (Password[0] != p_data[1] || Password[1] != p_data[2] || Password[2] != p_data[3] || Password[3] != p_data[4]) {
nfc_tag_14a_tx_nbit(NAK_INVALID_OPERATION_TBIV, 4);
break;
}
/* Authenticate the user */
//RESET AUTHLIM COUNTER, CURRENTLY NOT IMPLEMENTED
// TODO
/* Send the PACK value back */
if (m_tag_information->config.mode_uid_magic) {
nfc_tag_14a_tx_bytes(ntagPwdOK, 2, true);
} else {
nfc_tag_14a_tx_bytes(m_tag_information->memory[get_block_cfg_by_tag_type(m_tag_type) + CONF_PASSWORD_OFFSET], 2, true);
}
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);
break;
}
return;
}
nfc_tag_14a_coll_res_reference_t *get_ntag_coll_res() {
// Use a separate anti -conflict information instead of using the information in the sector
m_shadow_coll_res.sak = m_tag_information->res_coll.sak;
m_shadow_coll_res.atqa = m_tag_information->res_coll.atqa;
m_shadow_coll_res.uid = m_tag_information->res_coll.uid;
m_shadow_coll_res.size = &(m_tag_information->res_coll.size);
m_shadow_coll_res.ats = &(m_tag_information->res_coll.ats);
// Finally, a shadow data structure pointer with only reference, no physical shadow,
return &m_shadow_coll_res;
}
void nfc_tag_ntag_reset_handler() {
// TODO
}
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_ntag_configure_t) + (get_block_max_by_tag_type(type) * NFC_TAG_NTAG_DATA_SIZE);
}
/** @brief ntag's callback before saving data
* @param type detailed label type
* @param buffer data buffer
* @return to be saved, the length of the data that needs to be saved, it means not saved when 0
*/
int nfc_tag_ntag_data_savecb(tag_specific_type_t type, tag_data_buffer_t *buffer) {
if (m_tag_type != TAG_TYPE_UNDEFINED) {
// Save the corresponding size data according to the current label type
return get_information_size_by_tag_type(type);
} else {
return 0;
}
}
int nfc_tag_ntag_data_loadcb(tag_specific_type_t type, tag_data_buffer_t *buffer) {
int info_size = get_information_size_by_tag_type(type);
if (buffer->length >= info_size) {
// Convert the data buffer to NTAG structure type
m_tag_information = (nfc_tag_ntag_information_t *)buffer->buffer;
// The specific type of NTAG that is simulated by the cache
m_tag_type = type;
// Register 14A communication management interface
nfc_tag_14a_handler_t handler_for_14a = {
.get_coll_res = get_ntag_coll_res,
.cb_state = nfc_tag_ntag_state_handler,
.cb_reset = nfc_tag_ntag_reset_handler,
};
nfc_tag_14a_set_handler(&handler_for_14a);
NRF_LOG_INFO("HF ntag data load finish.");
} else {
NRF_LOG_ERROR("nfc_tag_ntag_information_t too big.");
}
return info_size;
}
// Initialized NTAG factory data
bool nfc_tag_ntag_data_factory(uint8_t slot, tag_specific_type_t tag_type) {
// default ntag data
uint8_t default_p0[] = { 0x04, 0x68, 0x95, 0x71 };
uint8_t default_p1[] = { 0xFA, 0x5C, 0x64, 0x80 };
uint8_t default_p2[] = { 0x42, 0x48, 0x0F, 0xE0 };
// default ntag info
nfc_tag_ntag_information_t ntag_tmp_information;
nfc_tag_ntag_information_t *p_ntag_information;
p_ntag_information = &ntag_tmp_information;
int block_max = get_block_max_by_tag_type(tag_type);
for (int block = 0; block < block_max; block++) {
if (block == 0) {
memcpy(p_ntag_information->memory[block], default_p0, NFC_TAG_NTAG_DATA_SIZE);
}
if (block == 1) {
memcpy(p_ntag_information->memory[block], default_p1, NFC_TAG_NTAG_DATA_SIZE);
}
if (block == 2) {
memcpy(p_ntag_information->memory[block], default_p2, NFC_TAG_NTAG_DATA_SIZE);
}
}
// default ntag auto ant-collision res
p_ntag_information->res_coll.atqa[0] = 0x44;
p_ntag_information->res_coll.atqa[1] = 0x00;
p_ntag_information->res_coll.sak[0] = 0x00;
p_ntag_information->res_coll.uid[0] = 0x04;
p_ntag_information->res_coll.uid[1] = 0x68;
p_ntag_information->res_coll.uid[2] = 0x95;
p_ntag_information->res_coll.uid[3] = 0x71;
p_ntag_information->res_coll.uid[4] = 0xFA;
p_ntag_information->res_coll.uid[5] = 0x5C;
p_ntag_information->res_coll.uid[6] = 0x64;
p_ntag_information->res_coll.size = NFC_TAG_14A_UID_DOUBLE_SIZE;
p_ntag_information->res_coll.ats.length = 0;
// default ntag config
p_ntag_information->config.mode_uid_magic = true;
p_ntag_information->config.detection_enable = false;
// save data to flash
tag_sense_type_t sense_type = get_sense_type_from_tag_type(tag_type);
fds_slot_record_map_t map_info;
get_fds_map_by_slot_sense_type_for_dump(slot, sense_type, &map_info);
int info_size = get_information_size_by_tag_type(tag_type);
NRF_LOG_INFO("NTAG info size: %d", info_size);
bool ret = fds_write_sync(map_info.id, map_info.key, info_size, p_ntag_information);
if (ret) {
NRF_LOG_INFO("Factory slot data success.");
} else {
NRF_LOG_ERROR("Factory slot data error.");
}
return ret;
}
@@ -1,39 +0,0 @@
#ifndef NFC_NTAG_H
#define NFC_NTAG_H
#include "nfc_14a.h"
#define NFC_TAG_NTAG_DATA_SIZE 4
#define NFC_TAG_NTAG_FRAME_SIZE 64
#define NFC_TAG_NTAG_BLOCK_MAX 231
#define NTAG213_PAGES 45 //45 pages total for ntag213, from 0 to 44
#define NTAG215_PAGES 135 //135 pages total for ntag215, from 0 to 134
#define NTAG216_PAGES 231 //231 pages total for ntag216, from 0 to 230
typedef struct {
uint8_t mode_uid_magic: 1;
uint8_t detection_enable: 1;
// reserve
uint8_t reserved1: 5;
uint8_t reserved2;
uint8_t reserved3;
} nfc_tag_ntag_configure_t;
typedef struct __attribute__((aligned(4))) {
nfc_tag_14a_coll_res_entity_t res_coll;
nfc_tag_ntag_configure_t config;
uint8_t memory[NFC_TAG_NTAG_BLOCK_MAX][NFC_TAG_NTAG_DATA_SIZE];
}
nfc_tag_ntag_information_t;
typedef struct {
uint8_t tx_buffer[NFC_TAG_NTAG_FRAME_SIZE];
} nfc_tag_ntag_tx_buffer_t;
int nfc_tag_ntag_data_loadcb(tag_specific_type_t type, tag_data_buffer_t *buffer);
int nfc_tag_ntag_data_savecb(tag_specific_type_t type, tag_data_buffer_t *buffer);
bool nfc_tag_ntag_data_factory(uint8_t slot, tag_specific_type_t tag_type);
#endif
@@ -75,6 +75,10 @@ typedef enum {
TAG_TYPE_NTAG_213 = 1100,
TAG_TYPE_NTAG_215,
TAG_TYPE_NTAG_216,
TAG_TYPE_MF0ICU1,
TAG_TYPE_MF0ICU2,
TAG_TYPE_MF0UL11,
TAG_TYPE_MF0UL21,
// MIFARE Plus series 1200
// DESFire series 1300
@@ -106,7 +110,11 @@ typedef enum {
TAG_TYPE_MIFARE_4096,\
TAG_TYPE_NTAG_213,\
TAG_TYPE_NTAG_215,\
TAG_TYPE_NTAG_216
TAG_TYPE_NTAG_216,\
TAG_TYPE_MF0ICU1,\
TAG_TYPE_MF0ICU2,\
TAG_TYPE_MF0UL11,\
TAG_TYPE_MF0UL21
typedef struct {
tag_specific_type_t tag_hf;
@@ -2,7 +2,7 @@
#include "nfc_14a.h"
#include "lf_tag_em.h"
#include "nfc_mf1.h"
#include "nfc_ntag.h"
#include "nfc_mf0_ntag.h"
#include "fds_ids.h"
#include "fds_util.h"
#include "tag_emulation.h"
@@ -71,7 +71,7 @@ static tag_slot_config_t slotConfig ALIGN_U32 = {
// See tag_emulation_factory_init for actual tag content
.slots = {
{ .enabled_hf = true, .enabled_lf = true, .tag_hf = TAG_TYPE_MIFARE_1024, .tag_lf = TAG_TYPE_EM410X, }, // 1
{ .enabled_hf = true, .enabled_lf = false, .tag_hf = TAG_TYPE_MIFARE_1024, .tag_lf = TAG_TYPE_UNDEFINED, }, // 2
{ .enabled_hf = true, .enabled_lf = false, .tag_hf = TAG_TYPE_MF0ICU1, .tag_lf = TAG_TYPE_UNDEFINED, }, // 2
{ .enabled_hf = false, .enabled_lf = true, .tag_hf = TAG_TYPE_UNDEFINED, .tag_lf = TAG_TYPE_EM410X, }, // 3
{ .enabled_hf = false, .enabled_lf = false, .tag_hf = TAG_TYPE_UNDEFINED, .tag_lf = TAG_TYPE_UNDEFINED, }, // 4
{ .enabled_hf = false, .enabled_lf = false, .tag_hf = TAG_TYPE_UNDEFINED, .tag_lf = TAG_TYPE_UNDEFINED, }, // 5
@@ -100,9 +100,11 @@ static tag_base_handler_map_t tag_base_map[] = {
{ TAG_SENSE_HF, TAG_TYPE_MIFARE_2048, nfc_tag_mf1_data_loadcb, nfc_tag_mf1_data_savecb, nfc_tag_mf1_data_factory, &m_tag_data_hf },
{ TAG_SENSE_HF, TAG_TYPE_MIFARE_4096, nfc_tag_mf1_data_loadcb, nfc_tag_mf1_data_savecb, nfc_tag_mf1_data_factory, &m_tag_data_hf },
// NTAG tag simulation
{ TAG_SENSE_HF, TAG_TYPE_NTAG_213, nfc_tag_ntag_data_loadcb, nfc_tag_ntag_data_savecb, nfc_tag_ntag_data_factory, &m_tag_data_hf },
{ TAG_SENSE_HF, TAG_TYPE_NTAG_215, nfc_tag_ntag_data_loadcb, nfc_tag_ntag_data_savecb, nfc_tag_ntag_data_factory, &m_tag_data_hf },
{ TAG_SENSE_HF, TAG_TYPE_NTAG_216, nfc_tag_ntag_data_loadcb, nfc_tag_ntag_data_savecb, nfc_tag_ntag_data_factory, &m_tag_data_hf },
{ TAG_SENSE_HF, TAG_TYPE_NTAG_213, nfc_tag_mf0_ntag_data_loadcb, nfc_tag_mf0_ntag_data_savecb, nfc_tag_mf0_ntag_data_factory, &m_tag_data_hf },
{ TAG_SENSE_HF, TAG_TYPE_NTAG_215, nfc_tag_mf0_ntag_data_loadcb, nfc_tag_mf0_ntag_data_savecb, nfc_tag_mf0_ntag_data_factory, &m_tag_data_hf },
{ TAG_SENSE_HF, TAG_TYPE_NTAG_216, nfc_tag_mf0_ntag_data_loadcb, nfc_tag_mf0_ntag_data_savecb, nfc_tag_mf0_ntag_data_factory, &m_tag_data_hf },
// MF0 tag simulation
{ TAG_SENSE_HF, TAG_TYPE_MF0ICU1, nfc_tag_mf0_ntag_data_loadcb, nfc_tag_mf0_ntag_data_savecb, nfc_tag_mf0_ntag_data_factory, &m_tag_data_hf },
};
@@ -701,7 +703,7 @@ void tag_emulation_factory_init(void) {
}
}
if (slotConfig.slots[1].enabled_hf && slotConfig.slots[1].tag_hf == TAG_TYPE_MIFARE_1024) {
if (slotConfig.slots[1].enabled_hf && slotConfig.slots[1].tag_hf == TAG_TYPE_MF0ICU1) {
// Initialize a high -frequency M1 card in the card slot 2, if it does not exist.
get_fds_map_by_slot_sense_type_for_dump(1, TAG_SENSE_HF, &map_info);
if (!fds_is_exists(map_info.id, map_info.key)) {
+1 -1
View File
@@ -8,7 +8,7 @@
#include "hw_connect.h"
#include "nfc_14a.h"
#include "nfc_mf1.h"
#include "nfc_ntag.h"
#include "nfc_mf0_ntag.h"
#include "lf_tag_em.h"
#include "tag_emulation.h"
+24 -1
View File
@@ -1744,9 +1744,12 @@ class HFMFUDUMP(MFUAuthArgsUnit):
class HFMFUEConfig(SlotIndexArgsAndGoUnit, HF14AAntiCollArgsUnit, DeviceRequiredUnit):
def args_parser(self) -> ArgumentParserNoExit:
parser = ArgumentParserNoExit()
parser.description = 'Settings of Mifare Classic emulator'
parser.description = 'Settings of Mifare Ultralight / NTAG emulator'
self.add_slot_args(parser)
self.add_hf14a_anticoll_args(parser)
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")
return parser
def on_exec(self, args: argparse.Namespace):
@@ -1763,6 +1766,10 @@ class HFMFUEConfig(SlotIndexArgsAndGoUnit, HF14AAntiCollArgsUnit, DeviceRequired
fwslot = SlotNumber.to_fw(self.slot_num)
hf_tag_type = TagSpecificType(slotinfo[fwslot]['hf'])
if hf_tag_type not in [
TagSpecificType.MF0ICU1,
TagSpecificType.MF0ICU2,
TagSpecificType.MF0UL11,
TagSpecificType.MF0UL21,
TagSpecificType.NTAG_213,
TagSpecificType.NTAG_215,
TagSpecificType.NTAG_216,
@@ -1770,6 +1777,18 @@ class HFMFUEConfig(SlotIndexArgsAndGoUnit, HF14AAntiCollArgsUnit, DeviceRequired
print(f"{CR}Slot {self.slot_num} not configured as MIFARE Ultralight / NTAG{C0}")
return
change_requested, change_done, uid, atqa, sak, ats = self.update_hf14a_anticoll(args, uid, atqa, sak, ats)
if args.enable_uid_magic:
change_requested = True
self.cmd.mf0_ntag_set_uid_magic_mode(True)
magic_mode = True
elif args.disable_uid_magic:
change_requested = True
self.cmd.mf0_ntag_set_uid_magic_mode(False)
magic_mode = False
else:
magic_mode = self.cmd.mf0_ntag_get_uid_magic_mode()
if change_done:
print(' - MFU/NTAG Emulator settings updated')
if not change_requested:
@@ -1780,6 +1799,10 @@ class HFMFUEConfig(SlotIndexArgsAndGoUnit, HF14AAntiCollArgsUnit, DeviceRequired
print(f'- {"SAK:":40}{CY}{sak.hex().upper()}{C0}')
if len(ats) > 0:
print(f'- {"ATS:":40}{CY}{ats.hex().upper()}{C0}')
if magic_mode:
print(f'- {"UID Magic:":40}{CY}enabled{C0}')
else:
print(f'- {"UID Magic:":40}{CY}disabled{C0}')
@lf_em_410x.command('read')
+11
View File
@@ -919,6 +919,17 @@ class ChameleonCMD:
resp.parsed = {'uid': uid, 'atqa': atqa, 'sak': sak, 'ats': ats}
return resp
@expect_response(Status.SUCCESS)
def mf0_ntag_get_uid_magic_mode(self):
resp = self.device.send_cmd_sync(Command.MF0_NTAG_GET_UID_MAGIC_MODE)
if resp.status == Status.SUCCESS:
resp.parsed, = struct.unpack('!?', resp.data)
return resp
@expect_response(Status.SUCCESS)
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 get_ble_pairing_enable(self):
"""
+15 -1
View File
@@ -95,6 +95,8 @@ class Command(enum.IntEnum):
MF1_GET_WRITE_MODE = 4016
MF1_SET_WRITE_MODE = 4017
HF14A_GET_ANTI_COLL_DATA = 4018
MF0_NTAG_GET_UID_MAGIC_MODE = 4019
MF0_NTAG_SET_UID_MAGIC_MODE = 4020
EM410X_SET_EMU_ID = 5000
EM410X_GET_EMU_ID = 5001
@@ -260,6 +262,10 @@ class TagSpecificType(enum.IntEnum):
NTAG_213 = 1100
NTAG_215 = 1101
NTAG_216 = 1102
MF0ICU1 = 1103
MF0ICU2 = 1104
MF0UL11 = 1105
MF0UL21 = 1106
# MIFARE Plus series 1200
# DESFire series 1300
@@ -303,6 +309,14 @@ class TagSpecificType(enum.IntEnum):
return "NTAG 215"
elif self == TagSpecificType.NTAG_216:
return "NTAG 216"
elif self == TagSpecificType.MF0ICU1:
return "Mifare Ultralight"
elif self == TagSpecificType.MF0ICU2:
return "Mifare Ultralight C"
elif self == TagSpecificType.MF0UL11:
return "Mifare Ultralight EV1 (640 bit)"
elif self == TagSpecificType.MF0UL21:
return "Mifare Ultralight EV1 (1312 bit)"
elif self < TagSpecificType.OLD_TAG_TYPES_END:
return "Old tag type, must be migrated! Upgrade fw!"
return "Invalid"
@@ -438,4 +452,4 @@ class ButtonPressFunction(enum.IntEnum):
class MfcValueBlockOperator(enum.IntEnum):
DECREMENT = 0xC0
INCREMENT = 0xC1
RESTORE = 0xC2
RESTORE = 0xC2