1
votes

I'm trying to set the CommandAPDU buffer with a byte array. However, if the length is >7, it throws the following error:

Exception in thread "main" java.lang.IllegalArgumentException: Invalid APDU: length=8, b1=1 at javax.smartcardio.CommandAPDU.parse(CommandAPDU.java:318) at javax.smartcardio.CommandAPDU.(CommandAPDU.java:98) at terminal.Main.main(Main.java:78)

My code:

byte terminal = 0x00;
byte instruction = 0x01;
byte [] msg = {0x01,0x00,0x01,0x00};
byte [] fullmsg = new byte[msg.length + 4];
System.arraycopy(new byte []{terminal}, 0, fullmsg, 0, 1);
System.arraycopy(new byte [] {instruction}, 0, fullmsg, 1, 1);
System.arraycopy(new byte [] {0,0}, 0, fullmsg, 2, 2);
System.arraycopy(msg, 0, fullmsg, 4, msg.length);
CommandAPDU cmdapdu = new CommandAPDU(fullmsg);

Can someone help me out?

1
That code is hardly readable. vlp already posted a perfect answer for this, but if you ever write code like that then 1. use an offset variable (and ++ or += 2) 2. use constants for specific byte values (also for use within vlp's answer) and 3. please write a comment on what the code line is doing, because currently it is not easy to extract any meaning from the code. And the code failed because you forgot to write the fifth Lc byte which encodes the length of the command data, known as Nc. - Maarten Bodewes
Oh, and the byte before the INStruction byte is called the CLAss byte, not the terminal byte. - Maarten Bodewes

1 Answers

3
votes

Consider using CommandAPDU(int cla, int ins, int p1, int p2, byte[] data) (if you do not expect any data in return from card -- i.e. command is ISO-7816 case 3) or CommandAPDU(int cla, int ins, int p1, int p2, byte[] data, int ne) (if you expect some data in return from card -- i.e. command is ISO-7816 case 4) to create your CommandAPDU object.

See ISO 7816-3, section 12.1 "Application protocol data units" for further details on Command APDU formats (partially available here).

E.g.:

CommandAPDU cmdapdu = new CommandAPDU(terminal, instruction, 0, 0, msg);

or (feel free to replace 256 with any other expected length of response data):

CommandAPDU cmdapdu = new CommandAPDU(terminal, instruction, 0, 0, msg, 256);

Good luck!