nRF5 SDK v15.3.0
APDU reader/writer

Special communication units, called application protocol data units (APDUs), are used when exchanging data with a Type 4 Tag platform. Command APDUs (C-APDUs) are the commands sent from the NFC reader, while the response APDUs (R-APDUs) are the responses to a specific command received by NFC reader from the tag.

The APDU reader/writer module provides functions to encode a C-APDU according to its descriptor and to decode a raw R-APDU data into the appropriate descriptor. For the API documentation of this module, refer to APDU reader/writer.

APDU types

There are three types of APDU that are relevant for the Type 4 Tag platform:

APDU type Description
Select Selection of applications or files.
ReadBinary Reading data from a file.
UpdateBinary Writing data to a file.

C-APDU and R-APDU format

A C-APDU consists of the following fields:

Field Length Required Description
CLA 1 byte yes Specifies the security level of the message.
INS 1 byte yes Specifies the command type to process. See APDU types.
P1 1 byte yes Specifies the first parameter for the chosen command type.
P2 1 byte yes Specifies the second parameter for the chosen command type.
Lc 1 or 3 bytes no Specifies the data length.
Data Lc bytes no Required if LC field is present. Contains payload of C-APDU.
Le 1 or 2 bytes no Specifies the expected response body length of R-APDU.

An R-APDU consists of the following fields:

Field Length Required Description
Response Body variable no Carries the data of the R-APDU.
SW1 1 byte yes Specifies the first status word.
SW2 1 byte yes Specifies the second status word.

Generating C-APDU and decoding R-APDU

The following code example shows how to build a C-APDU which can be used in CC/NDEF select procedure (see Type 4 Tag NDEF detection procedure):

ret_code_t err_code;
uint8_t apdu_buff[APDU_BUFF_SIZE];
uint8_t file_id_buff[] = ...; // 2-byte long File Identifier, for example: {0xE1, 0x04}
capdu.data.p_buff = file_id_buff;
capdu.data.len = sizeof(file_id_buff);
uint16_t apdu_buff_len = APDU_BUFF_SIZE;
apdu_buff,
&apdu_buff_len);
if (err_code != NRF_SUCCESS)
{
//Error during C-APDU generation.
return err_code;
}

Note that the Le field is not present in this case.

The following code example shows how to create a C-APDU descriptor which can be used in CC/NDEF read procedure (see Type 4 Tag NDEF detection procedure):

uint16_t file_offset = ...; // File offset where to start reading data.
uint16_t file_bytes_to_read = ...; // The number of bytes to be read from file.
capdu.parameter = file_offset;
capdu.resp_len = file_bytes_to_read;

Note that Lc and Data fields are not present in this case. You must also ensure that the number of bytes to write (the value carried by the Le field) is not greater than the MLe (Maximum R-APDU data) field, which is located in the CC file.

The following code example shows how to create a C-APDU descriptor which can be used in the NDEF update procedure (see Type 4 Tag NDEF detection procedure):

uint8_t ndef_file_buff = ...; // NDEF file buffer.
uint16_t file_offset = ...; // File offset where to start writing data.
uint16_t file_bytes_to_write = ...; // The number of bytes to be written to the file.
capdu.parameter = file_offset;
capdu.data.p_buff = ndef_file_buff + file_offset;
capdu.data.len = file_bytes_to_write;

Note that the Le field is not present in this case. You also need to ensure that the number of bytes to read (value carried by the Lc field) is not greater than the MLc (Maximum C-APDU data) field, which is located in the CC file.

The last code example shows how to decode a raw R-APDU data to its descriptor:

ret_code_t err_code;
uint8_t rapdu_buff[] = ...; // Buffer with raw R-APDU data.
err_code = nfc_t4t_resp_apdu_decode(&rapdu, rapdu_buff, sizeof(rapdu_buff));
if (err_code != NRF_SUCCESS)
{
//Error during R-APDU decoding.
return err_code;
}
//Print R-APDU descriptor.

Note that if the Response Body field is not present in the R-APDU, the data field in the R-APDU descriptor is equal to NULL.


Documentation feedback | Developer Zone | Subscribe | Updated