or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

atr-card-types.mdcard-connections.mdgui-components.mdindex.mdmonitoring.mdpcsc-interface.mdreader-management.mdsession-api.mdstatus-word-handling.mdutilities.md

atr-card-types.mddocs/

0

# ATR and Card Types

1

2

Tools for parsing Answer To Reset (ATR) sequences, extracting card parameters, and implementing card type detection logic. The ATR contains essential information about the card's capabilities and communication parameters.

3

4

## Capabilities

5

6

### ATR Processing

7

8

The ATR class provides comprehensive parsing and analysis of Answer To Reset sequences according to ISO/IEC 7816-3 standards.

9

10

```python { .api }

11

class ATR:

12

def __init__(self, atr):

13

"""

14

Parse an Answer To Reset sequence.

15

16

Args:

17

atr (list[int]): ATR bytes as list of integers

18

19

Raises:

20

InvalidATRException: If ATR format is invalid

21

"""

22

23

# ATR Structure Properties

24

@property

25

def TS(self):

26

"""int: Initial character indicating bit order and voltage class."""

27

28

@property

29

def T0(self):

30

"""int: Format character encoding interface characters presence and historical bytes count."""

31

32

@property

33

def K(self):

34

"""int: Number of historical bytes."""

35

36

@property

37

def TA(self):

38

"""list[int]: Interface characters TA1, TA2, ..."""

39

40

@property

41

def TB(self):

42

"""list[int]: Interface characters TB1, TB2, ..."""

43

44

@property

45

def TC(self):

46

"""list[int]: Interface characters TC1, TC2, ..."""

47

48

@property

49

def TD(self):

50

"""list[int]: Interface characters TD1, TD2, ..."""

51

52

@property

53

def Y(self):

54

"""list[int]: Interface character presence indicators."""

55

56

@property

57

def historicalBytes(self):

58

"""list[int]: Historical bytes containing card-specific information."""

59

60

@property

61

def TCK(self):

62

"""int: Check character for ATR integrity verification."""

63

64

# Protocol Detection

65

def getSupportedProtocols(self):

66

"""

67

Get dictionary of communication protocols supported by the card.

68

69

Returns:

70

dict[str, bool]: Dictionary with protocol names as keys (e.g., "T=0", "T=1")

71

and True as values for supported protocols

72

"""

73

74

def isT0Supported(self):

75

"""

76

Check if T=0 protocol is supported.

77

78

Returns:

79

bool: True if T=0 is supported

80

"""

81

82

def isT1Supported(self):

83

"""

84

Check if T=1 protocol is supported.

85

86

Returns:

87

bool: True if T=1 is supported

88

"""

89

90

def isT15Supported(self):

91

"""

92

Check if T=15 protocol is supported.

93

94

Returns:

95

bool: True if T=15 is supported

96

"""

97

98

# ATR Data Access

99

def getChecksum(self):

100

"""

101

Get the ATR checksum (TCK).

102

103

Returns:

104

int: Checksum byte, or None if not present

105

"""

106

107

def getHistoricalBytes(self):

108

"""

109

Get the historical bytes.

110

111

Returns:

112

list[int]: Historical bytes

113

"""

114

115

def getHistoricalBytesCount(self):

116

"""

117

Get the number of historical bytes.

118

119

Returns:

120

int: Count of historical bytes

121

"""

122

123

# Communication Parameters

124

def getBitRateFactor(self):

125

"""

126

Get the bit rate adjustment factor from TA1.

127

128

Returns:

129

int: Bit rate factor (1-16)

130

"""

131

132

def getClockRateConversion(self):

133

"""

134

Get the clock rate conversion factor from TA1.

135

136

Returns:

137

int: Clock rate conversion factor

138

"""

139

140

def getProgrammingCurrent(self):

141

"""

142

Get the maximum programming current from TB1.

143

144

Returns:

145

int: Programming current in mA, or None if not specified

146

"""

147

148

def getProgrammingVoltage(self):

149

"""

150

Get the programming voltage from TB1.

151

152

Returns:

153

int: Programming voltage class, or None if not specified

154

"""

155

156

def getGuardTime(self):

157

"""

158

Get the guard time from TC1.

159

160

Returns:

161

int: Guard time in ETUs (Elementary Time Units)

162

"""

163

164

# Display and Formatting

165

def render(self):

166

"""

167

Render ATR in human-readable format with detailed breakdown.

168

169

Returns:

170

str: Formatted ATR analysis

171

"""

172

173

def __str__(self):

174

"""

175

String representation of ATR.

176

177

Returns:

178

str: ATR as space-separated hex bytes

179

"""

180

181

def dump(self):

182

"""

183

Deprecated: Use render() instead.

184

185

Returns:

186

str: ATR dump (deprecated)

187

"""

188

189

# Class Constants for Parameter Lookup

190

clockrateconversion = {

191

# Clock rate conversion factors indexed by TA1 high nibble

192

0x0: 372, 0x1: 372, 0x2: 558, 0x3: 744, 0x4: 1116, 0x5: 1488,

193

0x6: 1860, 0x7: 2232, 0x8: 2604, 0x9: 372, 0xA: 512, 0xB: 768,

194

0xC: 1024, 0xD: 1536, 0xE: 2048, 0xF: 2048

195

}

196

197

bitratefactor = {

198

# Bit rate adjustment factors indexed by TA1 low nibble

199

0x1: 1, 0x2: 2, 0x3: 4, 0x4: 8, 0x5: 16, 0x6: 32,

200

0x8: 12, 0x9: 20

201

}

202

203

currenttable = {

204

# Programming current values in mA indexed by TB1 low nibble

205

0x0: 25, 0x1: 50, 0x2: 100, 0x3: 200, 0x4: 400, 0x5: 800

206

}

207

```

208

209

### Card Type Detection

210

211

Card type classes provide flexible mechanisms for matching cards based on ATR patterns, enabling applications to identify specific card types.

212

213

```python { .api }

214

class CardType:

215

"""Abstract base class for card type matching."""

216

217

def matches(self, atr, reader=None):

218

"""

219

Check if the given ATR matches this card type.

220

221

Args:

222

atr (list[int]): ATR bytes to check

223

reader (Reader, optional): Reader containing the card

224

225

Returns:

226

bool: True if ATR matches this card type

227

"""

228

229

class AnyCardType(CardType):

230

"""Card type that matches any card."""

231

232

def matches(self, atr, reader=None):

233

"""

234

Always returns True - matches any card type.

235

236

Args:

237

atr (list[int]): ATR bytes (ignored)

238

reader (Reader, optional): Reader (ignored)

239

240

Returns:

241

bool: Always True

242

"""

243

244

class ATRCardType(CardType):

245

"""Card type that matches specific ATR patterns with optional masking."""

246

247

def __init__(self, atr, mask=None):

248

"""

249

Create ATR-based card type matcher.

250

251

Args:

252

atr (list[int]): ATR pattern to match

253

mask (list[int], optional): Mask for ATR comparison.

254

If provided, must be same length as atr.

255

0x00 bytes in mask are ignored during comparison.

256

0xFF bytes in mask must match exactly.

257

258

Raises:

259

InvalidATRMaskLengthException: If mask length doesn't match ATR length

260

"""

261

262

def matches(self, atr, reader=None):

263

"""

264

Check if ATR matches the pattern with optional masking.

265

266

Args:

267

atr (list[int]): ATR bytes to check

268

reader (Reader, optional): Reader containing the card

269

270

Returns:

271

bool: True if ATR matches pattern (considering mask if provided)

272

"""

273

```

274

275

## Usage Examples

276

277

### Basic ATR Analysis

278

279

```python

280

from smartcard import ATR

281

from smartcard.util import toHexString

282

283

# Example ATR from a contact smart card

284

atr_bytes = [0x3B, 0x7F, 0x96, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xB0, 0x84, 0x41, 0x82, 0x54, 0x43, 0x4F, 0x53, 0x70, 0x02, 0x47, 0x00, 0x44, 0x32, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

285

286

# Parse the ATR

287

atr = ATR(atr_bytes)

288

289

print(f"ATR: {atr}")

290

print(f"ATR hex: {toHexString(atr_bytes)}")

291

print()

292

293

# Analyze structure

294

print("ATR Structure:")

295

print(f" TS (Initial Character): 0x{atr.TS:02X}")

296

print(f" T0 (Format Character): 0x{atr.T0:02X}")

297

print(f" Historical Bytes Count: {atr.K}")

298

print(f" Historical Bytes: {toHexString(atr.historicalBytes)}")

299

print()

300

301

# Check protocol support

302

print("Protocol Support:")

303

print(f" T=0 supported: {atr.isT0Supported()}")

304

print(f" T=1 supported: {atr.isT1Supported()}")

305

print(f" T=15 supported: {atr.isT15Supported()}")

306

supported_protocols = atr.getSupportedProtocols()

307

print(f" All supported protocols: {list(supported_protocols.keys())}")

308

print()

309

310

# Get communication parameters

311

print("Communication Parameters:")

312

if atr.TA:

313

print(f" Clock rate conversion: {atr.getClockRateConversion()}")

314

print(f" Bit rate factor: {atr.getBitRateFactor()}")

315

if atr.TB:

316

current = atr.getProgrammingCurrent()

317

voltage = atr.getProgrammingVoltage()

318

if current: print(f" Programming current: {current} mA")

319

if voltage: print(f" Programming voltage class: {voltage}")

320

if atr.TC:

321

print(f" Guard time: {atr.getGuardTime()} ETU")

322

```

323

324

### ATR Detailed Analysis

325

326

```python

327

from smartcard import ATR

328

329

def analyze_atr(atr_bytes):

330

"""Perform comprehensive ATR analysis."""

331

atr = ATR(atr_bytes)

332

333

print("=== ATR Analysis ===")

334

print(atr.render()) # Detailed human-readable breakdown

335

print()

336

337

# Interface character analysis

338

print("Interface Characters:")

339

for i, ta in enumerate(atr.TA, 1):

340

print(f" TA{i}: 0x{ta:02X}")

341

for i, tb in enumerate(atr.TB, 1):

342

print(f" TB{i}: 0x{tb:02X}")

343

for i, tc in enumerate(atr.TC, 1):

344

print(f" TC{i}: 0x{tc:02X}")

345

for i, td in enumerate(atr.TD, 1):

346

print(f" TD{i}: 0x{td:02X}")

347

348

return atr

349

350

# Example usage

351

sample_atr = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03]

352

analyze_atr(sample_atr)

353

```

354

355

### Card Type Matching

356

357

```python

358

from smartcard.CardType import ATRCardType, AnyCardType

359

from smartcard.CardRequest import CardRequest

360

361

# Match any card type

362

any_card = AnyCardType()

363

print(f"Any card matches sample ATR: {any_card.matches([0x3B, 0x65])}")

364

365

# Match specific ATR exactly

366

exact_atr = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03]

367

exact_card_type = ATRCardType(exact_atr)

368

369

test_atr1 = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03] # Exact match

370

test_atr2 = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x04] # Different

371

372

print(f"Exact match: {exact_card_type.matches(test_atr1)}") # True

373

print(f"Different ATR: {exact_card_type.matches(test_atr2)}") # False

374

375

# Match with mask (ignore certain bytes)

376

atr_pattern = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03]

377

atr_mask = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00] # Ignore last byte

378

379

masked_card_type = ATRCardType(atr_pattern, atr_mask)

380

381

test_atr3 = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0xFF] # Last byte different but masked

382

383

print(f"Masked match: {masked_card_type.matches(test_atr3)}") # True

384

```

385

386

### Card Type in Card Request

387

388

```python

389

from smartcard.CardType import ATRCardType

390

from smartcard.CardRequest import CardRequest

391

from smartcard import ATR

392

393

# Define card type for specific smart card series

394

mifare_atr_pattern = [0x3B, 0x8F, 0x80, 0x01, 0x80, 0x4F, 0x0C, 0xA0, 0x00, 0x00, 0x03, 0x06, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x6A]

395

mifare_card_type = ATRCardType(mifare_atr_pattern)

396

397

# Wait specifically for this card type

398

card_request = CardRequest(timeout=30, cardType=mifare_card_type)

399

400

try:

401

print("Waiting for MIFARE card...")

402

card_service = card_request.waitforcard()

403

404

print("MIFARE card detected!")

405

connection = card_service.connection

406

407

# Analyze the ATR

408

atr_bytes = connection.getATR()

409

atr = ATR(atr_bytes)

410

411

print(f"Card ATR: {atr}")

412

print(f"Protocols: {list(atr.getSupportedProtocols().keys())}")

413

print(f"Historical bytes: {atr.getHistoricalBytes()}")

414

415

except Exception as e:

416

print(f"Card request failed: {e}")

417

```

418

419

### Custom Card Type Implementation

420

421

```python

422

from smartcard.CardType import CardType

423

from smartcard import ATR

424

425

class JavaCardType(CardType):

426

"""Custom card type for detecting Java Cards based on historical bytes."""

427

428

def matches(self, atr_bytes, reader=None):

429

try:

430

atr = ATR(atr_bytes)

431

historical = atr.getHistoricalBytes()

432

433

# Check for Java Card indicators in historical bytes

434

# This is a simplified example - real detection would be more complex

435

if len(historical) >= 4:

436

# Look for Java Card identifier

437

if historical[0:3] == [0x4A, 0x43, 0x4F]: # "JCO" in ASCII

438

return True

439

440

# Look for other Java Card patterns

441

if 0x72 in historical: # Common in Java Card ATRs

442

return True

443

444

return False

445

except:

446

return False

447

448

# Use custom card type

449

java_card_type = JavaCardType()

450

card_request = CardRequest(timeout=20, cardType=java_card_type)

451

452

try:

453

print("Waiting for Java Card...")

454

card_service = card_request.waitforcard()

455

print("Java Card detected!")

456

457

except Exception as e:

458

print(f"No Java Card found: {e}")

459

```

460

461

## Related Types

462

463

```python { .api }

464

# Exception types for ATR processing

465

class InvalidATRException(SmartcardException):

466

"""Raised when ATR format is invalid."""

467

468

class InvalidATRMaskLengthException(SmartcardException):

469

"""Raised when ATR mask length doesn't match ATR length."""

470

471

# Type aliases for clarity

472

ATRBytes = list[int]

473

ATRMask = list[int]

474

ProtocolDict = dict[str, bool]

475

HistoricalBytes = list[int]

476

477

# ATR parameter constants (from ATR class)

478

ClockRateConversion = dict[int, int]

479

BitRateFactor = dict[int, int]

480

CurrentTable = dict[int, int]

481

```