How to Build APDU Commands — C-APDU Construction Walkthrough

Every interaction with a smart card is an APDU (Application Protocol Data Unit) exchange. The command APDU (C-APDU) is a 4-byte header + optional body that tells the card what to do. This guide covers CLA/INS/P1/P2 byte selection, Lc/Le encoding, Case 1-4 structures, extended APDU, and practical command recipes for common smart card operations.

1. C-APDU Structure — The 4 Cases

ISO 7816-4 defines four C-APDU cases based on whether data is sent (Lc) and/or expected back (Le):

CaseStructureLcLeExample
1CLA INS P1 P2NoNoSELECT MF (implicit Le=0)
2CLA INS P1 P2 LeNoYesREAD BINARY with expected length
3CLA INS P1 P2 Lc DataYesNoVERIFY PIN with no response
4CLA INS P1 P2 Lc Data LeYesYesSELECT by AID with response

2. CLA Byte — Class Byte

CLA byte structure (ISO 7816-4):
Bit 7-6: Interindustry flags
Bit 5:   Command chaining (0=last/no chain, 1=more commands follow)
Bit 4-3: Secure messaging flags
Bit 2-0: Logical channel number (0-3)

Common CLA values:
0x00 — ISO standard, no SM, no chaining, channel 0
0x04 — ISO standard, chaining, no SM, channel 0
0x0C — ISO standard, SM, channel 0
0x80 — GP (GlobalPlatform) command
0x84 — GP with chaining
0xB0 — EMV payment system command (always P1=0x00, P2=0x00)

3. INS Byte — Instruction Byte

INSNameDescriptionTypical Use
0xA4SELECTSelect file/applet by DF name or FIDEvery session starts here
0xB0READ BINARYRead transparent/linear EF dataRead ICCID, IMSI, PAN
0xD6UPDATE BINARYWrite to transparent EFUpdate card data records
0xB2READ RECORDRead linear/circular EF recordRead EMV AFL records
0x20VERIFYSubmit PIN/passwordPIN verification (P2=CHV reference)
0x84GET CHALLENGERequest random number for authMutual authentication start
0x88INTERNAL AUTHENTICATECard signs/encrypts challengeCard authentication proof
0x82EXTERNAL AUTHENTICATETerminal authenticates to cardGP secure channel init
0xC0GET RESPONSERetrieve data from T=0 cardAfter 61XX status (T=0 protocol)

4. Building Common APDU Commands

SELECT — Select an Application

# SELECT by AID (Application Identifier)
# CLA=0x00, INS=0xA4, P1=0x04 (by DF name), P2=0x00
aid = [0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10]  # Visa AID
SELECT_AID = [0x00, 0xA4, 0x04, 0x00, len(aid)] + aid + [0x00]
# → [00 A4 04 00 07 A0 00 00 00 03 10 10 00]

# SELECT MF (Master File)
SELECT_MF = [0x00, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00]

# SELECT by FID (2-byte file ID)
# P1=0x00 selects MF/DF/EF by file identifier
SELECT_FILE = [0x00, 0xA4, 0x00, 0x00, 0x02, 0x2F, 0xE2]  # EF_ICCID

READ BINARY — Read File Data

# READ BINARY on currently selected EF
# P1P2 = offset (15 bits available, top bit reserved)
# Le = bytes to read (0x00 = read 256 bytes in short APDU)
READ_10_BYTES  = [0x00, 0xB0, 0x00, 0x00, 0x0A]  # Offset 0, 10 bytes
READ_OFFSET_50 = [0x00, 0xB0, 0x00, 0x32, 0x10]  # Offset 50, 16 bytes

# Extended APDU (>256 bytes):
# Offset = 0x000200 (512), Le = 0x0100 (256 bytes)
READ_EXTENDED = [0x00, 0xB0, 0x02, 0x00, 0x00, 0x01, 0x00]
#                CLA  INS  P1   P2   00(Lc field) Le_hi Le_lo

VERIFY — Submit PIN

# VERIFY CHV1 (P2 = 0x01 for basic PIN, 0x80 for GP PIN)
pin = "1234"
VERIFY_PIN = [0x00, 0x20, 0x00, 0x01, len(pin)] + [ord(c) for c in pin]
# → [00 20 00 01 04 31 32 33 34]

5. Extended APDU — Handling >256 Bytes

Standard APDU uses 1-byte Lc and Le (max 255). Extended APDU uses 3 bytes for each, supporting up to 65535 bytes:

# Standard (short) APDU: CLA INS P1 P2 [Lc] [Data] [Le]
# Extended APDU:         CLA INS P1 P2 00 Lc_hi Lc_lo [Data] Le_hi Le_lo

# SELECT with extended Le:
SELECT_EXT = [0x00, 0xA4, 0x04, 0x00, 0x07] + aid + [0x00, 0x00, 0x00]
#             CLA  INS  P1   P2   Lc   Data   00(Lc empty) Le=0x000000

# Card indicates extended APDU support in ATR (interface bytes TA2/TB2)

6. CLA/INS Quick Reference for Common Smart Cards

Card TypeCLA RangeNotable INS Values
ISO 7816-4 standard0x00, 0x04, 0x0CSame as table above
GlobalPlatform (GP)0x80, 0x84DELETE 0xE4, INSTALL 0xE6, PUT KEY 0xD8, STORE DATA 0xE2
EMV Payment0x80, 0xB0GET PROCESSING OPTIONS 0xA8, READ RECORD 0xB2, GENERATE AC 0xAE, GET DATA 0xCA
MIFARE DESFire0x90GET VERSION 0x60, CREATE APPLICATION 0xCA, GET FILE IDS 0x6F
PIV / CAC0x00GET DATA 0xCB, GENERAL AUTHENTICATE 0x87 (P1=alg, P2=key ref)
Test this yourself: Use our APDU Command Builder to visually construct commands — pick CLA/INS/P1/P2 from dropdowns, enter hex data, and get ready-to-send byte arrays. Our APDU Response Debugger decodes SW1 SW2 instantly.

7. Command Chaining

When command data exceeds 255 bytes (and extended APDU isn't supported), split across multiple commands:

# Chain 500-byte UPDATE BINARY across 3 commands:
CHUNK1 = [0x10, 0xD6, 0x00, 0x00, 0xFF] + data[0:255]     # CLA bit5=1: more follows
CHUNK2 = [0x10, 0xD6, 0x00, 0x00, 0xFF] + data[255:510]   # Last chunk: CLA bit5=0
CHUNK3 = [0x00, 0xD6, 0x00, 0x00, len(data[510:])] + data[510:]
# First 2 have CLA=0x10 (chaining), last has CLA=0x00 (end of chain)

Related Tools

APDU Command Builder — Visual APDU construction | APDU Response Debugger — Decode SW1 SW2 | APDU Quick Reference — All ISO 7816-4 instructions | ISO 7816 Protocol Reference