Smart cards. Part 2. APDU
After the general information described in the first part , today we’ll talk about APDUs in the format described in the ISO7816-4 standard.
APDU (application protocol data unit) is the communication format of the card and terminal. The terminal sends a Command APDU (C-APDU), and the card responds with a Response APDU (R-APDU).
C-APDU
The C-APDU format is as follows:
| Header | Body |
|---|---|
| CLA INS P1 P2 | [Lc field] [Data field] [Le field] |
Each header element is stored on one byte and is required. We’ll return to the title a bit later, now let's talk about the body of the team.
The body elements are as follows:
- Lc : length of the Data element in bytes.
- Data : command data.
- Le : The expected length of the response data in bytes, excluding the length of the Status Word.
Lc and Le, if present, can occupy 1 (Short Length) or 3 bytes (Extended Length) each. Short Length encodes values from 1 to 256. The data length of 256 bytes is written as “00”. With Extended Length, values from 1 to 65536 are encoded. The first byte is always “00” and the remaining 2 bytes are a number in Big Endian format. When Lc or Le is “00 00 00”, then the data length is 65536 bytes.
Depending on the presence or absence of the body elements of the team can be divided into 4 categories:
- Case 1 : Body is completely absent, that is, the team does not contain any data and is not expected to receive any data from the card when responding.
- Case 2 : Only Le is present in the body, that is, the command does not contain any data, but it is expected to receive data from the card.
- Case 3 : Lc and Data are present in the body, that is, the command contains data, but it is not expected to receive data from the card.
- Case 4 : All elements are present in the body, which means that the command contains data and is expected to receive data from the card.
I will show examples of commands later. Now back to header.
| Element | Value |
|---|---|
| CLA | Class bytes . Contains command metadata (logical channel, secure messaging, etc.). |
| Ins | Instruction byte . Instruction code. This is a hexadecimal number, the highest nibble of which cannot be 6 or 9. Moreover, the minor nibble is always an even number. |
| P1 | The first parameter of the command . If it is not needed, then its value is "00". |
| P2 | The second parameter of the command . If it is not needed, then its value is also “00”. |
Since the series of my articles is aimed at considering the details of the Global Platform, I will describe the meaning of CLA in the context of the Global Platform.
CLA bytes with a logical channel from 0 to 3
| b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 | Value |
|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | - | - | - | - | Team from ISO7816-4 |
| 1 | 0 | 0 | 0 | - | - | - | - | Team from Global Platform Specification |
| - | 0 | 0 | 0 | 0 | 0 | - | - | No Secure Messaging |
| - | 0 | 0 | 0 | 0 | 1 | - | - | Secure Messaging by Global Platform |
| - | 0 | 0 | 0 | 1 | 0 | - | - | Secure Messaging to ISO7816-4 without C-MAC |
| - | 0 | 0 | 0 | 1 | 1 | - | - | Secure Messaging to ISO7816-4 with C-MAC |
| - | 0 | 0 | 0 | - | - | X | X | Logical channel |
CLA bytes with a logical channel from 4 to 19
| b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 | Value |
|---|---|---|---|---|---|---|---|---|
| 0 | 1 | - | 0 | - | - | - | - | Team from ISO7816-4 |
| 1 | 1 | - | 0 | - | - | - | - | Team from Global Platform Specification |
| - | 1 | 0 | 0 | - | - | - | - | No Secure Messaging |
| - | 1 | 1 | 0 | - | - | - | - | Secure Messaging by Global Platform or ISO7816-4 |
| - | 1 | - | 0 | X | X | X | X | Logical channel |
b7 determines if the CLA format is either in the first or as in the second table. When the logical channel is in the range from 0 to 3, its value is written in bits 1 and 2. Otherwise, the number written in bits 1-4 encodes the number from 4 to 19 (0 = 4, 1 = 5, ..., 15 = 19).
b5 in the ISO7816-4 standard stands for Command Chaining. The Global Platform is not used.
R-APDU
The format of the R-APDU is as follows:
| Body | Trailer |
|---|---|
| [Data field] | SW1 SW2 |
Body is present upon successful execution (with or without comments) of teams from the Case 2 and Case 4 categories. Its contents depend on the particular team. Trailer is always there and contains the so-called Status Word, that is, the result code, positive or negative. Status can be one of the following:
| SW1SW2 | Value |
|---|---|
| Successful execution | |
| 9000 | OK. |
| 61XX | OK, but there are still XX bytes of data. |
| Execution completed with comments | |
| 62XX | SW2 clarifies the reasons for the comment. Permanent memory has not been changed. |
| 63XX | SW2 clarifies the reasons for the comment. Permanent memory has been changed. |
| Errors in the execution of the command | |
| 6400 | The command was not executed. Permanent memory has not been changed. |
| 65XX | The command was not executed. The constant has been changed. |
| 66XX | The command was not executed for security reasons. |
| Command format errors | |
| 6700 | Wrong team length. |
| 6881 | The card does not support the specified logical channel. |
| 6882 | The card does not support the specified type of Secure Messaging. |
| 69XX | The command is not allowed. |
| 6AXX | Incorrect command parameters. |
| 6B00 | Incorrect command parameters. |
| 6CXX | Wrong Le. |
| 6D00 | Unknown INS. |
| 6E00 | Unknown CLA. |
| 6F00 | Error without description. |
Errors from the 69XX and 6AXX series are often used in the Global Platform and will be described in detail in parts of the Global Platform article.
Statuses from the 61XX and 6CXX series require special attention. Code 61XX is possible when the card executed a command from the Case 2 or Case 4 category and sent an incomplete response. In this case, SW2 encodes the length of the remainder of the response (“00” = 256). In response, the terminal may send a GET RESPONSE command in order to receive the remaining data. This procedure can be repeated several times until the card sends a complete response. The true Status Word is the status contained in the last response to the GET RESPONSE command. A similar situation occurs mainly when the APDU is transmitted via the ISO7816-3 T = 0 protocol due to the peculiarity of transferring commands from the Case 4 category (we will talk about this a bit later). Code 6CXX occurs when the specified Le does not match the actual length of the response. It should be noted that while the card does not send any data to the R-APDU,
Features of the transfer of commands in the Case 4 category through the T = 0 protocol
Protocol T = 0 is very common, as it is used in SIM cards. Its peculiarity lies in the fact that header always consists of 5 bytes: CLA, INS, P1, P2, P3. P3 can be used to encode Lc or Le. It turns out that it will be superfluous for Case 1 teams, suitable for Case 2 and Case 3 teams, but insufficient for Case 4 teams where both Lc and Le are needed. How can this problem be solved?
In the following way. Case 4 commands are transmitted with P3 = Lc, as if it were a Case 3 command. Then the card, if the command is executed successfully, responds without data, but with a status of 61XX. In turn, the terminal sends a GET RESPONSE command (from the Case 2 category), and then the card sends a real response.
GET RESPONSE
| Element | Value |
|---|---|
| CLA | as the previous command, but without Secure Messaging and bit8 = 0 (although the cards accept bit8 = 1) |
| Ins | C0 |
| P1 | 00 |
| P2 | 00 |
| Lc | - |
| Data | - |
| Le | XX (usually SW2 of the previous answer) |
Examples of communication with the card
Finally, we come to the most interesting part of the article - examples.
GET DATA (Card Production Life Cycle)
C-APDU => 80 CA 9F 7F 00
R-APDU <= 6C 2D
C-APDU => 80 CA 9F 7F 2D
R-APDU <= 9F 7F 2A 47 90 50 40 47 91 81 02 31 00 83 58 00 11 68 91 45 81 48 12 83 65 00 00 00 00 01 2F 31 30 31 31 36 38 00 00 00 00 00 00 00 00 00 90 00
The GET DATA command (Case 2) reads information from the card. Which one is determined by the parameters P1 and P2. Answer in BER-TLV format (subject of the next part of the article). Here we see how at the beginning the team was sent with the wrong Le and the card, in turn, responded with the status 6C 2D. After repeating the command with Le = 2D, the card sent a response and a final status of 9000, indicating successful execution.
GET STATUS through T = 1
C-APDU => 80 F2 40 00 08 4F 06 31 32 33 34 35 36 09
R-APDU <= 06 31 32 33 34 35 36 07 00 90 00
The GET STATUS (Case 4) command gives information about the life cycle of the card and applications. In this example, Lc = 8, Data = 4F 06 31 32 33 34 35 36 and Le = 9. At this stage I will not go into an explanation of the meaning of these data, since this is not so important. The card in response sends data 06 31 32 33 34 35 36 07 00 and status 9000. Below we look at the exact same command, only sent via the T = 0 protocol.
GET STATUS over T = 0
C-APDU => 80 F2 40 00 08 4F 06 31 32 33 34 35 36
R-APDU => 61 09
C-APDU => 00 C0 00 00 09
R-APDU <= 06 31 32 33 34 35 36 07 00 90 00
Here we see that GET STATUS leaves without Le. The protocol does not allow us to do this, since Lc is specified in P3. In response, the card will tell us the length of the data we need to receive. Then we send the GET RESPONSE command with Le = 9. After that, the card finally sends us the corresponding response.
So we have come to the end of this part. If anyone has questions, you can write them in the comments. The next part of the article will be about BER-TLV, since this data encoding format is used for almost everything related to smart cards.
The rest of the article
Part 1. Principles of Operation
Part 3. TLV