3
votes

I wrote a Java Card applet that saves some data into the APDU buffer at offset ISO7816.OFFSET_CDATA and sends those bytes as a response.

Util.arrayCopy(Input_Data, (short)0, buffer, (short) ISO7816.OFFSET_CDATA, (short)Datalength);
apdu.setOutgoing();
apdu.setOutgoingLength((short)(DataLength) );

apdu.sendBytesLong(buffer, ISO7816.OFFSET_CDATA, (short)(DataLength));

I tested this in a simulator without any problem. But when I test this on a real smart card (Java Card v2.2.1 manufactured by Gemalto), I get the status word 0x6180 as response.

My command APDU is 00 40 00 00 80 Data, where data has a length of 128 bytes, so I have 4+128 bytes in the buffer and (260-(4+128)) byte is null.

1

1 Answers

6
votes

Your simulator probably uses T=1 transport protocol, but your real card does not. It uses T=0 protocol, which means it can either receive data, or send data in a single APDU.

Status word 0x6180 indicates there are 0x80 bytes to receive from the card. Generally, 61XX means XX bytes to receive.

How to receive them? Well, there is a special APDU command called GET RESPONSE. You should call it each time you get 61XX status word. Use XX as the Le byte of your GET RESPONSE APDU

APDU -> 61 XX
00 C0 00 00 XX -> your data 90 00

A few other notes on your code:

  • Datalength vs DataLength?
  • Copy your output data to 0 instead of ISO7816.OFFSET_CDATA
  • Why do you cast DataLength to short each time? Is it short? Do not cast then. Is it byte? You cast it in a wrong way then, because unsigned byte value > 0x80 will be cast to a negative short. The correct cast from an unsigned byte to a short is (short) (DataLength & 0xFF)
  • Use setOutgoingAndSend whenever you can. It is much simpler.
  • Use arrayCopyNonAtomic instead of arrayCopy whenever you are not copying to a persistent array. Performance of arrayCopyNonAtomic is much better.