Protocol-dependent methods of processing APDU commands
Programming of applets for the Java Card platform at the application level involves processing APDU commands using the capabilities of the APDU class. The APDU class provides a simple, unified interface for applets that does not depend on the lower-level transport protocol used (T=0 or T=1). However, some outdated smart card systems were designed in such a way that in order to exchange data, the applets must know the features of the transport protocol being used. To ensure compatibility with the same systems and be able to exchange data with a variety of available card readers, applets must use protocol-dependent attributes. Therefore, the APDU class also defines methods that the applet can use to find out the type of transport protocol used, allocate memory for receiving and sending data, and make a request for additional processing time.
This section explains what these methods are for and how they should be used. However, we emphasize once again that all the methods that are defined in the APDU class can be used in a way that does not take into account the transport protocol used. In other words, to work with these methods, you do not need to know the details of the implementation of the transport protocol.
For most applet developers, a cursory acquaintance with this section will be enough. In the future, it can be used as a reference guide for special cases of applet programming.
getProtocol method
public static byte getProtocol()
The getProtocol method returns the type of the ISO 7816 transport protocol that the Java Card platform supports. The result can be either APDU.PROTOCOL_T0 for protocol T=0, or APDU.PROTOCOL_T1 for protocol T=1.
getInBlockSize method
public static short getInBlockSize()
The getInBlockSize method returns the size of the incoming block specified in the configuration. The T=1 protocol is a block transfer protocol. The APDU command is transmitted either by one block or by several, if a coupling mechanism is provided. The coupling mechanism allows you to transmit the APDU command in several consecutive blocks. Each block consists of three fields: the prologue field, the information field and the epilogue field. The prologue and epilogue fields contain service data about the block, and the information field is used to deliver the APDU command.
If the T=1 protocol is used, the getInBlockSize method returns the block size corresponding to the IFSC parameter (length of the card data field, information field size on card). IFSC defines the maximum length of the information field in the block that the card can accept. The IFSC value may be different for different maps. The default IFSC value is 32 bytes. Therefore, the minimum size of the APDU buffer is 37, including a 5-byte header and 32 bytes of data (default IFSC value). Usually the length of the APDU buffer is slightly longer. This allows the applet to leave a few bytes of data in the APDU buffer and continue to receive data from the next command without risking an overflow.
The protocol T=0 is byte-based. It has no requirements for the length of the transmitted data. Only 1 byte of data is transmitted per exchange operation. Therefore, if the T=0 protocol is used, the getInBlockSize method returns 1.
The applet can use the getInBlockSize method in protocol-independent mode to determine the maximum number of bytes that can be received into the APDU buffer in a single exchange operation. During the execution of the receiveBytes and setIncomingAndReceive methods, one or more of these data exchange operations with the host system occur.
In addition, before calling receiveBytes, the applet can use the InBlockSize method to make sure that there is enough free space in the APDU buffer. For example, in order to optimize memory usage, an applet can reserve n bytes at the beginning of the APDU buffer to store daily data, so as not to allocate a separate buffer for this purpose. To do this, the applet must check whether the remaining part of the APDU buffer will be enough to store at least one block of data that can come from the host system.
getOutBlockSize method
public static short getOutBlockSize()
The getOutBlockSize method is similar to the getInBlockSize method. It returns the size of the outgoing block specified in the configuration. If the protocol T=1 is used, this method returns the maximum size of the information field that the host application can accept. This size corresponds to the IFSD parameter (length of the data field of the interface device, information field size for interface device). The minimum value defined in the ISO 7816-3 specification is 32 bytes. For the T=0 protocol, this method returns 258. 2 bytes added to transmit the status word. Thus, the maximum size of data that an applet can send to a host application is 256 bytes.
The IFSD parameter is set in the host system. Unlike the data receiving operation (the InBlockSize method), when transmitting, the applet usually does not check the allowable size of the data being sent using the OutBlockSize method. When using the T=1 protocol, JCRE usually cannot send all data in one block – the maximum size of the response data is limited by IFSD. Therefore, JCRE can divide data into blocks and send them using the chaining mechanism of commands. However, if the existing protocol implementation T=1 does not support coupling, JCRE cannot transmit large-volume response data to the host system. In this case, it raises an APDUException exception. This example shows how the applet can bypass the limitation associated with the inability to use coupling.
// The “electronic wallet” applet stores in the transaction log
// information about the last three communication sessions
//
// For simplicity, let’s assume that each log entry is formed in a byte array
// and the full size of the log less than 256 bytes
//
// In response to the APDU READ_TRANSACTION_LOG command
// the applet should send all transaction log entries to the host application
//
// Which transport protocol is used?
if (apdu.getProtocol() == APDU.PROTOCOL_T0) {
// Protocol T=0 – all log entries can be transferred in one operation
//…
} else {
// Protocol T=1 – get the size of the outgoing block
short out_block_size = apdu.getOutBlockSize();
// Check if the entire log
// fits into one outgoing block
if (TOTAL_LOG_RECORD_SIZE <= out_block_size) {
// The entire log can be sent in one transfer operation apdu.setOutgoingLength(TOTAL_LOG_RECORD_SIZE); apdu.sendBytesLong(log_record_1, (short)0,
(short)log_record_1.length);
apdu.sendBytesLong(log_record_2, (short)0,
(short)log_record_2.length); apdu.sendBytesLong(log_record_3, (short)0,
(short)log_record_3.length);
return;
} else {
// We send one record and inform the host application that
// not all records have been sent yet apdu.setOutgoingLength((short)log_record_1.length); apdu.sendBytesLong(log_record_1, (short)0,
(short)log_record_1.length);
// We inform the host application that there are two more log entries left.
// The host application can send additional APDU commands,
// to get the remaining entries
ISOException.throwIt(SW_2_MORE_RECORDS);
}
}
setOutgoingNoChaining method
public short setOutgoingNoChaining() throws APDUException
If coupling is not supported, this method is used to switch to data transmission mode in the direction of the host system and get the expected response length in bytes (Le field). Applets should use this method instead of the setOutgoing method to ensure compliance with the EMV specification. The setOutgoingNoChaining method can be used in the same way as the setOutgoing method. After calling this method, all unrecognized incoming data is discarded. The applet should call the setOutgoingLength method to report
to the host application about how many bytes it is going to actually transfer to it.
getNAD method
public byte getNAD()
When using the T=1 protocol, this method returns a byte of the node address byte (NAD). The NAD field is the first byte in the prologue field of the block T=1. The NAD field defines both the address of the source node (source node address, SAD) and the address of the destination node (destination node address, DAD). The smart card system can use NAD to support multiple logical communication sessions between the host system and the card.
For the T=0 protocol, the getNAD method returns 0.
waitExtension method
public byte waitExtension()
If the host system does not receive any response within the maximum period of time defined in the ISO 7816-3 specification, it considers that
Conclusions
The card is unavailable and interrupts the communication session. The applet can call the waitExtension method in order to request additional time from the host system to process the command so that a timeout does not occur during the execution of a long operation by the applet. Such an operation may involve writing a large amount of data to the EEPROM memory or performing complex encryption algorithms.
The applet can call the waitExtension method at any time during the processing of the APDU command. If the card has a hardware timer that automatically calls the waitExtension method, the applet may not request additional time from the host system to process the command.
This chapter was devoted to the issues of processing APDU commands in applets. We have carefully considered the methods of the APDU class, which are designed to analyze the head of the APDU command, read the command data block and send a response to the host application.
At the end of this topic, we will give the algorithms that the applet should perform when processing different types of APDU commands. In all cases, the applet can raise an ISOException exception with the appropriate reason code to report the error.
Type 1 – data is not transmitted to or from the card.
- The process method of the applet is called. The applet checks the first 4 bytes of the APDU buffer and determines that the command is of type 1. The value of the P3 field (the fifth byte in the APDU buffer) is 0.
- The applet performs the necessary actions encoded in the header of the APDU code.
- There is a return from the process method of the applet.
Type 2 – data is not transmitted to the card, but response data is transmitted from the card. - The process method of the applet is called. The applet checks the first 4 bytes of the APDU buffer and determines that the command is of type 2. In this case, the P3 field is interpreted as Le (the length of the message expected by the host application in response to this command).
- The applet performs the necessary actions encoded in the header of the APDU code.
- Then the applet sends the response data. The response data can be placed in the APDU buffer, or it can exceed it in length. These cases are treated differently.
The response data is placed in the APDU buffer: - The applet calls the setOutgoingAndSend method and specifies the actual length of the response data.
- There is a return from the process method of the applet.
The length of the response data exceeds the size of the APDU buffer:
- The applet calls the setOutgoing method and gets the length of the Le field.
- The applet calls the setOutgoingLength method and indicates to the host application the actual length of the response data.
- The applet calls the sendBytes or sendBytesLong method (if necessary several times) to send groups of response bytes.
- There is a return from the process method of the applet.
Type 3 – data is transmitted to the card, the response data is not transmitted from the card. - The process method of the applet is called. The applet checks the first 4 bytes of the APDU buffer and determines that the command is of type 3. In this case, the P3 field is interpreted as Lc (the length of the command data field).
- The applet calls the setIncomingAndReceive method, then, if necessary, cyclically calls the receiveBytes method to accept all bytes of the command. After receiving each group of bytes of command data, it is either processed in place or copied to the internal buffer.
- There is a return from the process method of the applet.
Type 4 – Data is transferred to and from the card.
Type 4 is a combination of types 3 and 2. First, the applet reads the command data, as described in case 3. Then the applet sends the response data, as described in case 2. Finally, a return occurs from the process method of the applet.