diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index 9400edbd..09fb2334 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -491,13 +491,17 @@ data_frame_tx_t *cmd_processor_get_mf1_anti_coll_data(uint16_t cmd, uint16_t sta if (tag_type[0] == TAG_TYPE_UNKNOWN) { return data_frame_make(cmd, STATUS_PAR_ERR, 0, data); // no data in slot, don't send garbage } - uint8_t responseData[16] = {}; + picc_14a_tag_t taginfo; nfc_tag_14a_coll_res_reference_t *info = get_saved_mifare_coll_res(); - memcpy(responseData, info->uid, *info->size); - responseData[10] = *info->size; // size is 2 byte len, but... - responseData[12] = info->sak[0]; - memcpy(&responseData[13], info->atqa, 2); - return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 16, responseData); + taginfo.uid_len = *info->size; + taginfo.cascade = (taginfo.uid_len + 2) / 4; //it's weird but it works for 4->1, 7->2, 10->3 + taginfo.sak = *info->sak; + taginfo.ats_len = info->ats->length; + memcpy(taginfo.uid, info->uid, taginfo.uid_len); + memcpy(taginfo.atqa, info->atqa, 2); + memcpy(taginfo.ats, info->ats->data, taginfo.ats_len); + + return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, sizeof(taginfo), (uint8_t*) &taginfo); } data_frame_tx_t *cmd_processor_set_mf1_detection_enable(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 030cd387..89a75efb 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -648,11 +648,16 @@ static void btn_fn_copy_ic_uid(void) { status = pcd_14a_reader_scan_auto(&tag); if (status == HF_TAG_OK) { // copy uid + antres->size = tag.uid_len; memcpy(antres->uid, tag.uid, tag.uid_len); // copy atqa memcpy(antres->atqa, tag.atqa, 2); // copy sak antres->sak[0] = tag.sak; + // copy ats + antres->ats.length = tag.ats_len; + memcpy(antres->ats.data, tag.ats, tag.ats_len); + NRF_LOG_INFO("Offline HF uid copied") offline_status_ok(); } else { diff --git a/firmware/application/src/app_status.h b/firmware/application/src/app_status.h index 44ddc010..442dba57 100644 --- a/firmware/application/src/app_status.h +++ b/firmware/application/src/app_status.h @@ -13,7 +13,7 @@ #define HF_ERR_BCC (0x05) // IC card BCC error #define MF_ERR_AUTH (0x06) // MF card verification failed #define HF_ERR_PARITY (0x07) // IC card parity error - +#define HF_ERR_ATS (0x08) // ATS should be present but card NAKed ///////////////////////////////////////////////////////////////////// // MIFARE status diff --git a/firmware/application/src/rfid/reader/hf/rc522.c b/firmware/application/src/rfid/reader/hf/rc522.c index 29d3c27c..8c41b9cc 100644 --- a/firmware/application/src/rfid/reader/hf/rc522.c +++ b/firmware/application/src/rfid/reader/hf/rc522.c @@ -491,6 +491,7 @@ uint8_t pcd_14a_reader_scan_once(picc_14a_tag_t *tag) { if (tag) { tag->uid_len = 0; memset(tag->uid, 0, 10); + tag->ats_len = 0; } else { return STATUS_PAR_ERR; // Finding cards are not allowed to be transmitted to the label information structure } @@ -579,6 +580,22 @@ uint8_t pcd_14a_reader_scan_once(picc_14a_tag_t *tag) { // Therefore + 1 tag->cascade = cascade_level + 1; } + if (tag->sak & 0x20) { + // Tag supports 14443-4, sending RATS + uint16_t ats_size; + status = pcd_14a_reader_ats_request(tag->ats, &ats_size, 0xFF*8); + ats_size -= 2; // size returned by pcd_14a_reader_ats_request includes CRC + ASSERT(ats_size <= 0xFF); + if (tag->ats[0] != ats_size) { + NRF_LOG_INFO("Invalid ATS! First byte doesn't match received length\n"); + return HF_ERR_ATS; + } + tag->ats_len = ats_size; + if (status != HF_TAG_OK) { + NRF_LOG_INFO("Tag SAK claimed to support ATS but tag NAKd RATS\n"); + return HF_ERR_ATS; + } + } return HF_TAG_OK; } diff --git a/firmware/application/src/rfid/reader/hf/rc522.h b/firmware/application/src/rfid/reader/hf/rc522.h index be1493f7..ad9704b5 100644 --- a/firmware/application/src/rfid/reader/hf/rc522.h +++ b/firmware/application/src/rfid/reader/hf/rc522.h @@ -157,6 +157,8 @@ typedef struct { uint8_t cascade; // theAntiCollisionLevelValueIs1Representation 4Byte,2Represents7Byte,3Means10Byte uint8_t sak; // chooseToConfirm uint8_t atqa[2]; // requestResponse + uint8_t ats[0xFF];// 14443-4 answer to select + uint8_t ats_len; // 14443-4 answer to select size } picc_14a_tag_t; #ifdef __cplusplus diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 440e22f9..c38d56e4 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -294,6 +294,9 @@ def scan(self): print(f"- UID Hex : {info['uid_hex'].upper()}") print(f"- SAK Hex : {info['sak_hex'].upper()}") print(f"- ATQA Hex : {info['atqa_hex'].upper()}") + if info['ats_size']: + print(f"- ATS Size: {info['ats_size']}") + print(f"- ATS Hex : {info['ats_hex'].upper()}") return True else: print("ISO14443-A Tag no found") @@ -853,6 +856,9 @@ def scan(self): print(f"- UID Hex : {info['uid_hex'].upper()}") print(f"- SAK Hex : {info['sak_hex'].upper()}") print(f"- ATQA Hex : {info['atqa_hex'].upper()}") + if info['ats_size']: + print(f"- ATS Size: {info['ats_size']}") + print(f"- ATS Hex : {info['ats_hex'].upper()}") return True else: print("No data loaded in slot") diff --git a/software/script/chameleon_cstruct.py b/software/script/chameleon_cstruct.py index 14edc5fe..5daa7a2a 100644 --- a/software/script/chameleon_cstruct.py +++ b/software/script/chameleon_cstruct.py @@ -20,9 +20,11 @@ def parse_14a_scan_tag_result(data: bytearray): """ return { 'uid_size': data[10], - 'uid_hex': data[0:data[10]].hex(), + 'uid_hex': data[0:data[10]].hex(' '), 'sak_hex': hex(data[12]).lstrip('0x').rjust(2, '0'), - 'atqa_hex': data[13:15].hex().upper() + 'atqa_hex': data[13:15].hex(' '), + 'ats_size': data[270], + 'ats_hex': data[15:15 + data[270]].hex(' '), } diff --git a/software/script/chameleon_status.py b/software/script/chameleon_status.py index c3a9180b..9ef5ebe5 100644 --- a/software/script/chameleon_status.py +++ b/software/script/chameleon_status.py @@ -22,6 +22,7 @@ class Device(metaclass=MetaDevice): HF_ERR_BCC = 0x05 # IC card BCC error MF_ERR_AUTH = 0x06 # MF card verification failed HF_ERR_PARITY = 0x07 # IC card parity error + HF_ERR_ATS = 0x08 # ATS should be present but card NAKed # Darkside, the random number cannot be fixed, this situation may appear on the UID card DARKSIDE_CANT_FIXED_NT = 0x20 @@ -63,6 +64,7 @@ class Device(metaclass=MetaDevice): Device.HF_ERR_BCC: "HF tag uid bcc error", Device.MF_ERR_AUTH: "HF tag auth fail", Device.HF_ERR_PARITY: "HF tag data parity error", + Device.HF_ERR_ATS: "HF tag was supposed to send ATS but didn't", Device.DARKSIDE_CANT_FIXED_NT: "Darkside Can't select a nt(PRNG is unpredictable)", Device.DARKSIDE_LUCK_AUTH_OK: "Darkside try to recover a default key",