I wrote the following program to change the Historical Bytes in the ATR of my smartcard to, for example, 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
. I use GPSystem.setATRHistBytes()
to set the historical bytes.
Note that 0x00 0x00 ... 0x00
is not the actual value that I'm using for the historical bytes but I censored it. The actual value is an array of 15 bytes that is equal to the historical bytes of another exisitng card.
package org.globalplatform;
import javacard.framework.*;
import org.globalplatform.GPSystem;
public class TestPrj extends Applet {
public static final byte[] HIST_B= {(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
public static byte counter = (byte) 0x00;
public static void install(byte[] bArray, short bOffset, byte bLength) {
new TestPrj();
}
protected TestPrj() {
register();
}
public void process(APDU apdu) {
if (selectingApplet()) {
if (counter == 0x03) {
counter = (byte) (counter + 1);
boolean changed = GPSystem.setATRHistBytes(HIST_B, (short) 0, (byte) HIST_B.length);
if (changed) {
ISOException.throwIt((short) 0x9000);
} else {
ISOException.throwIt((short) 0x6400);
}
} else {
counter = (byte) (counter + 1);
}
}
ISOException.throwIt((short) counter);
}
}
After converting the above program to its CAP file and installing the applet with Default Selected
privilege (which is required to use GPSystem.setATRHistBytes()
), I still have problems with changing the historical bytes.
Based on the APDU responses that I receive, it seems that the setATRHistBytes()
method always returns false
indicating the the historical bytes are not updated.
Connect successful.
Download Cap begin...
Download Cap successful.
Install Applet begin...
Install Applet successful.
Send: 00 A4 04 00 06 01 02 03 04 05 01
Recv: 00 01
Time used: 22.000 ms
Send: 00 A4 04 00 06 01 02 03 04 05 01
Recv: 00 02
Time used: 23.000 ms
Send: 00 A4 04 00 06 01 02 03 04 05 01
Recv: 00 03
Time used: 24.000 ms
Send: 00 A4 04 00 06 01 02 03 04 05 01
Recv: 64 00
Time used: 15.000 ms
Send: 00 A4 04 00 06 01 02 03 04 05 01
Recv: 00 05
Time used: 15.000 ms
Note that 01 02 03 04 05 01
is my applet AID.
My card is JCOP v2.4.2 R3 and I tried to compile against both GP 2.2.1 v1.6 and GP 2.2 v1.4 APIs.
setATRHistBytes(byte[] baBuffer, short sOffset, byte bLength)
requires a global array passed as input buffer (baBuffer
). See the API documentation:
baBuffer
- the source byte array containing the ATR historical bytes. Must be a global array.
A global array is a special array that is managed by the Java Card runtime and accessible by all applets. During the invokation of the process()
applet lifecylce method, the only global buffer that you can expect to be available to your Java Card applet is the APDU buffer.
Therefore, you need to copy the contents of HIST_B
into the APDU buffer and then pass the APDU buffer into setATRHistBytes()
:
byte[] buffer = apdu.getBuffer();
Util.arrayCopyNonAtomic(HIST_B, (short)0, buffer, (short)0, (short)HIST_B.length);
boolean changed = GPSystem.setATRHistBytes(buffer, (short)0, (short)HIST_B.length);
来源:https://stackoverflow.com/questions/34390973/setatrhistbytes-method-always-returns-false