Skip to content

Commit

Permalink
new tag_specific_type_t enum, new slotConfig struct. FW will take car…
Browse files Browse the repository at this point in the history
…e of existing slots. Disruptive changes: see below

Disruptive changes:
- tag types are 2-byte long with new values
- GET_SLOT_INFO returns 32 bytes as tag types are now 2-byte long
- "enable" is not common to one slot anymore but bound to the HF or LF part
- GET_ENABLED_SLOTS returns 16 bytes as we get "enabled_hf" and "enabled_lf" for each slot
- SET_SLOT_ENABLE needs 3 bytes slot_number|sense_type|enable as we need to specify to enable HF or LF
- slotConfig changed a lot but this is internal to the fw and its flash and a function does the format conversion on first boot after flash
  so slot data is preserved on fw upgrade, but if one downgrades to a previous version, data will be erased.
  • Loading branch information
doegox committed Sep 23, 2023
1 parent 879b8e3 commit 7da58bb
Show file tree
Hide file tree
Showing 18 changed files with 533 additions and 232 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...

## [unreleased][unreleased]
- slot_number|sense_type|enable
Disruptive changes:
- Changed slot enabled logic: now we have separate enabled_hf and enabled_lf, changed GET_ENABLED_SLOTS and SET_SLOT_ENABLE (@doegox)
- Changed tag type enum to be ready for new types, changed stored slotConfig and GET_SLOT_INFO (@doegox)
- Removed MF1_DETECT_DARKSIDE (@doegox)
- Added MF1_STATIC_NESTED_ACQUIRE and its support in `hf mf nested` (@xianglin1998)
- Changed `hf 14a scan`: Automatically send RATS to 14443-4a tags (@augustozanellato)
Expand Down
7 changes: 2 additions & 5 deletions docs/protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ Each command and response have their own payload formats.
Standard response status is `STATUS_DEVICE_SUCCESS` for general commands, `HF_TAG_OK` for HF commands and `LF_TAG_OK` for LF commands.
See [Guidelines](#new-data-payloads-guidelines-for-developers) for more info.

* **TODO:** remap `tag_specific_type_t` enum. Maybe dissociate LF & HF types in 2 enums
* **TODO:** num_to_bytes bytes_to_num
* **TODO:** mf1_darkside_acquire /nested acquire deep PACKED struct...
* **FIXME:** mf1_get_emulator_config with bits -> bytes (5) with 4 bools <> mf1_get_detection_log with bitfield (2)...

Beware, slots in protocol count from 0 to 7 (and from 1 to 8 in the CLI...).
Expand Down Expand Up @@ -68,7 +66,7 @@ In the following list, "CLI" refers to one typical CLI command using the describ
* Response: no data
* CLI: cf `hw slot init`
### 1006: SET_SLOT_ENABLE
* Command: 2 bytes. `slot_number|enable` with `slot_number` between 0 and 7 and `enable` = `0x01` to enable, `0x00` to disable
* Command: 3 bytes. `slot_number|sense_type|enable` with `slot_number` between 0 and 7, `sense_type` according to `tag_sense_type_t` enum and `enable` = `0x01` to enable, `0x00` to disable
* Response: no data
* CLI: cf `hw slot enable`
### 1007: SET_SLOT_TAG_NICK
Expand Down Expand Up @@ -129,7 +127,7 @@ In the following list, "CLI" refers to one typical CLI command using the describ
* CLI: cf `hw factory_reset`
### 1023: GET_ENABLED_SLOTS
* Command: no data
* Response: 8 bytes, 8 bool = `0x00` or `0x01`, for slots from 0 to 7
* Response: 16 bytes, 8*2 bool = `0x00` or `0x01`, 2 bytes for each slot from 0 to 7, as `enabled_hf|enabled_lf`
### 1024: DELETE_SLOT_SENSE_TYPE
* Command: 2 bytes. `slot_number|sense_type` with `slot_number` between 0 and 7 and `sense_type` according to `tag_sense_type_t` enum.
* Response: no data
Expand Down Expand Up @@ -227,7 +225,6 @@ Notes:
* `nr[4]` U32
* `ar[4]` U32
* CLI: cf `hf mf darkside`
* **FIXME:** always `CANT_FIX_NT` or watchdog reset on static nonce cards
### 2005: MF1_DETECT_NT_DIST
* Command: 8 bytes: `type_known|block_known|key_known[6]`. Key as 6 bytes.
* Response: 8 bytes: `uid[4]|dist[4]`
Expand Down
66 changes: 37 additions & 29 deletions firmware/application/src/app_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,10 @@ static data_frame_tx_t *cmd_processor_hf14a_raw(uint16_t cmd, uint16_t status, u
uint8_t auto_select : 1;
uint8_t bit_frame : 1;
uint8_t append_crc : 1;
uint8_t wait_response : 1;
uint8_t wait_response : 1;
uint8_t open_rf_field : 1;
} options;

// U16NTOHS
uint16_t resp_timeout;
uint16_t data_length;
Expand All @@ -435,16 +435,16 @@ static data_frame_tx_t *cmd_processor_hf14a_raw(uint16_t cmd, uint16_t status, u
NRF_LOG_INFO("keep_rf_field = %d", payload->options.keep_rf_field);
NRF_LOG_INFO("check_response_crc = %d", payload->options.check_response_crc);
NRF_LOG_INFO("reserved = %d", payload->options.reserved);

status = pcd_14a_reader_raw_cmd(
payload->options.open_rf_field,
payload->options.wait_response,
payload->options.append_crc,
payload->options.bit_frame,
payload->options.auto_select,
payload->options.keep_rf_field,
payload->options.check_response_crc,
payload->options.wait_response,
payload->options.append_crc,
payload->options.bit_frame,
payload->options.auto_select,
payload->options.keep_rf_field,
payload->options.check_response_crc,

U16NTOHS(payload->resp_timeout),

U16NTOHS(payload->data_length),
Expand Down Expand Up @@ -504,7 +504,7 @@ static data_frame_tx_t *cmd_processor_set_slot_tag_type(uint16_t cmd, uint16_t s

payload_t *payload = (payload_t *)data;
tag_specific_type_t tag_type = U16NTOHS(payload->tag_type);
if (payload->num_slot >= TAG_MAX_SLOT_NUM || tag_type == TAG_TYPE_UNKNOWN) {
if (payload->num_slot >= TAG_MAX_SLOT_NUM || !is_tag_specific_type_valid(tag_type)) {
return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL);
}
tag_emulation_change_type(payload->num_slot, tag_type);
Expand Down Expand Up @@ -538,7 +538,7 @@ static data_frame_tx_t *cmd_processor_set_slot_data_default(uint16_t cmd, uint16

payload_t *payload = (payload_t *)data;
tag_specific_type_t tag_type = U16NTOHS(payload->tag_type);
if (payload->num_slot >= TAG_MAX_SLOT_NUM || tag_type == TAG_TYPE_UNKNOWN) {
if (payload->num_slot >= TAG_MAX_SLOT_NUM || !is_tag_specific_type_valid(tag_type)) {
return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL);
}
status = tag_emulation_factory_data(payload->num_slot, tag_type) ? STATUS_DEVICE_SUCCESS : STATUS_NOT_IMPLEMENTED;
Expand All @@ -548,20 +548,23 @@ static data_frame_tx_t *cmd_processor_set_slot_data_default(uint16_t cmd, uint16
static data_frame_tx_t *cmd_processor_set_slot_enable(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
typedef struct {
uint8_t slot_index;
uint8_t sense_type;
uint8_t enabled;
} PACKED payload_t;

payload_t *payload = (payload_t *)data;
if (length != sizeof(payload_t) ||
payload->slot_index >= TAG_MAX_SLOT_NUM ||
(payload->sense_type != TAG_SENSE_HF && payload->sense_type != TAG_SENSE_LF) ||
payload->enabled > 1) {
return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL);
}

uint8_t slot_now = payload->slot_index;
bool enable = payload->enabled;
tag_emulation_slot_set_enable(slot_now, enable);
if (!enable) {
tag_emulation_slot_set_enable(slot_now, payload->sense_type, payload->enabled);
if ((!payload->enabled) &&
(!tag_emulation_slot_is_enabled(slot_now, payload->sense_type == TAG_SENSE_HF ? TAG_SENSE_LF : TAG_SENSE_HF))) {
// HF and LF disabled, need to change slot
uint8_t slot_prev = tag_emulation_slot_find_next(slot_now);
NRF_LOG_INFO("slot_now = %d, slot_prev = %d", slot_now, slot_prev);
if (slot_prev == slot_now) {
Expand Down Expand Up @@ -589,11 +592,11 @@ static data_frame_tx_t *cmd_processor_get_slot_info(uint16_t cmd, uint16_t statu
uint16_t lf_tag_type;
} PACKED payload[8];

tag_specific_type_t tag_type[2];
tag_slot_specific_type_t tag_types;
for (uint8_t slot = 0; slot < 8; slot++) {
tag_emulation_get_specific_type_by_slot(slot, tag_type);
payload[slot].hf_tag_type = U16HTONS(tag_type[0]);
payload[slot].lf_tag_type = U16HTONS(tag_type[1]);
tag_emulation_get_specific_types_by_slot(slot, &tag_types);
payload[slot].hf_tag_type = U16HTONS(tag_types.tag_hf);
payload[slot].lf_tag_type = U16HTONS(tag_types.tag_lf);
}

return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, sizeof(payload), (uint8_t *)&payload);
Expand All @@ -617,9 +620,9 @@ static data_frame_tx_t *cmd_processor_em410x_set_emu_id(uint16_t cmd, uint16_t s
}

static data_frame_tx_t *cmd_processor_em410x_get_emu_id(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
tag_specific_type_t tag_type[2];
tag_emulation_get_specific_type_by_slot(tag_emulation_get_slot(), tag_type);
if (tag_type[1] == TAG_TYPE_UNKNOWN) {
tag_slot_specific_type_t tag_types;
tag_emulation_get_specific_types_by_slot(tag_emulation_get_slot(), &tag_types);
if (tag_types.tag_lf != TAG_TYPE_EM410X) {
return data_frame_make(cmd, STATUS_PAR_ERR, 0, data); // no data in slot, don't send garbage
}
tag_data_buffer_t *buffer = get_buffer_by_tag_type(TAG_TYPE_EM410X);
Expand All @@ -629,9 +632,9 @@ static data_frame_tx_t *cmd_processor_em410x_get_emu_id(uint16_t cmd, uint16_t s
}

static data_frame_tx_t *cmd_processor_hf14a_get_anti_coll_data(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
tag_specific_type_t tag_type[2];
tag_emulation_get_specific_type_by_slot(tag_emulation_get_slot(), tag_type);
if (tag_type[0] == TAG_TYPE_UNKNOWN) {
tag_slot_specific_type_t tag_types;
tag_emulation_get_specific_types_by_slot(tag_emulation_get_slot(), &tag_types);
if (tag_types.tag_hf == TAG_TYPE_UNDEFINED) {
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 0, NULL); // no data in slot, don't send garbage
}
nfc_tag_14a_coll_res_reference_t *info = get_saved_mifare_coll_res();
Expand Down Expand Up @@ -792,7 +795,8 @@ static data_frame_tx_t *cmd_processor_get_slot_tag_nick(uint16_t cmd, uint16_t s
return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL);
}
get_fds_map_by_slot_sense_type_for_nick(slot, sense_type, &map_info);
bool ret = fds_read_sync(map_info.id, map_info.key, sizeof(buffer), buffer);
uint16_t buffer_length = sizeof(buffer);
bool ret = fds_read_sync(map_info.id, map_info.key, &buffer_length, buffer);
if (!ret) {
return data_frame_make(cmd, STATUS_FLASH_READ_FAIL, 0, NULL);
}
Expand Down Expand Up @@ -862,11 +866,15 @@ static data_frame_tx_t *cmd_processor_mf1_set_write_mode(uint16_t cmd, uint16_t
}

static data_frame_tx_t *cmd_processor_get_enabled_slots(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
uint8_t slot_info[8] = {};
struct {
uint8_t enabled_hf;
uint8_t enabled_lf;
} PACKED payload[8];
for (uint8_t slot = 0; slot < 8; slot++) {
slot_info[slot] = tag_emulation_slot_is_enable(slot);
payload[slot].enabled_hf = tag_emulation_slot_is_enabled(slot, TAG_SENSE_HF);
payload[slot].enabled_lf = tag_emulation_slot_is_enabled(slot, TAG_SENSE_LF);
}
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, sizeof(slot_info), slot_info);
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, sizeof(payload), (uint8_t*)&payload);
}

static data_frame_tx_t *cmd_processor_get_ble_connect_key(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
Expand Down
14 changes: 7 additions & 7 deletions firmware/application/src/app_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,8 +570,8 @@ static void btn_fn_copy_ic_uid(void) {
uint8_t id_buffer[5] = { 0x00 };
// get 14a tag res buffer;
uint8_t slot_now = tag_emulation_get_slot();
tag_specific_type_t tag_type[2];
tag_emulation_get_specific_type_by_slot(slot_now, tag_type);
tag_slot_specific_type_t tag_types;
tag_emulation_get_specific_types_by_slot(slot_now, &tag_types);

nfc_tag_14a_coll_res_entity_t *antres;

Expand All @@ -584,7 +584,7 @@ static void btn_fn_copy_ic_uid(void) {
NRF_LOG_INFO("Start reader mode to offline copy.")
}

switch (tag_type[1]) {
switch (tag_types.tag_lf) {
case TAG_TYPE_EM410X:
status = PcdScanEM410X(id_buffer);

Expand All @@ -599,16 +599,16 @@ static void btn_fn_copy_ic_uid(void) {
offline_status_error();
}
break;
case TAG_TYPE_UNKNOWN:
case TAG_TYPE_UNDEFINED:
// empty LF slot, nothing to do, move on to HF
break;
default:
NRF_LOG_ERROR("Unsupported LF tag type")
offline_status_error();
}

tag_data_buffer_t *buffer = get_buffer_by_tag_type(tag_type[0]);
switch (tag_type[0]) {
tag_data_buffer_t *buffer = get_buffer_by_tag_type(tag_types.tag_hf);
switch (tag_types.tag_hf) {
case TAG_TYPE_MIFARE_Mini:
case TAG_TYPE_MIFARE_1024:
case TAG_TYPE_MIFARE_2048:
Expand All @@ -626,7 +626,7 @@ static void btn_fn_copy_ic_uid(void) {
break;
}

case TAG_TYPE_UNKNOWN:
case TAG_TYPE_UNDEFINED:
// empty HF slot, nothing to do
goto exit;

Expand Down
2 changes: 1 addition & 1 deletion firmware/application/src/rfid/nfctag/hf/nfc_mf1.c
Original file line number Diff line number Diff line change
Expand Up @@ -1114,7 +1114,7 @@ static int get_information_size_by_tag_type(tag_specific_type_t type, bool auth_
* @return The length of the data that needs to be saved is that it does not save when 0
*/
int nfc_tag_mf1_data_savecb(tag_specific_type_t type, tag_data_buffer_t *buffer) {
if (m_tag_type != TAG_TYPE_UNKNOWN) {
if (m_tag_type != TAG_TYPE_UNDEFINED) {
if (m_tag_information->config.mode_block_write == NFC_TAG_MF1_WRITE_SHADOW) {
NRF_LOG_INFO("The mf1 is shadow write mode.");
return 0;
Expand Down
2 changes: 1 addition & 1 deletion firmware/application/src/rfid/nfctag/hf/nfc_ntag.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ static int get_information_size_by_tag_type(tag_specific_type_t type) {
* @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_UNKNOWN) {
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 {
Expand Down
4 changes: 2 additions & 2 deletions firmware/application/src/rfid/nfctag/lf/lf_tag_em.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ static volatile bool m_is_lf_emulating = false;
// The timer of the delivery card number, we use the timer 3
const nrfx_timer_t m_timer_send_id = NRFX_TIMER_INSTANCE(3);
// Cache label type
static tag_specific_type_t m_tag_type = TAG_TYPE_UNKNOWN;
static tag_specific_type_t m_tag_type = TAG_TYPE_UNDEFINED;

/**
* @brief Convert the card number of EM410X to the memory layout of U64 and calculate the puppet school inspection
Expand Down Expand Up @@ -396,7 +396,7 @@ int lf_tag_em410x_data_loadcb(tag_specific_type_t type, tag_data_buffer_t *buffe
*/
int lf_tag_em410x_data_savecb(tag_specific_type_t type, tag_data_buffer_t *buffer) {
// Make sure to load this label before allowing saving
if (m_tag_type != TAG_TYPE_UNKNOWN) {
if (m_tag_type != TAG_TYPE_UNDEFINED) {
// Just save the original card package directly
return LF_EM410X_TAG_ID_SIZE;
} else {
Expand Down
95 changes: 87 additions & 8 deletions firmware/application/src/rfid/nfctag/tag_base_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,100 @@ typedef enum {
* Note that all the defined label type below is the specific type statistics of the application layer refine
* No longer distinguish between high and low frequencies
*/

typedef enum {
//Specific and necessary signs do not exist
TAG_TYPE_UNKNOWN,
//125kHz (ID card) series
TAG_TYPE_EM410X,
// MiFare series
TAG_TYPE_MIFARE_Mini,
TAG_TYPE_UNDEFINED = 0,

// old HL/LF common types, slots using these ones need to be migrated first
OLD_TAG_TYPE_EM410X,
OLD_TAG_TYPE_MIFARE_Mini,
OLD_TAG_TYPE_MIFARE_1024,
OLD_TAG_TYPE_MIFARE_2048,
OLD_TAG_TYPE_MIFARE_4096,
OLD_TAG_TYPE_NTAG_213,
OLD_TAG_TYPE_NTAG_215,
OLD_TAG_TYPE_NTAG_216,

//////////// LF ////////////

//////// ASK Tag-Talk-First 100
// EM410x
TAG_TYPE_EM410X = 100,
// FDX-B
// securakey
// gallagher
// PAC/Stanley
// Presco
// Visa2000
// Viking
// Noralsy
// Jablotron

//////// FSK Tag-Talk-First 200
// HID Prox
// ioProx
// AWID
// Paradox

//////// PSK Tag-Talk-First 300
// Indala
// Keri
// NexWatch

//////// Reader-Talk-First 400
// T5577
// EM4x05/4x69
// EM4x50/4x70
// Hitag series

//////////// HF ////////////

// MIFARE Classic series 1000
TAG_TYPE_MIFARE_Mini = 1000,
TAG_TYPE_MIFARE_1024,
TAG_TYPE_MIFARE_2048,
TAG_TYPE_MIFARE_4096,
// NTAG series
TAG_TYPE_NTAG_213,
// MFUL / NTAG series 1100
TAG_TYPE_NTAG_213 = 1100,
TAG_TYPE_NTAG_215,
TAG_TYPE_NTAG_216,
// MIFARE Plus series 1200
// DESFire series 1300

// ST25TA series 2000

// HF14A-4 series 3000

} tag_specific_type_t;

#define TAG_SPECIFIC_TYPE_OLD2NEW_LF_VALUES \
{OLD_TAG_TYPE_EM410X, TAG_TYPE_EM410X}

#define TAG_SPECIFIC_TYPE_OLD2NEW_HF_VALUES \
{OLD_TAG_TYPE_MIFARE_Mini, TAG_TYPE_MIFARE_Mini},\
{OLD_TAG_TYPE_MIFARE_1024, TAG_TYPE_MIFARE_1024},\
{OLD_TAG_TYPE_MIFARE_2048, TAG_TYPE_MIFARE_2048},\
{OLD_TAG_TYPE_MIFARE_4096, TAG_TYPE_MIFARE_4096},\
{OLD_TAG_TYPE_NTAG_213, TAG_TYPE_NTAG_213},\
{OLD_TAG_TYPE_NTAG_215, TAG_TYPE_NTAG_215},\
{OLD_TAG_TYPE_NTAG_216, TAG_TYPE_NTAG_216}

#define TAG_SPECIFIC_TYPE_LF_VALUES \
TAG_TYPE_EM410X

#define TAG_SPECIFIC_TYPE_HF_VALUES \
TAG_TYPE_MIFARE_Mini,\
TAG_TYPE_MIFARE_1024,\
TAG_TYPE_MIFARE_2048,\
TAG_TYPE_MIFARE_4096,\
TAG_TYPE_NTAG_213,\
TAG_TYPE_NTAG_215,\
TAG_TYPE_NTAG_216

typedef struct {
tag_specific_type_t tag_hf;
tag_specific_type_t tag_lf;
} tag_slot_specific_type_t;


#endif
Loading

0 comments on commit 7da58bb

Please sign in to comment.