Understanding APDUs with ISO/IEC 7816-4

Break down a POOM NFC command APDU into CLA, INS, P1, P2, Lc, Data, and Le fields, then read the SELECT command byte by byte.

We have already learned what an APDU is and sent one from POOM. Sending a command directly to a card and receiving a real response is exciting, but the previous lesson left one question open:

Where do those bytes come from, and what does each one mean?

This is where ISO/IEC 7816-4 enters the picture. ISO/IEC 14443-4 helped us transport information with ISO-DEP; ISO/IEC 7816-4 helps us understand what the command says.

We do not need the entire standard for this lesson. We only need one useful short C-APDU structure:

CLA INS P1 P2 [Lc] [Data] [Le]

Goal

In this lab, you will:

  • understand the basic structure of a C-APDU;
  • learn what CLA, INS, P1, P2, Lc, Data, and Le mean;
  • break down the APDU from the previous lesson byte by byte;
  • read an APDU as a structured message instead of random hexadecimal.

Our APDU

This is the command from the previous lesson:

00 A4 04 00 07 D2 76 00 00 85 01 01 00

It becomes much easier to read when we divide it into fields:

00 | A4 | 04 | 00 | 07 | D2 76 00 00 85 01 01 | 00

CLA  INS   P1   P2   Lc            Data            Le

ISO/IEC 7816-4 defines these fields for constructing a command APDU. Let us examine them one at a time.

CLA: which command class are we using?

The first byte is:

CLA = 00

CLA means Class. Think of it as the command family. Here, 00 identifies the interindustry class defined by ISO/IEC 7816.

You do not need to memorize every possible value. For now, remember:

CLA = command family

INS: what do we want to do?

The next byte is:

INS = A4

INS means Instruction. It identifies the operation we want the card to execute. In this command:

A4 = SELECT

When we see 00 A4, we already know something important: we want to perform a SELECT. You can think of INS as a function name, except that the card receives a byte instead of C source code.

P1 and P2: how should the command run?

A4 says SELECT, but the card still needs to know what to select and how. That is the job of the two parameter bytes:

P1 = 04
P2 = 00

For SELECT, P1 = 04 requests selection by DF name. For this lab, think of a DF name as an identifier we want the card to find. P2 supplies additional selection options; we do not need to memorize all of its combinations yet.

A simple way to remember the relationship is:

INS   = what I want to do
P1 P2 = how I want to do it

Lc: how much data are we sending?

The next byte is:

Lc = 07

07 is not part of the identifier. Lc tells the card how many bytes are present in the command's Data field. Here it means: seven data bytes follow.

1  D2
2  76
3  00
4  00
5  85
6  01
7  01

The count matches the value in Lc.

Data: what information are we sending?

The seven data bytes are:

D2 76 00 00 85 01 01

Because this is INS = A4 with P1 = 04, these bytes are the DF name we want to select. Written without spaces:

D2760000850101

Our command is now beginning to speak clearly:

Select the DF named D2760000850101.

Le: how much data do we expect back?

The final byte is:

Le = 00

Le is related to the amount of response data we expect. The distinction is important:

Lc = how much Data I am sending
Le = how much Data I expect to receive

In a short APDU, Le = 00 has a special meaning. It does not request zero bytes; it represents a maximum response length of 256 bytes. Extended APDUs use other encodings, but we do not need them for this lesson.

Read the complete command

We can now label every part:

CLA  = 00
INS  = A4
P1   = 04
P2   = 00
Lc   = 07
Data = D2 76 00 00 85 01 01
Le   = 00
FieldValueMeaning here
CLA00Interindustry command class
INSA4Execute SELECT
P104Select by DF name
P200Options for the SELECT
Lc07Seven command data bytes follow
DataD2760000850101The DF name to find
Le00Allow up to 256 response bytes

In plain language, the APDU says:

Card, execute SELECT. Find the DF identified by D2760000850101 and return the information associated with that selection.

The hexadecimal sequence is not arbitrary. It is a structured message.

Try it again

On POOM, open THE BEAST from the main menu and select CLI. Keep the same compatible NFC Type A tag under POOM, then run the sequence:

nfc-core-stop
nfc-core-start
nfc-tech-set-a
nfc-card-connect
nfc-card-send 00 A4 04 00 07 D2 76 00 00 85 01 01 00
Authorized lab only: send APDUs only to cards and systems that you own or have explicit permission to test.

In the previous example, POOM received:

R-APDU: 6A 82

6A 82 means File not found. The card received the SELECT, looked for D2760000850101, and reported that it could not find that object.

The response is not the main point this time. The important result is that we now understand exactly what we asked.

An easy way to remember it

CLA
Which command family am I using?

INS
What do I want to do?

P1 P2
How do I want to do it?

Lc
How much data am I sending?

Data
What information am I sending?

Le
How much do I expect to receive?

What you should learn

In the previous lesson, we proved that POOM can send a C-APDU and receive an R-APDU. Now we understand that a short command APDU can be organized as:

CLA INS P1 P2 [Lc] [Data] [Le]

When we encounter a command beginning with 00 A4 04 00, we can recognize a SELECT by DF name and then use Lc, Data, and Le to read the rest of the message.

The next lesson can apply the same knowledge to application identifiers found on payment cards, where this command structure appears in EMV. Use only your own cards or cards you are explicitly authorized to examine.