C H A P T E R  5

Using Extended APDU

The extended APDU feature in the Java Card Platform, v2.2.2, allows applet developers to take advantage of extended APDU functionality, as defined in the ISO 7816 specification. Extended APDU allows large amounts of data to be sent to the card, processed appropriately, and sent back to the terminal, in a more efficient way. Instead of having to re-issue multiple APDU messages to complete an operation requiring large volumes of data, and requiring the developer to code the application to keep a state across such multiple APDU commands, extended APDU allows applets to perform this function more efficiently with one large APDU exchange.

Extended APDU can be beneficial when dealing with large amounts of information. For example, applications such as signature verification, biometrics verification and image storage and retrieval could greatly benefit from this feature. Extended APDU implementations can easily be implemented if the underlying transport protocol is T=1, while applets developed for T=0 cards would need special logic and care to work correctly.


Extended APDU Nominal Cases

The ISO 7816-4:2005 specification defines an extended APDU as any APDU whose payload data, response data or expected data length exceeds the 256 byte limit. Therefore, the four traditional cases are redefined as follows:


Extended APDU Format

To express extended length, the APDU format has changed. The table below summarizes the format defined by ISO 7816-4:2005 for extended length APDU. Any APDU classified as extended must follow this format.


TABLE 5-1 Extended APDU Format

Field

Description

Number of Bytes

Command Header

Class byte CLA

1

Command Header

Instruction byte INS

1

Command Header

Parameter bytes P1- P2

2

LC Field

Absent for Nc = 0. Present for Nc > 0

0, 1, or 3

Data Field

Absent if Nc = 0, present if Nc >0

Nc

LE Field

Absent for Ne = 0, present for Ne > 0

0, 1, 2 or 3

Response Data

Absent if Nr = 0, present if Nr >0

Nr (max. Ne)

Response Status

Status bytes SW1 SW2

2

 

NOTATION

Nc = command data length

Ne = expected response data length

Nr = actual response data length

 


The encoding rules are defined as:

For LC:

For LE:

If LE is an extended field:


Extended APDU Limits

The Java Card platform supports extended APDUs with some limitations. Because the platform defines all of its mandatory API in terms of short data length, the values of LC and LE are limited to short positive values. That is, LC and LE have a range of 0..32,767. Lengths of 32,768 and beyond are not supported by the Java Card platform at this time.

javacardx.framework.ExtendedLength Interface

Not all Java Card applets can handle extended APDUs. Legacy applets should never encounter an extended APDU in the APDU buffer. Because of this, the Java Card API has added a tagging interface, javacardx.apdu.ExtendedLength, to signal that the applet implementing this interface is capable of processing, receiving and replying to extended APDU commands. The Java Card RE will not deliver extended APDU commands to applets not implementing this interface (it would throw an ISOException with reason code ISO7816.SW_WRONG_LENGTH in that case), nor would it allow applets to send reply data lengths greater than 256, if such an interface is not implemented by the applet.

The APDU buffer in Java Card technology applications will reflect the structure of the extended APDU as defined in ISO. In T=1, this representation is straightforward and precise; whereas in T=0, there need to be some adaptations for some cases.

Specifically, a case 2E APDU sent over T=0 transport will not show its extended LE value in the APDU buffer. Instead, a P3 value of '00' will always be transmitted, and interpreted as 32,767, if the applet implements ExtendedLength, or 256 if it does not. The Java Card RE analyzes the APDU type coming into the card and determines its type based on the rules defined in the ISO 7816-3 specification. Because case 2E commands look like case 2S commands in T=0, the Java Card RE is not able to distinguish this particular case.

Extensions To javacard.framework.APDU Class

Because LC in cases 3E and 4E can take a large value, the parameter is sent to the card as a three-byte quantity, in the format of 00 LCh LCl starting at ISO7816.OFFSET_LC. Two new API calls have been added to javacard.framework.APDU so that the applet developer will not be required to parse the APDU. The API calls allow the applet developer to get the value of LC and the data offset inside the APDU buffer without having to get them directly from that buffer, as was necessary before.

These two APIs allow applet developers to write applets without having to worry about parsing extended length in T=0 and T=1 implementations.

This API call returns the value of LC as expressed in the APDU, whether it is extended or not.

This API call returns the offset where the first byte of the APDU data segment is found.


Sending and Receiving Extended APDU Commands

To write an applet that takes advantage of extended length, follow these steps:

1. Implement the javacardx.apdu.ExtendedLength interface in your applet:


...

import javacard.framework.*;

import javacardx.apdu.ExtendedLength;

...

public MyApplet extends Applet implements

ExtendedLength {

...

}

 


2. Write your applet and Applet.process(..) method as you would with any other applets. For consistency, it is advisable that your process(..) code begin like the one below:


public void process(APDU apdu) {

byte[] buffer = apdu.getBuffer();

if (apdu.isISOInterindustryCLA()) {

if (this.selectingApplet()) {

return;

} else {

ISOException.throwIt (ISO7816.SW_CLA_NOT_SUPPORTED);

}

}

switch (buffer[ISO7816.OFFSET_INS]) {

case CHOICE_1:

...

return;

case CHOICE_2:

...

...

default:

ISOException.throwIt (ISO7816.SW_INS_NOT_SUPPORTED);

}

}


3. For cases 3S, 4S, 3E and 4E, write the method to handle incoming data. Do it relying on API extensions so that your applet properly handles extended, as well as non-extended, cases.


void receiveData(APDU apdu) {

byte[] buffer = apdu.getBuffer();

short LC = apdu.getIncomingLength();

short recvLen = apdu.setIncomingAndreceive();

short dataOffset = apdu.getOffsetCdata();

while (recvLen > 0) {

...

[process data in buffer[dataOffset]...]

...

recvLen = apdu.receiveBytes(dataOffset);

}

// Done

}


4. For case 2S, 2E, write the method handling data output. A method could look something like this:


void sendData(APDU apdu) {

byte[] buffer = apdu.getBuffer();

short LE = apdu.setOutgoing();

short toSend = ...

if (LE != toSend) {

apdu.setOutgoingLength(toSend);

}

while (toSend > 0) {

...

[prepare data to send in APDU buffer]

...

apdu.sendBytes(dataOffset, sentLen);

toSend -= sentLen;

}

// Done

}