Files
proxmark3/include/iclass_cmd.h
T
Antiklesys 0ffe244a6b Fix for circular buffer error during hf iclass sim
Issue origin:
Commit 6b7665ed5 "Added live fc/cn update to hf iclass tagsim" added a data_available() poll inside the per-byte DMA loop of GetIso15693CommandFromReader so the ARM could drop out of RF-listen and process live emulator updates.

Before that commit, that tight loop had no USB poll at all — only gotFrame / BUTTON_PRESS / WDT_HIT. Verified via git show 6b7665ed5^:armsrc/iso15693.c.

Why it shows up on sim -t 3/6/7: those are the FULL sim modes that share do_iclass_simulation. Between reader commands the decoder sits in STATE_READER_UNSYNCD, so the gated poll at iso15693.c:1570-1575 fires every byte (reading UDP peripheral registers). With DMA filling at ~1 byte / ~19 µs, the added USB register reads plus jitter occasionally push the CPU past the 90% lag threshold → behindBy 461 with DMA_BUFFER_SIZE=512.

Commit fb8f94fa2 narrowed the gate to UNSYNCD to stop mid-frame exits, but the per-byte poll itself is still what's new on that path.

Fix:

New mode constant in include/iclass_cmd.h:

#define ICLASS_SIM_MODE_FULL_LIVE  8  // FULL + allow USB interrupt for live emul updates
Treat it identically to ICLASS_SIM_MODE_FULL everywhere except for the poll gate.

Add a flag param to GetIso15693CommandFromReader — e.g. bool allow_usb_interrupt in iso15693.c:1495 and iso15693.h:42. Wrap the poll:

if (allow_usb_interrupt &&
    (dr->state == STATE_READER_UNSYNCD ||
     dr->state == STATE_READER_AWAIT_1ST_FALLING_EDGE_OF_SOF) &&
     data_available()) { ... }
Pass true only for live mode in do_iclass_simulation iclass.c:502:

bool live = (simulationMode == ICLASS_SIM_MODE_FULL_LIVE);
len = GetIso15693CommandFromReader(receivedCmd, MAX_FRAME_SIZE, &reader_eof_time, live);
The len == -2 drain block stays but becomes dead code for non-live modes (never returns -2).

Client side: cmdhficlass.c:1687 (CmdHFiClassTagSim) sends ICLASS_SIM_MODE_FULL_LIVE. CmdHFiClassSim -t 3/6/7 keeps sending ICLASS_SIM_MODE_FULL / _GLITCH / _GLITCH_KEY.

Other callers (iso15693.c:2270, iclass.c:1121 = reader-attack sim) pass false.

Result:

hf iclass sim -t 3/6/7 → byte-inner loop is back to its pre-tagsim shape → no blow-buffer abort.
hf iclass tagsim → keeps live update ability; still has the overhead, but that's the trade-off the feature needs.
2026-04-17 03:00:14 +08:00

213 lines
5.7 KiB
C

//-----------------------------------------------------------------------------
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// iCLASS type prototyping
//-----------------------------------------------------------------------------
#ifndef _ICLASS_CMD_H_
#define _ICLASS_CMD_H_
#include "common.h"
//-----------------------------------------------------------------------------
// iCLASS / PICOPASS
//-----------------------------------------------------------------------------
#define PICOPASS_KEY_SIZE ( 8 )
#define PICOPASS_BLOCK_SIZE ( 8 )
#define PICOPASS_MAX_BYTES ( 4096 ) // # 32k bits = 4096 bytes
// iCLASS reader flags
#define FLAG_ICLASS_READER_INIT 0x01
#define FLAG_ICLASS_READER_CLEARTRACE 0x02
//#define FLAG_ICLASS_READER_ONLY_ONCE 0x04
#define FLAG_ICLASS_READER_CREDITKEY 0x08
#define FLAG_ICLASS_READER_AIA 0x10
#define FLAG_ICLASS_READER_SHALLOW_MOD 0x20
// iCLASS reader status flags
#define FLAG_ICLASS_NULL 0x00
#define FLAG_ICLASS_CSN 0x01
#define FLAG_ICLASS_CC 0x02
#define FLAG_ICLASS_CONF 0x04
#define FLAG_ICLASS_AIA 0x08
// iCLASS simulation modes
#define ICLASS_SIM_MODE_CSN 0
#define ICLASS_SIM_MODE_CSN_DEFAULT 1
#define ICLASS_SIM_MODE_READER_ATTACK 2
#define ICLASS_SIM_MODE_FULL 3
#define ICLASS_SIM_MODE_READER_ATTACK_KEYROLL 4
#define ICLASS_SIM_MODE_EXIT_AFTER_MAC 5 // note: device internal only
#define ICLASS_SIM_MODE_FULL_GLITCH 6
#define ICLASS_SIM_MODE_FULL_GLITCH_KEY 7
#define ICLASS_SIM_MODE_FULL_LIVE 8 // FULL + USB poll for live emul updates (hf iclass tagsim)
// iCLASS auth request data structure
// used with read block, dump, write block
typedef struct {
uint8_t key[8];
bool use_raw;
bool use_elite;
bool use_credit_key;
bool use_replay;
bool send_reply;
bool do_auth;
bool shallow_mod;
uint8_t blockno;
} PACKED iclass_auth_req_t;
// iCLASS read block response data structure
typedef struct {
bool isOK;
uint8_t div_key[8];
uint8_t mac[4];
uint8_t data[8];
} PACKED iclass_readblock_resp_t;
// iCLASS dump data structure
typedef struct {
iclass_auth_req_t req;
uint8_t page;
uint8_t start_block;
uint8_t end_block;
} PACKED iclass_dump_req_t;
// iCLASS write block request data structure
typedef struct {
iclass_auth_req_t req;
uint8_t data[8];
uint8_t mac[4];
} PACKED iclass_writeblock_req_t;
// iCLASS tearoff block request data structure
typedef struct {
iclass_auth_req_t req;
uint8_t data[8];
uint8_t mac[4];
int tear_start;
int tear_end;
int increment;
int tear_loop;
} PACKED iclass_tearblock_req_t;
// iCLASS write block request data structure
typedef struct {
iclass_auth_req_t req;
uint8_t epurse[4];
} PACKED iclass_credit_epurse_t;
// iCLASS dump data structure
typedef struct {
uint8_t blockno;
uint8_t data[8];
} PACKED iclass_restore_item_t;
typedef struct {
iclass_auth_req_t req;
uint8_t item_cnt;
iclass_restore_item_t blocks[];
} PACKED iclass_restore_req_t;
typedef struct {
iclass_auth_req_t req;
uint32_t index;
uint32_t loop;
uint8_t nfa[8];
bool debug;
bool test;
bool fast;
bool short_delay;
} PACKED iclass_recover_req_t;
typedef struct iclass_premac {
uint8_t mac[4];
} PACKED iclass_premac_t;
typedef struct {
bool use_credit_key;
bool shallow_mod;
uint8_t count;
iclass_premac_t items[];
} PACKED iclass_chk_t;
typedef struct iclass_block {
uint8_t d[8];
} iclass_block_t;
typedef struct iclass_prekey {
uint8_t mac[4];
uint8_t key[8];
} iclass_prekey_t;
typedef struct {
char desc[70];
uint8_t data[16];
} iclass_config_card_item_t;
// iclass / picopass chip config structures and shared routines
typedef struct {
uint8_t app_limit; //[8]
uint8_t otp[2]; //[9-10]
uint8_t block_writelock;//[11]
uint8_t chip_config; //[12]
uint8_t mem_config; //[13]
uint8_t eas; //[14]
uint8_t fuses; //[15]
} PACKED picopass_conf_block_t;
// iCLASS secure mode memory mapping
typedef struct {
uint8_t csn[PICOPASS_BLOCK_SIZE];
picopass_conf_block_t conf;
uint8_t epurse[PICOPASS_BLOCK_SIZE];
uint8_t key_d[PICOPASS_BLOCK_SIZE];
uint8_t key_c[PICOPASS_BLOCK_SIZE];
uint8_t app_issuer_area[PICOPASS_BLOCK_SIZE];
} PACKED picopass_hdr_t;
// iCLASS non-secure mode memory mapping
typedef struct {
uint8_t csn[8];
picopass_conf_block_t conf;
uint8_t app_issuer_area[8];
} PACKED picopass_ns_hdr_t;
// reader flags
typedef struct {
uint8_t flags;
uint8_t page;
} PACKED iclass_card_select_t;
// reader flags
typedef struct {
uint8_t status;
union {
picopass_hdr_t hdr;
picopass_ns_hdr_t ns_hdr;
} header;
} PACKED iclass_card_select_resp_t;
typedef struct {
union {
picopass_hdr_t hdr;
picopass_ns_hdr_t ns_hdr;
} header;
uint8_t data[PICOPASS_MAX_BYTES];
} PACKED iclass_tag_t;
#endif // _ICLASS_H_