javacard.framework
Class APDU

java.lang.Object
  extended byjavacard.framework.APDU

public final class APDU
extends Object

Application Protocol Data Unit (APDU) is the communication format between the card and the off-card applications. The format of the APDU is defined in ISO specification 7816-4.

This class only supports messages which conform to the structure of command and response defined in ISO 7816-4. The behavior of messages which use proprietary structure of messages ( for example with header CLA byte in range 0xD0-0xFE ) is undefined. This class does not support extended length fields.

The APDU object is owned by the JCRE. The APDU class maintains a byte array buffer which is used to transfer incoming APDU header and data bytes as well as outgoing data. The buffer length must be at least 37 bytes ( 5 bytes of header and 32 bytes of data ). The JCRE must zero out the APDU buffer before each new message received from the CAD.

The JCRE designates the APDU object as a temporary JCRE Entry Point Object (See Java Card Runtime Environment (JCRE) Specification, section 6.2.1 for details). A temporary JCRE Entry Point Object can be accessed from any applet context. References to these temporary objects cannot be stored in class variables or instance variables or array components.

The JCRE similarly marks the APDU buffer as a global array (See Java Card Runtime Environment (JCRE) Specification, section 6.2.2 for details). A global array can be accessed from any applet context. References to global arrays cannot be stored in class variables or instance variables or array components.

The applet receives the APDU instance to process from the JCRE in the Applet.process(APDU) method, and the first five bytes [ CLA, INS, P1, P2, P3 ] are available in the APDU buffer.

The APDU class API is designed to be transport protocol independent. In other words, applets can use the same APDU methods regardless of whether the underlying protocol in use is T=0 or T=1 (as defined in ISO 7816-3).

The incoming APDU data size may be bigger than the APDU buffer size and may therefore need to be read in portions by the applet. Similarly, the outgoing response APDU data size may be bigger than the APDU buffer size and may need to be written in portions by the applet. The APDU class has methods to facilitate this.

For sending large byte arrays as response data, the APDU class provides a special method sendBytesLong() which manages the APDU buffer.

 // The purpose of this example is to show most of the methods
 // in use and not to depict any particular APDU processing

public void process(APDU apdu){
  // ...
  byte[] buffer = apdu.getBuffer();
  byte cla = buffer[ISO7816.OFFSET_CLA];
  byte ins = buffer[ISO7816.OFFSET_INS];
  ...
  // assume this command has incoming data
  // Lc tells us the incoming apdu command length
  short bytesLeft = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
  if (bytesLeft < (short)55) ISOException.throwIt( ISO7816.SW_WRONG_LENGTH );

  short readCount = apdu.setIncomingAndReceive();
  while ( bytesLeft > 0){
      // process bytes in buffer[5] to buffer[readCount+4];
      bytesLeft -= readCount;
      readCount = apdu.receiveBytes ( ISO7816.OFFSET_CDATA );
      }
  //
  //...
  //
  // Note that for a short response as in the case illustrated here
  // the three APDU method calls shown : setOutgoing(),setOutgoingLength() & sendBytes()
  // could be replaced by one APDU method call : setOutgoingAndSend().

  // construct the reply APDU
  short le = apdu.setOutgoing();
  if (le < (short)2) ISOException.throwIt( ISO7816.SW_WRONG_LENGTH );
  apdu.setOutgoingLength( (short)3 );

  // build response data in apdu.buffer[ 0.. outCount-1 ];
  buffer[0] = (byte)1; buffer[1] = (byte)2; buffer[3] = (byte)3;
  apdu.sendBytes ( (short)0 , (short)3 );
  // return good complete status 90 00
  }
 

See Also:
APDUException, ISOException

Field Summary
static byte PROTOCOL_T0
          ISO 7816 transport protocol type T=0
static byte PROTOCOL_T1
          ISO 7816 transport protocol type T=1
 
Method Summary
 byte[] getBuffer()
          Returns the APDU buffer byte array.
static short getInBlockSize()
          Returns the configured incoming block size.  In T=1 protocol, this corresponds to IFSC (information field size for ICC), the maximum size of incoming data blocks into the card.  In T=0 protocol, this method returns 1.
 byte getNAD()
          In T=1 protocol, this method returns the Node Address byte, NAD.  In T=0 protocol, this method returns 0.
static short getOutBlockSize()
          Returns the configured outgoing block size.  In T=1 protocol, this corresponds to IFSD (information field size for interface device), the maximum size of outgoing data blocks to the CAD.  In T=0 protocol, this method returns 258 (accounts for 2 status bytes).
static byte getProtocol()
          Returns the ISO 7816 transport protocol type, T=1 or T=0 in progress.
 short receiveBytes(short bOff)
          Gets as many data bytes as will fit without APDU buffer overflow, at the specified offset bOff.  Gets all the remaining bytes if they fit.
 void sendBytes(short bOff, short len)
          Sends len more bytes from APDU buffer at specified offset bOff.
 void sendBytesLong(byte[] outData, short bOff, short len)
          Sends len more bytes from outData byte array starting at specified offset bOff.
 short setIncomingAndReceive()
          This is the primary receive method.
 short setOutgoing()
          This method is used to set the data transfer direction to outbound and to obtain the expected length of response (Le).
 void setOutgoingAndSend(short bOff, short len)
          This is the "convenience" send method.
 void setOutgoingLength(short len)
          Sets the actual length of response data.
 short setOutgoingNoChaining()
          This method is used to set the data transfer direction to outbound without using BLOCK CHAINING(See ISO 7816-3/4) and to obtain the expected length of response (Le).
static void waitExtension()
          Requests additional processing time from CAD.
 
Methods inherited from class java.lang.Object
equals
 

Field Detail

PROTOCOL_T0

public static final byte PROTOCOL_T0
ISO 7816 transport protocol type T=0

See Also:
Constant Field Values

PROTOCOL_T1

public static final byte PROTOCOL_T1
ISO 7816 transport protocol type T=1

See Also:
Constant Field Values
Method Detail

getBuffer

public byte[] getBuffer()
Returns the APDU buffer byte array.

Notes:

Returns:
byte array containing the APDU buffer

getInBlockSize

public static short getInBlockSize()
Returns the configured incoming block size.  In T=1 protocol, this corresponds to IFSC (information field size for ICC), the maximum size of incoming data blocks into the card.  In T=0 protocol, this method returns 1. IFSC is defined in ISO 7816-3.

This information may be used to ensure that there is enough space remaining in the APDU buffer when receiveBytes() is invoked.

Notes:

Returns:
incoming block size setting.
See Also:
receiveBytes(short)

getOutBlockSize

public static short getOutBlockSize()
Returns the configured outgoing block size.  In T=1 protocol, this corresponds to IFSD (information field size for interface device), the maximum size of outgoing data blocks to the CAD.  In T=0 protocol, this method returns 258 (accounts for 2 status bytes). IFSD is defined in ISO 7816-3.

This information may be used prior to invoking the setOutgoingLength() method, to limit the length of outgoing messages when BLOCK CHAINING is not allowed.

Notes:

Returns:
outgoing block size setting.
See Also:
setOutgoingLength(short)

getProtocol

public static byte getProtocol()
Returns the ISO 7816 transport protocol type, T=1 or T=0 in progress.

Returns:
the protocol type in progress. One of PROTOCOL_T0, PROTOCOL_T1 listed above.

getNAD

public byte getNAD()
In T=1 protocol, this method returns the Node Address byte, NAD.  In T=0 protocol, this method returns 0. This may be used as additional information to maintain multiple contexts.

Returns:
NAD transport byte as defined in ISO 7816-3.

setOutgoing

public short setOutgoing()
                  throws APDUException
This method is used to set the data transfer direction to outbound and to obtain the expected length of response (Le).

Notes.

Returns:
Le, the expected length of response.
Throws:
APDUException - with the following reason codes:
  • APDUException.ILLEGAL_USE if this method or setOutgoingNoChaining() method already invoked.
  • APDUException.IO_ERROR on I/O error.

setOutgoingNoChaining

public short setOutgoingNoChaining()
                            throws APDUException
This method is used to set the data transfer direction to outbound without using BLOCK CHAINING(See ISO 7816-3/4) and to obtain the expected length of response (Le). This method should be used in place of the setOutgoing() method by applets which need to be compatible with legacy CAD/terminals which do not support ISO 7816-3/4 defined block chaining. See Java Card Runtime Environment (JCRE) Specification, section 8.4 for details.

Notes.

Returns:
Le, the expected length of response data.
Throws:
APDUException - with the following reason codes:
  • APDUException.ILLEGAL_USE if this method or setOutgoing() method already invoked.
  • APDUException.IO_ERROR on I/O error.

setOutgoingLength

public void setOutgoingLength(short len)
                       throws APDUException
Sets the actual length of response data. Default is 0.

Note:

Parameters:
len - the length of response data.
Throws:
APDUException - with the following reason codes:
  • APDUException.ILLEGAL_USE if setOutgoing() not called or this method already invoked.
  • APDUException.BAD_LENGTH if len is greater than 256 or if non BLOCK CHAINED data transfer is requested and len is greater than (IFSD-2), where IFSD is the Outgoing Block Size. The -2 accounts for the status bytes in T=1.
  • APDUException.IO_ERROR on I/O error.
See Also:
getOutBlockSize()

receiveBytes

public short receiveBytes(short bOff)
                   throws APDUException
Gets as many data bytes as will fit without APDU buffer overflow, at the specified offset bOff.  Gets all the remaining bytes if they fit.

Notes:

Parameters:
bOff - the offset into APDU buffer.
Returns:
number of bytes read. Returns 0 if no bytes are available.
Throws:
APDUException - with the following reason codes:
  • APDUException.ILLEGAL_USE if setIncomingAndReceive() not called or if setOutgoing() or setOutgoingNoChaining() previously invoked.
  • APDUException.BUFFER_BOUNDS if not enough buffer space for incoming block size.
  • APDUException.IO_ERROR on I/O error.
  • APDUException.T1_IFD_ABORT if T=1 protocol is in use and the CAD sends in an ABORT S-Block command to abort the data transfer.
See Also:
getInBlockSize()

setIncomingAndReceive

public short setIncomingAndReceive()
                            throws APDUException
This is the primary receive method. Calling this method indicates that this APDU has incoming data. This method gets as many bytes as will fit without buffer overflow in the APDU buffer following the header.  It gets all the incoming bytes if they fit.

Notes:

Returns:
number of bytes read. Returns 0 if no bytes are available.
Throws:
APDUException - with the following reason codes:
  • APDUException.ILLEGAL_USE if setIncomingAndReceive() already invoked or if setOutgoing() or setOutgoingNoChaining() previously invoked.
  • APDUException.IO_ERROR on I/O error.
  • APDUException.T1_IFD_ABORT if T=1 protocol is in use and the CAD sends in an ABORT S-Block command to abort the data transfer.

sendBytes

public void sendBytes(short bOff,
                      short len)
               throws APDUException
Sends len more bytes from APDU buffer at specified offset bOff.

If the last part of the response is being sent by the invocation of this method, the APDU buffer must not be altered. If the data is altered, incorrect output may be sent to the CAD. Requiring that the buffer not be altered allows the implementation to reduce protocol overhead by transmitting the last part of the response along with the status bytes.

Notes:

Parameters:
bOff - the offset into APDU buffer.
len - the length of the data in bytes to send.
Throws:
APDUException - with the following reason codes:
  • APDUException.ILLEGAL_USE if setOutgoingLen() not called or setOutgoingAndSend() previously invoked or response byte count exceeded or if APDUException.NO_T0_GETRESPONSE previously thrown.
  • APDUException.BUFFER_BOUNDS if the sum of bOff and len exceeds the buffer size.
  • APDUException.IO_ERROR on I/O error.
  • APDUException.NO_T0_GETRESPONSE if T=0 protocol is in use and the CAD does not respond to response status with GET RESPONSE command.
  • APDUException.T1_IFD_ABORT if T=1 protocol is in use and the CAD sends in an ABORT S-Block command to abort the data transfer.
See Also:
setOutgoing(), setOutgoingNoChaining()

sendBytesLong

public void sendBytesLong(byte[] outData,
                          short bOff,
                          short len)
                   throws APDUException
Sends len more bytes from outData byte array starting at specified offset bOff.

If the last of the response is being sent by the invocation of this method, the APDU buffer must not be altered. If the data is altered, incorrect output may be sent to the CAD. Requiring that the buffer not be altered allows the implementation to reduce protocol overhead by transmitting the last part of the response along with the status bytes.

The JCRE may use the APDU buffer to send data to the CAD.

Notes:

Parameters:
outData - the source data byte array.
bOff - the offset into OutData array.
len - the bytelength of the data to send.
Throws:
SecurityException - if the outData byte array is not accessible in the caller's context.
APDUException - with the following reason codes:
  • APDUException.ILLEGAL_USE if setOutgoingLen() not called or setOutgoingAndSend() previously invoked or response byte count exceeded or if APDUException.NO_T0_GETRESPONSE previously thrown.
  • APDUException.IO_ERROR on I/O error.
  • APDUException.NO_T0_GETRESPONSE if T=0 protocol is in use and CAD does not respond to response status with GET RESPONSE command.
  • APDUException.T1_IFD_ABORT if T=1 protocol is in use and the CAD sends in an ABORT S-Block command to abort the data transfer.
See Also:
setOutgoing(), setOutgoingNoChaining()

setOutgoingAndSend

public void setOutgoingAndSend(short bOff,
                               short len)
                        throws APDUException
This is the "convenience" send method. It provides for the most efficient way to send a short response which fits in the buffer and needs the least protocol overhead. This method is a combination of setOutgoing(), setOutgoingLength( len ) followed by sendBytes ( bOff, len ). In addition, once this method is invoked, sendBytes() and sendBytesLong() methods cannot be invoked and the APDU buffer must not be altered.

Sends len byte response from the APDU buffer at starting specified offset bOff.

Notes:

Parameters:
bOff - the offset into APDU buffer.
len - the bytelength of the data to send.
Throws:
APDUException - with the following reason codes:
  • APDUException.ILLEGAL_USE if setOutgoing() or setOutgoingAndSend() previously invoked or response byte count exceeded.
  • APDUException.IO_ERROR on I/O error.

waitExtension

public static void waitExtension()
                          throws APDUException
Requests additional processing time from CAD. The implementation should ensure that this method needs to be invoked only under unusual conditions requiring excessive processing times.

Notes:

Throws:
APDUException - with the following reason codes:
  • APDUException.ILLEGAL_USE if setOutgoingNoChaining() previously invoked.
  • APDUException.IO_ERROR on I/O error.


Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.