Smart Card Filesystem Internals
The smart card filesystem defined by ISO 7816-4 is fundamentally different from disk-based filesystems. There are no directories in the POSIX sense — instead, the card uses a hierarchical structure of Master File (MF), Dedicated Files (DF), and Elementary Files (EF) organized as a tree. This guide covers the full structure, file types, access control, and how GlobalPlatform security domains map onto the filesystem.
1. Filesystem Hierarchy
1.1 The Three File Types
| Type | Abbreviation | Role | Analogy |
|---|---|---|---|
| Master File | MF | Root of the filesystem; always exists | Root directory / |
| Dedicated File | DF | Container for other DFs and EFs | Subdirectory |
| Elementary File | EF | Stores actual data (records or bytes) | File (with records) |
3F00) is technically the root DF. It can contain both DFs and EFs, just like any other DF.
1.2 Typical Card Filesystem Tree
2. File Identifiers
2.1 2-Byte File ID (FID)
Every file on the card is identified by a 2-byte File ID (FID):
3F00— MF (always)2F00— EF.DIR (application directory)2F01— EF.ATR0000–00FF— Reserved for EFs within the current DF0100–01FF— Reserved for internal use2000–3FFF— DFs4000–FFFF— EFs (application-specific)
2.2 Application Identifier (AID)
DFs can also be selected by their AID (5–16 bytes), which is how the card's runtime environment (CRE) dispatches to Java Card applets:
// Select by AID
SELECT A0000001510000 → GlobalPlatform ISD
SELECT A0000003330101 → EMV payment application
SELECT A00000030800001000 → PIV application
3. Elementary File (EF) Structures
EFs come in three structures, each optimized for different data access patterns:
3.1 Transparent (Binary) File
A simple byte array addressed by offset. Think of it as a flat binary blob.
Offset: 0x00 0x01 0x02 0x03 0x04 ...
Data: 0x4D 0x79 0x44 0x61 0x74 0x61 ...
Read: READ BINARY offset=0 length=10
Write: UPDATE BINARY offset=0 data=4D7944617461
Use cases: Certificates, keys, configuration blobs, small binary data.
3.2 Linear Fixed File
A sequence of fixed-length records, each the same size. Accessed by record number (1-based).
Record 1: [Byte0 Byte1 Byte2 ... ByteN] ← Fixed length
Record 2: [Byte0 Byte1 Byte2 ... ByteN]
Record 3: [Byte0 Byte1 Byte2 ... ByteN]
...
Read: READ RECORD P1=1 P2=04 (read record 1, next record)
Write: UPDATE RECORD P1=1 P2=04 data=...
Use cases: EMV transaction log, phonebook entries, key catalogs.
3.3 Cyclic File
A circular buffer of fixed-length records. When the last record is written, the next write overwrites record 1. The most recent record is always record 1 (pointed to by P1=01).
Write order: Rec3 → Rec2 → Rec1 (newest)
Read P1=01 → newest record
Read P1=02 → second newest
...
Use cases: Transaction logs, event counters, last-N access records.
3.4 Comparison Table
| Property | Transparent | Linear Fixed | Cyclic |
|---|---|---|---|
| Structure | Byte array | Fixed-size records | Fixed-size circular records |
| Addressing | Offset (0-based) | Record number (1-based) | Record number (1 = newest) |
| Read command | READ BINARY | READ RECORD | READ RECORD |
| Write command | UPDATE BINARY | UPDATE RECORD | UPDATE/APPEND RECORD |
| Typical size | Up to 32KB | Up to 250 records × 255 bytes | Up to 250 records × 255 bytes |
| When to use | Certificates, keys, config | Directory, catalog, log | Rolling log, event buffer |
4. SELECT Command — Navigation
The SELECT command navigates the filesystem. It can select by FID, AID, or path:
SELECT by FID
CLA=00 INS=A4 P1=00 P2=00 Lc=02 Data=3F00
// Select MF (3F00)
CLA=00 INS=A4 P1=00 P2=00 Lc=02 Data=2F00
// Select EF.DIR under current DF
SELECT by AID (DF)
CLA=00 INS=A4 P1=04 P2=00 Lc=07 Data=A0000003330101
// Select EMV application by AID
// P1=04 means "select by DF name (AID)"
SELECT by Path
CLA=00 INS=A4 P1=08 P2=00 Lc=04 Data=3F002F00
// Select file by path from MF: 3F00/2F00
// P1=08 means "select by path from MF"
CLA=00 INS=A4 P1=09 P2=00 Lc=04 Data=3F002F00
// Select by path from current DF
// P1=09 means "select by path from current DF"
5. Access Control
5.1 Access Conditions
Each file has access conditions that define what authentication state is required for each operation:
| Condition Code | Meaning | Typical Use |
|---|---|---|
0x00 | Always (no authentication) | Public data (ATR, DIR) |
0x01 | Cardholder verification (PIN) | Private keys, personal data |
0x02 | Administrative (card issuer) | Card management, key update |
0x04 | External authentication required | Secure channel operations |
0xFF | Never (disabled) | Write-once data, locked files |
5.2 Security Status vs Access Conditions
The card maintains a security status — a set of flags indicating which authentications have been performed:
Security Status after:
- SELECT MF → No authentication (always)
- VERIFY PIN (correct) → PIN verified flag set
- EXTERNAL AUTHENTICATE → External auth flag set
- PERFORM SECURITY OP → Secure channel flag set
Read EF.PrivateKey:
Access condition = 0x01 (PIN required)
→ Allowed if PIN verified flag is set
→ Denied with SW=6982 (security status not satisfied) if not
5.3 Access Mode Byte
ISO 7816-4 defines access conditions for multiple operations on each file:
| Bit | Operation | Example Condition |
|---|---|---|
| 0 | READ / SEARCH | Always (0x00) |
| 1 | UPDATE / WRITE | External auth (0x04) |
| 2 | APPEND | Never (0xFF) |
| 3 | DEACTIVATE | Admin (0x02) |
| 4 | DELETE | Admin (0x02) |
| 5–7 | RFU / vendor-specific | — |
6. GlobalPlatform Security Domains
GlobalPlatform maps its security domain architecture onto the ISO 7816 filesystem:
6.1 ISD (Issuer Security Domain)
The ISD is the primary security domain, always present on a GP card:
- AID: Typically
A0000001510000orA000000003000000 - Maps to a DF under the MF
- Manages card content (install, load, delete applets)
- Holds the Issuer Key Set (ENC, MAC, DEK) for SCP03
6.2 SSD (Supplementary Security Domain)
SSDs are delegated security domains, typically used by service providers:
- Each SSD is a DF under the ISD
- Has its own key set (delegated from ISD)
- Can install applets into its own DF
- Cannot access other SSD's content
MF (3F00)
├── DF.ISD (A0000001510000)
│ ├── EF.CM-KEY ← Card Manager keys
│ ├── EF.CM-ATR
│ ├── DF.SSD-Telecom ← Telecom provider domain
│ │ ├── EF.Keys
│ │ └── DF.USIM ← USIM applet
│ └── DF.SSD-Bank ← Banking provider domain
│ ├── EF.Keys
│ └── DF.EMV-App ← EMV applet
6.3 Application Selection Flow
1. SELECT MF (3F00) → Security status: none
2. SELECT ISD by AID → Enter GP CM context
3. INITIALIZE UPDATE + EXTERNAL AUTHENTICATE
→ Establish SCP03 secure channel
4. SELECT SSD by AID → Enter provider context
5. INSTALL [for load] → Upload applet CAP file
6. INSTALL [for install] → Create applet instance
7. SELECT Applet by AID → Applet is now active
7. File Management Commands
| Command | INS | Description |
|---|---|---|
| SELECT | A4 | Select file by FID, AID, or path |
| READ BINARY | B0 | Read bytes from transparent EF |
| UPDATE BINARY | D6 | Write bytes to transparent EF |
| READ RECORD | B2 | Read record from linear/cyclic EF |
| UPDATE RECORD | DC | Write record to linear/cyclic EF |
| APPEND RECORD | E2 | Add record to linear/cyclic EF |
| GET DATA | CA | Read a data object (by tag) |
| PUT DATA | DA | Write a data object (by tag) |
| CREATE FILE | E0 | Create a new file (DF or EF) |
| DELETE FILE | E4 | Delete a file (GP cards only) |
8. Java Card Filesystem Mapping
In Java Card, the ISO 7816 filesystem is abstracted through the javacard.framework API:
// Creating a transparent EF (Java Card)
private void createFiles() {
// Create EF for storing a certificate (256 bytes, transparent)
EF certFile = EF.builder()
.fid((short)0x4001)
.type(EF.TYPE_TRANSPARENT)
.size((short)256)
.access(ACL.READ_ALWAYS | ACL.UPDATE_EXTERNAL_AUTH)
.build();
certFile.create();
}
// Reading from a transparent EF
short readCert(byte[] dest, short offset) {
// Select the EF first
certFile.select();
// Read bytes
return certFile.readBinary((short)0, dest, offset, (short)256);
}
// Writing to a transparent EF
void writeCert(byte[] data, short offset, short len) {
certFile.select();
certFile.updateBinary((short)0, data, offset, len);
}
FileSystem API for more direct control over the card's file structure, bypassing the applet abstraction.
9. Common Debugging Scenarios
| SW (Status Word) | Meaning | Cause | Fix |
|---|---|---|---|
| 6A82 | File not found | SELECT with wrong FID or AID | Check FID/AID; verify card content with GP -list |
| 6982 | Security status not satisfied | Missing authentication for the operation | VERIFY PIN or EXTERNAL AUTHENTICATE first |
| 6985 | Conditions not satisfied | Wrong sequence (e.g., read before select) | SELECT the file before reading |
| 6A86 | Incorrect P1/P2 | Invalid file type for the command | Use READ BINARY for transparent, READ RECORD for linear/cyclic |
| 6A84 | Not enough memory | File creation fails (NVM full) | Delete unused files; check available space |
| 6400 | State non-volatile memory changed | Write succeeded but NVM was full | Verify written data; free NVM |
10. Best Practices
- Always SELECT before READ. After any SELECT command, the previous EF is deselected.
- Use EF.DIR to discover applications. Read
2F00to enumerate all DFs and their AIDs. - Check security status before operations. Use
GET RESPONSEor card-specific commands to verify auth state. - Use transparent EFs for blobs, linear for records. Match the EF structure to your access pattern.
- Reserve FID ranges. Define a FID allocation scheme for your application to avoid collisions.
- Implement proper access control. Never leave sensitive EFs with "always" read access.
- For GP cards, use the ISD/SSD model. Don't create ad-hoc DFs — follow the GP security domain hierarchy.