From 5236a130666ba843630ff1c1a62bab18bfe83a44 Mon Sep 17 00:00:00 2001 From: Antiklesys Date: Mon, 30 Mar 2026 23:50:58 +0800 Subject: [PATCH 1/8] SECC Part 2 (fixed) --- armsrc/appmain.c | 10 ++++++ armsrc/iso14443a.c | 45 ++++++++++++++++++++------ armsrc/iso14443a.h | 21 +++++++++++- armsrc/secc.c | 14 ++++---- client/resources/hidconfig_sample.json | 2 +- client/src/cmdhf.c | 2 ++ 6 files changed, 75 insertions(+), 19 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 97c7544ce..4d7f74c8c 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -34,6 +34,7 @@ #include "iclass_cmd.h" #include "hfops.h" #include "iso14443a.h" +#include "secc.h" #include "iso14443b.h" #include "iso15693.h" #include "thinfilm.h" @@ -1837,6 +1838,11 @@ static void PacketReceived(PacketCommandNG *packet) { reply_ng(CMD_HF_ISO14443A_SNIFF, PM3_SUCCESS, NULL, 0); break; } + case CMD_HF_HIDCONFIG_SNIFF: { + SniffHIDConfigCard(packet->data.asBytes[0]); + reply_ng(CMD_HF_HIDCONFIG_SNIFF, PM3_SUCCESS, NULL, 0); + break; + } case CMD_HF_ISO14443A_READER: { ReaderIso14443a(packet); break; @@ -1898,6 +1904,10 @@ static void PacketReceived(PacketCommandNG *packet) { payload->getdata_response, payload->getdata_response_len); break; } + case CMD_HF_HIDCONFIG_SIM: { + SimulateHIDConfigCard((const hid_sim_payload_t *) packet->data.asBytes); + break; + } case CMD_HF_ISO14443A_ANTIFUZZ: { struct p { uint8_t flag; diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index f06dbd100..9430224b2 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -38,8 +38,6 @@ #include "mifare.h" // for iso14a_polling_frame_t structure #include "cmac_calc.h" -#define MAX_ISO14A_TIMEOUT 524288 -// this timeout is in MS static uint32_t iso14a_timeout; static uint8_t colpos = 0; @@ -47,6 +45,10 @@ static uint8_t colpos = 0; // the block number for the ISO14443-4 PCB static uint8_t iso14_pcb_blocknum = 0; +// optional ATQA/SAK overrides for SimulateIso14443aInit (set via iso14a_set_atqa_sak_override) +static uint16_t s_atqa_override = 0; +static uint8_t s_sak_override = 0; + // // ISO14443 timing: // @@ -106,7 +108,7 @@ static uint16_t FpgaSendQueueDelay; // 8 ticks on average until the data is stored in to_arm. // + the delays in transferring data - which is the same for // sniffing reader and tag data and therefore not relevant -#define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8) +// Delay defined in iso14443a.h as DELAY_READER_AIR2ARM_AS_SNIFFER //variables used for timing purposes: //these are in ssp_clk cycles: @@ -1233,8 +1235,22 @@ static void Simulate_read_ulaes_key0(uint8_t *ulaes_key0) { reverse_array(ulaes_key0 + 12, 4); } +void iso14a_set_atqa_sak_override(uint16_t atqa, uint8_t sak) { + s_atqa_override = atqa; + s_sak_override = sak; +} + +uint8_t iso14a_get_pcb_blocknum(void) { + return iso14_pcb_blocknum; +} + +void iso14a_toggle_pcb_blocknum(void) { + iso14_pcb_blocknum ^= 1; +} + bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, - uint8_t *ats, size_t ats_len, tag_response_info_t **responses, + uint8_t *ats, size_t ats_len, + tag_response_info_t **responses, uint32_t *cuid, uint8_t *pages, uint8_t *ulc_key) { uint8_t sak = 0; // The first response contains the ATQA (note: bytes are transmitted in reverse order). @@ -1472,6 +1488,11 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, } } + // Apply SAK override before it is encoded into rSAKc1/2/3. + if (flags & FLAG_SAK_IN_DATA) { + sak = s_sak_override; + } + // if uid not supplied then get from emulator memory if ((memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 10) == 0) || IS_FLAG_UID_IN_EMUL(flags)) { if (tagType == 2 || tagType == 7 || tagType == 13 || tagType == 14) { @@ -1565,6 +1586,12 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, return false; } + // Apply ATQA override after all UID-size bits have been set. + if (flags & FLAG_ATQA_IN_DATA) { + rATQA[0] = (uint8_t)(s_atqa_override >> 8); + rATQA[1] = (uint8_t)(s_atqa_override & 0xFF); + } + AddCrc14A(rATS, rATS_len - 2); AddCrc14A(rPPS, sizeof(rPPS) - 2); @@ -1702,9 +1729,9 @@ void SimulateIso14443aTagEx(uint8_t tagType, uint16_t flags, uint8_t *useruid, u .modulation_n = 0 }; - if (SimulateIso14443aInit(tagType, flags, useruid, ats, ats_len - , &responses, &cuid, &pages - , ulc_key) == false) { + if (SimulateIso14443aInit(tagType, flags, useruid, ats, ats_len, + &responses, &cuid, &pages, + ulc_key) == false) { BigBuf_free_keep_EM(); reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0); return; @@ -2417,8 +2444,8 @@ void SimulateIso14443aTagEx(uint8_t tagType, uint16_t flags, uint8_t *useruid, u } if (dynamic_response_info.response_n > 0) { - // Copy the CID from the reader query - if (tagType != 10) + // Copy the CID from the reader query (only when CID bit is set in PCB). + if (tagType != 10 && (receivedCmd[0] & 0x08)) dynamic_response_info.response[1] = receivedCmd[1]; // Add CRC bytes, always used in ISO 14443A-4 compliant cards diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index f00f686f8..e4ae956e4 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -154,8 +154,12 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid, uint8_t *selectaid_response, size_t selectaid_response_len, uint8_t *getdata_response, size_t getdata_response_len); +void iso14a_set_atqa_sak_override(uint16_t atqa, uint8_t sak); +uint8_t iso14a_get_pcb_blocknum(void); +void iso14a_toggle_pcb_blocknum(void); bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, - uint8_t *ats, size_t ats_len, tag_response_info_t **responses, + uint8_t *ats, size_t ats_len, + tag_response_info_t **responses, uint32_t *cuid, uint8_t *pages, uint8_t *ulc_key); @@ -202,4 +206,19 @@ bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint16_t rec_ extern iso14a_polling_parameters_t WUPA_POLLING_PARAMETERS; extern iso14a_polling_parameters_t REQA_POLLING_PARAMETERS; +// Sniffer timing delays (carrier clock cycles), for use by external sniff loops. +#define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8) + +// When the PM acts as sniffer and is receiving reader data, it takes +// 2 ticks delay in analogue RF receiver (for the falling edge of the +// start bit, which marks the start of the communication) +// 3 ticks A/D conversion +// 8 ticks on average until the data is stored in to_arm. +// + the delays in transferring data - which is the same for +// sniffing reader and tag data and therefore not relevant +#define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8) + +// Maximum ISO 14443A protocol timeout in field cycles (1/13.56 MHz). +#define MAX_ISO14A_TIMEOUT 524288 // this timeout is in MS + #endif /* __ISO14443A_H */ diff --git a/armsrc/secc.c b/armsrc/secc.c index 04e5fbae7..c65e4bf34 100644 --- a/armsrc/secc.c +++ b/armsrc/secc.c @@ -28,7 +28,7 @@ #include "fpgaloader.h" // FpgaWriteConfWord, FpgaSetupSscDma #include "desfire_crypto.h" // tdes_nxp_send #include "mbedtls/des.h" // mbedtls_des_*, mbedtls_des3_* -#include "iso14443a.h" // ReaderTransmit, ReaderReceive, iso14a_get/set_timeout, iso14_pcb_blocknum, MAX_ISO14A_TIMEOUT +#include "iso14443a.h" // ReaderTransmit, ReaderReceive, iso14a_get/set_timeout, iso14a_get/toggle_pcb_blocknum, MAX_ISO14A_TIMEOUT #include "appmain.h" // tearoff_hook, send_wtx #include "util.h" // data_available, BUTTON_PRESS #include "cmd.h" // reply_ng @@ -251,12 +251,12 @@ int hid_config_card_iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chainin real_cmd[0] = 0x0A; // I-block, CID present (bit 3), block number in bit 0 if (send_chaining) real_cmd[0] |= 0x10; - real_cmd[0] |= iso14_pcb_blocknum; + real_cmd[0] |= iso14a_get_pcb_blocknum(); real_cmd[1] = 0x00; // CID = 0 (as negotiated in RATS) memcpy(real_cmd + 2, cmd, cmd_len); } else { real_cmd[0] = 0xAA; // R-block ACK + CID present - real_cmd[0] |= iso14_pcb_blocknum; + real_cmd[0] |= iso14a_get_pcb_blocknum(); real_cmd[1] = 0x00; // CID = 0 } AddCrc14A(real_cmd, cmd_len + 2); // PCB + CID + APDU @@ -297,8 +297,8 @@ int hid_config_card_iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chainin // Toggle block number on valid I-block or R(ACK) if (len >= 3 && ((data_bytes[0] & 0xC0) == 0 || (data_bytes[0] & 0xD0) == 0x80) - && (data_bytes[0] & 0x01) == iso14_pcb_blocknum) { - iso14_pcb_blocknum ^= 1; + && (data_bytes[0] & 0x01) == iso14a_get_pcb_blocknum()) { + iso14a_toggle_pcb_blocknum(); } if (res) @@ -355,9 +355,8 @@ void SimulateHIDConfigCard(const hid_sim_payload_t *payload) { uint8_t uid[10]; memcpy(uid, payload->uid, sizeof(uid)); - // ATQA override: stored big-endian in payload, SimulateIso14443aInit takes uint16 uint16_t atqa_val = ((uint16_t)payload->atqa[0] << 8) | payload->atqa[1]; - uint8_t sak_val = payload->sak; + iso14a_set_atqa_sak_override(atqa_val, payload->sak); tag_response_info_t *responses; uint32_t cuid; @@ -365,7 +364,6 @@ void SimulateHIDConfigCard(const hid_sim_payload_t *payload) { if (SimulateIso14443aInit(4, flags, uid, (uint8_t *)payload->ats, payload->ats_len, - atqa_val, sak_val, &responses, &cuid, &pages, NULL) == false) { BigBuf_free_keep_EM(); reply_ng(CMD_HF_HIDCONFIG_SIM, PM3_EINIT, NULL, 0); diff --git a/client/resources/hidconfig_sample.json b/client/resources/hidconfig_sample.json index f990a1f12..7d0a526cd 100644 --- a/client/resources/hidconfig_sample.json +++ b/client/resources/hidconfig_sample.json @@ -1,5 +1,5 @@ { - "UID": "8F042795", + "UID": "00000000", "AID": "A0000003820013000101", "SCP02Key": "404142434445464748494A4B4C4D4E4F", "ATS": "1478F7B10280590180415254454346477300011B", diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index ad37bdf59..a48e7b419 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -32,6 +32,7 @@ #include "cmdhfemrtd.h" // eMRTD #include "cmdhffelica.h" // ISO18092 / FeliCa #include "cmdhffido.h" // FIDO authenticators +#include "cmdhfsecc.h" // HID Config Card #include "cmdhffudan.h" // Fudan cards #include "cmdhfgallagher.h" // Gallagher DESFire cards #include "cmdhfgst.h" // Google Smart Tap @@ -588,6 +589,7 @@ static command_t CommandTable[] = { {"fudan", CmdHFFudan, AlwaysAvailable, "{ Fudan RFIDs... }"}, {"gallagher", CmdHFGallagher, AlwaysAvailable, "{ Gallagher DESFire RFIDs... }"}, {"gst", CmdHFGST, AlwaysAvailable, "{ Google Smart Tap passes... }"}, + {"secc", CmdHFHIDConfig, AlwaysAvailable, "{ iClass SE Config Card Emulator... }"}, {"iclass", CmdHFiClass, AlwaysAvailable, "{ ICLASS RFIDs... }"}, {"ict", CmdHFICT, AlwaysAvailable, "{ ICT MFC/DESfire RFIDs... }"}, {"jooki", CmdHF_Jooki, AlwaysAvailable, "{ Jooki RFIDs... }"}, From 7b3c60bbea4e351124c35d621bdf9e5084e14f62 Mon Sep 17 00:00:00 2001 From: Antiklesys Date: Mon, 30 Mar 2026 23:52:20 +0800 Subject: [PATCH 2/8] Update iso14443a.h --- armsrc/iso14443a.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index e4ae956e4..b1e01c5e8 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -219,6 +219,7 @@ extern iso14a_polling_parameters_t REQA_POLLING_PARAMETERS; #define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8) // Maximum ISO 14443A protocol timeout in field cycles (1/13.56 MHz). -#define MAX_ISO14A_TIMEOUT 524288 // this timeout is in MS +#define MAX_ISO14A_TIMEOUT 524288 +// this timeout is in MS #endif /* __ISO14443A_H */ From cce48aa6e916de75b78ee094fc044afddd853c0d Mon Sep 17 00:00:00 2001 From: Antiklesys Date: Mon, 30 Mar 2026 23:52:56 +0800 Subject: [PATCH 3/8] Update cmdhf.c --- client/src/cmdhf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index a48e7b419..0b5e71465 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -32,7 +32,7 @@ #include "cmdhfemrtd.h" // eMRTD #include "cmdhffelica.h" // ISO18092 / FeliCa #include "cmdhffido.h" // FIDO authenticators -#include "cmdhfsecc.h" // HID Config Card +#include "cmdhfsecc.h" // iClass SE Config Card #include "cmdhffudan.h" // Fudan cards #include "cmdhfgallagher.h" // Gallagher DESFire cards #include "cmdhfgst.h" // Google Smart Tap From abc0b2ee2a24403ac073c74a609636d72987e628 Mon Sep 17 00:00:00 2001 From: Antiklesys Date: Tue, 31 Mar 2026 00:08:32 +0800 Subject: [PATCH 4/8] Update iso14443a.c --- armsrc/iso14443a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 9430224b2..ee8a1c158 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1489,8 +1489,8 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, } // Apply SAK override before it is encoded into rSAKc1/2/3. - if (flags & FLAG_SAK_IN_DATA) { - sak = s_sak_override; + if ( (flags & FLAG_SAK_IN_DATA) == FLAG_SAK_IN_DATA) { + sak = sak_override; } // if uid not supplied then get from emulator memory From f37e04a58f7d339a5b2279a8fba7236e0f6a0c09 Mon Sep 17 00:00:00 2001 From: Antiklesys Date: Tue, 31 Mar 2026 00:58:24 +0800 Subject: [PATCH 5/8] Fixed typo Signed-off-by: Antiklesys --- armsrc/iso14443a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index ee8a1c158..c65216a6e 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1490,7 +1490,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, // Apply SAK override before it is encoded into rSAKc1/2/3. if ( (flags & FLAG_SAK_IN_DATA) == FLAG_SAK_IN_DATA) { - sak = sak_override; + sak = s_sak_override; } // if uid not supplied then get from emulator memory From c01f3cdbc6e2b8ffc6558441a0f4784d73b36861 Mon Sep 17 00:00:00 2001 From: Antiklesys Date: Tue, 31 Mar 2026 00:58:40 +0800 Subject: [PATCH 6/8] Update iso14443a.c --- armsrc/iso14443a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index ee8a1c158..c65216a6e 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1490,7 +1490,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, // Apply SAK override before it is encoded into rSAKc1/2/3. if ( (flags & FLAG_SAK_IN_DATA) == FLAG_SAK_IN_DATA) { - sak = sak_override; + sak = s_sak_override; } // if uid not supplied then get from emulator memory From fd5a058674f9dd05698aa9cb0b26aef9d7bb1950 Mon Sep 17 00:00:00 2001 From: Antiklesys Date: Tue, 31 Mar 2026 03:04:39 +0800 Subject: [PATCH 7/8] Fixed menu spacing Signed-off-by: Antiklesys --- client/src/cmdhf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index 0b5e71465..3569126a1 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -589,7 +589,7 @@ static command_t CommandTable[] = { {"fudan", CmdHFFudan, AlwaysAvailable, "{ Fudan RFIDs... }"}, {"gallagher", CmdHFGallagher, AlwaysAvailable, "{ Gallagher DESFire RFIDs... }"}, {"gst", CmdHFGST, AlwaysAvailable, "{ Google Smart Tap passes... }"}, - {"secc", CmdHFHIDConfig, AlwaysAvailable, "{ iClass SE Config Card Emulator... }"}, + {"secc", CmdHFHIDConfig, AlwaysAvailable, "{ iClass SE Config Card Emulator... }"}, {"iclass", CmdHFiClass, AlwaysAvailable, "{ ICLASS RFIDs... }"}, {"ict", CmdHFICT, AlwaysAvailable, "{ ICT MFC/DESfire RFIDs... }"}, {"jooki", CmdHF_Jooki, AlwaysAvailable, "{ Jooki RFIDs... }"}, From 59ae6fa4585aa6f2ead354dbc87d082b766ec6ff Mon Sep 17 00:00:00 2001 From: Antiklesys Date: Tue, 31 Mar 2026 09:38:53 +0800 Subject: [PATCH 8/8] Fix ATQA flag check for correct condition Signed-off-by: Antiklesys --- armsrc/iso14443a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index c65216a6e..7fd193f2e 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1587,7 +1587,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, } // Apply ATQA override after all UID-size bits have been set. - if (flags & FLAG_ATQA_IN_DATA) { + if ((flags & FLAG_ATQA_IN_DATA) == FLAG_ATQA_IN_DATA) { rATQA[0] = (uint8_t)(s_atqa_override >> 8); rATQA[1] = (uint8_t)(s_atqa_override & 0xFF); }