How to Navigate a Smart Card File System — SELECT, READ BINARY, READ RECORD
Every smart card stores data in a hierarchical file system defined by ISO 7816-4. Whether you're reading EMV payment records, extracting a SIM phonebook, or debugging a PIV card, the navigation pattern is the same: SELECT a file, then READ it. This guide covers the full file system model with real APDU traces you can use immediately.
1. The ISO 7816-4 File Model: MF, DF, EF
The file system is a tree with three node types:
| Type | Full Name | Role | Max per Card |
|---|---|---|---|
| MF | Master File | Root directory. Every card has exactly one MF, selected at reset on some cards (FID = 3F 00) | 1 |
| DF | Dedicated File | Directory / application container. Holds EFs and child DFs. Can be selected by FID or AID | Unlimited (card memory permitting) |
| EF | Elementary File | Leaf node containing actual data. Cannot contain other files. Must be under MF or a DF | Unlimited |
The typical structure looks like this:
MF (3F 00) ← Root
├── EF.DIR (2F 00) ← Application directory (list of AIDs)
├── DF.CardManager ← GlobalPlatform card manager (security domain)
├── DF.PIV (A0 00 00 03 08) ← PIV application
│ ├── EF.CardHolderUUID
│ ├── EF.Certificate
│ └── EF.KeyHistory
├── DF.EMV (A0 00 00 00 03 10) ← EMV payment application (1PAY.SYS.DDF01)
│ ├── EF.ICC (2F 01) ← ICC public key certificate
│ └── DF.Visa (A0 00 00 00 03 10 10) ← Visa AID
│ ├── EF.Record (SFI 01) ← Payment records (track 2 equivalent data)
│ └── EF.Log (SFI 02) ← Transaction log
└── DF.SIM (7F 20) ← GSM/UICC telecom
├── DF.GSM (7F 20)
│ └── EF.IMSI (6F 07)
└── EF.ICCID (2F E2)
2. File Types: How Data Is Stored
EFs come in four structural types. The type determines which READ command to use:
| Type | Structure | Read Command | Used For |
|---|---|---|---|
| Transparent | Raw byte sequence (binary blob) | READ BINARY | Certificates, keys, ATR historical bytes, serial numbers |
| Linear Fixed | Fixed-length records (record 1, 2, 3...) | READ RECORD | EMV payment records, phonebook entries, transaction logs |
| Linear Variable | Variable-length records | READ RECORD | Free-form text, logs with variable entries |
| Cyclic | Fixed-length ring buffer (newest overwrites oldest) | READ RECORD | ATR event log, transaction counters |
The file type is discovered by parsing the File Control Information (FCI) returned after SELECT — see section 5 below.
3. The SELECT Command — Finding Your File
SELECT (INS A4) navigates to any file in the tree. P1 controls the selection method:
| P1 | Value | Selection Method | Data Field |
|---|---|---|---|
00 | Select by FID | Direct file identifier (2 bytes) | FID (e.g. 3F 00 for MF) |
04 | Select by AID | Application identifier (5-16 bytes) | AID (e.g. A0 00 00 00 03 10 10 for Visa) |
08 | Select by path (from MF) | Absolute path from root | Sequence of FIDs |
09 | Select by path (from current DF) | Relative path from current position | Sequence of FIDs |
P2 is normally 00 (return FCI) or 0C (no FCI, faster). Always use 00 when exploring — the FCI tells you the file type, size, and access conditions.
Select the MF (Root)
>> 00 A4 00 00 02 3F 00 << 90 00 # MF selected, at root now
Select an EMV Application by AID
>> 00 A4 04 00 07 A0 00 00 00 03 10 10 # Select Visa AID << 6F 1F 84 07 A0 00 00 00 03 10 10 # FCI template: AID confirmed A5 14 88 01 01 5F 2D 02 7A 65 ... # SFI, language preference etc. 90 00 # Success
Select an EF by FID (After Selecting Parent DF)
>> 00 A4 00 00 02 2F 01 # Select EF.ICC (under EMV DF) << 6F 17 82 01 05 83 02 2F 01 # FCI: file descriptor + FID 86 03 15 00 FF # Security attribute 8A 01 01 # Life cycle status 90 00 # Success
4. READ BINARY — Extracting Data from Transparent Files
READ BINARY (INS B0) reads raw bytes from a transparent EF. P1-P2 form a 15-bit file offset (bit 8 of P1 is reserved, must be 0):
# P1 = high byte of offset (bit 8 = 0, so 0x00-0x7F valid) # P2 = low byte of offset (0x00-0xFF, full range) # Offset = (P1 & 0x7F) << 8 | P2 # Read 10 bytes from offset 0: >> 00 B0 00 00 0A << 47 75 61 6E 67 7A 68 6F 75 20 90 00 # "Guangzhou " + SW OK
The offset calculation trips people up:
# Requested offset: 256 (0x0100) # P1 = (256 >> 8) & 0x7F = 0x01 # P2 = 256 & 0xFF = 0x00 >> 00 B0 01 00 10 # Read 16 bytes from offset 256 (correct) # Requested offset: 32768 (0x8000) — exceeds 15-bit limit # Cards with files > 32KB use "odd INS" B1 for the high bit >> 00 B1 00 00 10 # READ BINARY with odd INS (high offset)
Read EMV Payment Record by SFI
EMV uses Short File Identifier (SFI) instead of FID for efficiency. SFI values are 1-30, encoded in P2 bits 3-7 with the first record flag in bit 0-2:
# SFI 01, read all records — use READ RECORD (see section 5) # For transparent files referenced by SFI: >> 00 B0 81 00 00 # SFI 01, offset 0, read all (Le=0)
READ BINARY with odd INS (B1) to access the upper half. This is rare — most smart card files are under 32KB.5. READ RECORD — Retrieving Structured Data
READ RECORD (INS B2) reads records from linear-fixed, linear-variable, or cyclic files. P1 = record number (1-based, or 00 for current). P2 controls the read mode:
| P2 | Mode | Description |
|---|---|---|
04 | P1 = record number | Read specific record by index |
05 | P1 = 0, read first | Read from first record |
06 | P1 = 0, read last | Read from last record |
02 | P1 = 0, read next | Read next record (sequential iteration) |
03 | P1 = 0, read previous | Read previous record |
Read EMV Application Data Records
# After selecting an EMV application, read payment records by SFI: # SFI 01 (Track 2 equivalent data), Record 01 >> 00 B2 01 1C 00 # P2 = (SFI << 3) | 4 = (1 << 3) | 4 = 0x1C << 70 3A 57 13 47 69 73 78 ... # Record template with Track 2 data 90 00 # SFI 02 (transaction log), read all records sequentially: >> 00 B2 01 2C 00 # Record 1 of SFI 02 << ... 90 00 >> 00 B2 02 2C 00 # Record 2 of SFI 02 << ... 90 00
Read SIM Phonebook (Linear Fixed)
# SIM phonebook is at 7F10/6F3A (ADN — Abbreviated Dialing Numbers) >> 00 A4 00 00 02 7F 10 # Select DF.TELECOM << 90 00 >> 00 A4 00 00 02 6F 3A # Select EF.ADN << ... 90 00 # FCI tells us record length (e.g. 0x1C = 28 bytes) >> 00 B2 01 04 1C # READ RECORD 1, length 28 << 4D 6F 6D 05 81 10 ... # Record data (name + number encoded) 90 00
6. Parsing File Control Information (FCI)
After every SELECT, the card returns an FCI template containing critical metadata about the selected file. The FCI is a BER-TLV structure under tag 6F:
| Tag | Name | What It Tells You |
|---|---|---|
81 | File Size | Total data size in bytes (for transparent files) |
82 | File Descriptor | Byte 1: file type + structure. See decode table below |
83 | File Identifier | The FID (2 bytes) — confirms you selected the right file |
84 | DF Name | The AID (5-16 bytes) — confirms application identity |
86 | Security Attributes | Access conditions for READ, UPDATE, etc. |
88 | SFI | Short File Identifier (1 byte) — used by EMV |
File Descriptor Byte Decode
# Byte format: | 7 6 5 4 3 | 2 1 0 | # | File type | Structure | # # File type (bits 3-7): # 0x0: EF (working) # 0x1: EF (internal — for card OS only) # 0x2: EF (proprietary) # 0x8: DF (directory) # # Structure (bits 0-2) — only meaningful for EF: # 0x0: No info given # 0x1: Transparent # 0x2: Linear fixed # 0x3: Linear variable # 0x4: Cyclic # Example: 82 01 01 → File descriptor byte = 0x01 # Bits 7-3 = 00000 → EF (working) # Bits 2-0 = 001 → Transparent # Example: 82 01 02 → File descriptor byte = 0x02 # Bits 7-3 = 00000 → EF (working) # Bits 2-0 = 010 → Linear fixed # Example: 82 01 38 → File descriptor byte = 0x38 # Bits 7-3 = 00111 → DF (directory) # So this is a DF, not an EF
7. Complete Navigation Workflow
Here's the standard pattern for exploring an unknown card:
# Step 1: Select MF (always safe to start here) >> 00 A4 00 00 02 3F 00 << ... 90 00 # Step 2: Read application directory (EF.DIR at FID 2F00) >> 00 A4 00 00 02 2F 00 << 6F 15 82 01 01 83 02 2F 00 # FCI: transparent EF, FID 2F00 81 02 02 00 # File size: 512 bytes (0x0200) 90 00 # Step 3: READ BINARY to get AID list >> 00 B0 00 00 00 # Read all (Le=0 = until end or SW) << 61 08 4F 06 A0 00 00 00 03 # AID #1 (EMV PSE) 10 00 90 00 # Step 4: Select each AID and explore >> 00 A4 04 00 06 A0 00 00 00 03 10 00 << ... 90 00 # FCI returned # Step 5: Inside the application, SELECT the file of interest >> 00 A4 00 00 02 2F 01 << ... 90 00 # FCI returned, now know file type + size # Step 6: READ BINARY or READ RECORD depending on file type >> 00 B0 00 00 00 # or READ RECORD for structured files << ... 90 00
8. Common Errors and Fixes
| Error | Meaning | Fix |
|---|---|---|
6A 82 | File not found — FID or AID doesn't exist under current DF | Select correct parent DF first, or verify FID/AID spelling |
69 82 | Security not satisfied — need PIN or authentication before reading this file | Verify PIN or establish secure channel first |
6A 86 | Wrong P1-P2 — invalid offset (bit 8 of P1 set), or invalid record number | Check P1-P2 encoding. For offset > 32767, use odd INS B1 |
67 00 | Wrong length — Le exceeds file size or record length | Check file size from FCI response (81 tag), reduce Le |
6B 00 | Wrong Le — requested length doesn't match expected | Use 00 for Le (read until end) and handle 61XX response |
69 85 | Conditions not satisfied — wrong DF selected, or file not in current state | Ensure parent DF is selected; check file lifecycle status |
62 83 | Selected file in terminated state — cannot read | File is locked/deactivated; try a different file or re-personalize the card |
9. T=0 vs T=1 Considerations
File navigation commands work the same way on both protocols, but T=0 requires special handling for data returned in response:
# T=0 READ BINARY with unknown file size: >> 00 B0 00 00 00 # Le = 0 (read all) # T=0 card responds: << 61 1A # "I have 0x1A (26) bytes — ask with GET RESPONSE" >> 00 C0 00 00 1A # GET RESPONSE, Le = 0x1A << ...data... 90 00 # T=1 card responds directly: >> 00 B0 00 00 00 # Le = 0 << ...data... 90 00 # Data returned inline
61XX/6CXX handling loop. Our APDU Response Debugger auto-decodes all status words — paste 61 1A and it tells you exactly how many bytes to request.Related Tools
ISO 7816-4 File System Explorer — Visual file tree with FCI decoding | APDU Command Builder — Build SELECT/READ commands | APDU Response Debugger — Decode SW1 SW2 instantly | ATR Decoder — Parse card capabilities before navigation | ISO 7816 Protocol Reference — Full protocol reference