问题
I'm new to this field, so forgive me if my question is naive.
I want to issue a Java card which has an auto-select applet and almost all APDUs are going to get handled in this applet. I need this applet to send data to CAD not using the usual format in Java card standard (i.e. without sending 0x61 0xbytesToRead
and waiting for 0x00 0xc0
).
For example I'd like to send 0x23
bytes in answer to 0xA0A40000027F20
which is almost a SELECT command but with wrong first byte!
So is this possible to do this? and if it's possible please tell me how.
Thanks.
回答1:
Yes, it is possible. To aim your goal, you have two steps as below :
- You must make your applet default selected.
- You must return some data on reception of this command, and/or reception of SELECT APDU command.
For the first step, as it is answered here:
It depends on cards - not all of them seem to support making an applet default after installation. But you can use the open source GlobalPlatform tool for Java that has --make-default option:
java -jar gp.jar --make-default A000100201100001
IIRC JCOP was one of the cards that actually supported it.
And for the second step, as answered here :
I guess you do the "good practice" of "if selectingApplet() then return" in process? You need to process the incoming APDU instead of simple return. You can return data to select the normal way, but be careful to return 0x9000 if the select was successful.
It must be looked like this:
public void process(APDU apdu)
{
byte[] buf = apdu.getBuffer();
if (selectingApplet())
{
//send the data in buffer return;
}
}
Update:
To answer your comment below this answer :
I wrote the below program :
package test;
import javacard.framework.APDU;
import javacard.framework.ISO7816;
import javacard.framework.Applet;
import javacard.framework.ISOException;
import javacard.framework.Util;
public class Test extends Applet {
public static final byte[] res = { (byte) 0x00, (byte) 0x00, (byte) 0x3B,
(byte) 0xAD, (byte) 0x3F, (byte) 0x00, (byte) 0x01, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x16,
(byte) 0xB3, (byte) 0x03, (byte) 0x06, (byte) 0x04, (byte) 0x00,
(byte) 0x83, (byte) 0x8A, (byte) 0x83, (byte) 0x8A, (byte) 0x00,
(byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x3B, (byte) 0xAD,
(byte) 0x00, (byte) 0x00, (byte) 0x3B, (byte) 0xAD, (byte) 0x2F,
(byte) 0x06, (byte) 0x02 };
public static void install(byte[] bArray, short bOffset, byte bLength) {
new test.Test()
.register(bArray, (short) (bOffset + 1), bArray[bOffset]);
}
public void process(APDU apdu) {
if (selectingApplet()) {
return;
}
byte[] buf = apdu.getBuffer();
if (buf[ISO7816.OFFSET_CLA] == (byte)0xA0 && buf[ISO7816.OFFSET_INS] == (byte) 0xA4 && buf[ISO7816.OFFSET_P1] == (byte) 0x00&& buf[ISO7816.OFFSET_P2] == (byte) 0x00
&& buf[ISO7816.OFFSET_LC] == (byte) 0x02 && buf[ISO7816.OFFSET_LC + 1] == (byte) 0x7F && buf[ISO7816.OFFSET_LC + 2] == (byte) 0x20) {
ISOException.throwIt((short) 0x9F23);
} else if (buf[ISO7816.OFFSET_CLA] == (byte) 0xA0 && buf[ISO7816.OFFSET_INS] == (byte) 0xC0 && buf[ISO7816.OFFSET_P1] == (byte) 0x00
&& buf[ISO7816.OFFSET_P2] == (byte) 0x00 && buf[ISO7816.OFFSET_P2+1] == (byte) 0x23 ) {
Util.arrayCopyNonAtomic(res, (short) 0, buf, (short) 0, (short) 35);
apdu.setOutgoingAndSend((short) 0, (short) 35);
} else {
ISOException.throwIt((short) 0x9090);
}
}
}
Then I installed it as default selected applet :
CommandLine> gp -install e:\soq.cap --default
CommandLine>
And then I send the APDU commands to it :
CommandLine> OSC.exe -s A0A40000027F20 -s a0c0000023
Using reader with a card: ACS CCID USB Reader 0
Sending: A0 A4 00 00 02 7F 20
Received (SW1=0x9F, SW2=0x23)
Sending: A0 C0 00 00 23
Received (SW1=0x90, SW2=0x00):
00 00 3B AD 3F 00 01 00 00 00 00 00 16 B3 03 06 ..;.?...........
04 00 83 8A 83 8A 00 03 00 00 3B AD 00 00 3B AD ..........;...;.
2F 06 02 /..
It seems that it works as you wanted.
来源:https://stackoverflow.com/questions/31409177/java-card-to-send-data-without-get-data-apdu