[英]Cannot delete Java Card applet
I am quite new to Java Card but after some reading, my first Applet is working quite well.....until today. 我是Java Card的新手,但经过一些阅读,我的第一个Applet工作得很好.....直到今天。 I refactored a bit and inserted an OwnerPIN object to my Applet.
我重构了一下并将一个OwnerPIN对象插入到我的Applet中。 And now I can write the Applet once, but the second time, the deletion does not work anymore.
现在我可以编写Applet一次,但第二次,删除不再起作用了。 Here is my output:
这是我的输出:
Java Card 2.2.2 Class File Converter, Version 1.3
Copyright 2005 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms.
mode_201
gemXpressoPro
enable_timer
establish_context
command time: 16 ms
card_connect
command time: 187 ms
select -AID A000000018434D00
command time: 78 ms
open_sc -security 1 -keyind 0 -keyver 0 -key 47454d5850524553534f53414d504c45 -keyDerivation visa2
command time: 328 ms
delete -AID 0102030405060708090000
delete() returns 0x80206985 (6985: Command not allowed - Conditions of use not satisfied.)
command time: 31 ms
delete -AID 01020304050607080900
delete() returns 0x80206985 (6985: Command not allowed - Conditions of use not satisfied.)
command time: 47 ms
get_status -element e0
List of applets (AID state privileges)
a000000018434d00 1 9e
a0000000620001 1 0
a0000000620002 1 0
a0000000620003 1 0
a0000000620101 1 0
a000000062010101 1 0
a0000000620102 1 0
a0000000620201 1 0
a0000000620209 1 0
a0000000620202 1 0
a000000018100109 1 0
a00000001810010b 1 0
a00000001810010a 1 0
a0000000030000 1 0
a000000018100106 1 0
a000000018100201 1 0
a000000018100101 1 0
a00000015100 1 0
a000000018100108 1 0
a0000000181001ff 1 0
a000000018100501 1 0
a000000018100502 1 0
a000000018100401 1 0
5365637572697479 1 0
a0000000035350 1 0
01020304050607080900 1 0
0102030405060708090000 7 0
command time: 187 ms
install -file mycap.cap -sdAID A000000018434D00 -nvCodeLimit 4096 -instParam 2265
install_for_load() returns 0x80206985 (6985: Command not allowed - Conditions of use not satisfied.)
update As requested, parts of my code: 更新根据要求,我的部分代码:
public class MyApplet extends Applet
{
private static final byte MY_CLA = (byte)0xB0;
...
private final static byte VERIFY_INS = (byte)0x40;
...
private final static byte NEED_VERIFICATION_INS = (byte)0x47;
private final static byte GET_INSTALL_PARAMS_INS = (byte)0x50;
private final static byte GET_REMAINING_PIN_TRIES_INS = (byte)0x60;
private final static byte PIN_TRY_LIMIT = (byte)0x03;
private final static byte MAX_PIN_SIZE = (byte)0x08;
// signal that the PIN verification failed
private final static short SW_VERIFICATION_FAILED = 0x6300;
private final static short SW_PIN_VERIFICATION_REQUIRED = 0x6301;
...
private static byte[] testdata;
private OwnerPIN m_pin;
private byte[] m_array;
private short m_offset;
private byte m_length;
private MyApplet(byte[] bArray, short bOffset, byte bLength)
{
...
m_pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
// m_array = bArray;
// m_offset = bOffset;
// m_length = bLength;
register();
}
public boolean select()
{
if (m_pin.getTriesRemaining() == 0)
{
return false;
}
return true;
}
public void deselect()
{
m_pin.resetAndUnblock();
}
private void adminRest()
{
m_pin.resetAndUnblock();
return;
}
private void getInstallParams(APDU apdu)
{
try
{
byte[] buffer = apdu.getBuffer();
// inform the JCRE that the applet has data to return
short le = apdu.setOutgoing();
// set the actual number of the outgoing data bytes
apdu.setOutgoingLength(((short)testdata.length));
apdu.sendBytesLong(testdata, (short)0, (short)testdata.length);
}
catch (APDUException e)
{
// TODO Auto-generated catch block
}
catch (TransactionException e)
{
// TODO Auto-generated catch block
}
catch (ArrayIndexOutOfBoundsException e)
{
// TODO Auto-generated catch block
}
catch (NullPointerException e)
{
// TODO Auto-generated catch block
}
}
/**
* Get number of remaining pin tries
*
* @param apdu
*/
private void getPinTriesRemaining(APDU apdu)
{
try
{
byte[] buffer = apdu.getBuffer();
// inform the JCRE that the applet has data to return
apdu.setOutgoing();
// set the actual number of the outgoing data bytes
apdu.setOutgoingLength((byte)2);
// write the PinTriesRemaining into the APDU buffer at the offset 0
Util.setShort(buffer, (short)0, m_pin.getTriesRemaining());
// send the 2-byte balance at the offset
// 0 in the apdu buffer
apdu.sendBytes((short)0, (short)2);
}
catch (APDUException e)
{
// TODO Auto-generated catch block
}
catch (TransactionException e)
{
// TODO Auto-generated catch block
}
catch (ArrayIndexOutOfBoundsException e)
{
// TODO Auto-generated catch block
}
catch (NullPointerException e)
{
// TODO Auto-generated catch block
}
} // end of getPinTriesRemaining method
/**
* Verification method to verify the PIN
*
* @param apdu
*/
private void verify(APDU apdu)
{
byte[] buffer = apdu.getBuffer();
// receive the PIN data for validation.
byte byteRead = (byte)(apdu.setIncomingAndReceive());
// check pin
// the PIN data is read into the APDU buffer
// starting at the offset ISO7816.OFFSET_CDATA
// the PIN data length = byteRead
if (!m_pin.check(buffer, ISO7816.OFFSET_CDATA, byteRead))
{
ISOException.throwIt(SW_VERIFICATION_FAILED);
}
} // end of verify method
/**
* Installs the applet.
*
* @param bArray array with installation parameters.
* @param bOffset offset into array.
* @param bLength the length of the parameters.
*/
public static void install(byte[] bArray, short bOffset, byte bLength)
{
testdata = new byte[bLength];
Util.arrayCopy(bArray, (short)0, testdata, (short)0, bLength);
new MyApplet(bArray, bOffset, bLength);
}
/**
* Processes an incoming APDU.
*
* @param apdu the APDU.
*/
public void process(APDU apdu)
{
byte l_transferredBuffer[] = apdu.getBuffer();
// Get the CLA; mask out the logical-channel info.
l_transferredBuffer[ISO7816.OFFSET_CLA] = (byte)(l_transferredBuffer[ISO7816.OFFSET_CLA] & (byte)0xFC);
if ((l_transferredBuffer[ISO7816.OFFSET_CLA] == 0) && (l_transferredBuffer[ISO7816.OFFSET_INS] == (byte)(0xA4)))
{
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
}
if (l_transferredBuffer[ISO7816.OFFSET_CLA] != MY_CLA)
{
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
}
byte l_ins = l_transferredBuffer[ISO7816.OFFSET_INS];
...
else if (l_ins == VERIFY_INS)
{
verify(apdu);
}
...
else if (l_ins == NEED_VERIFICATION_INS)
{
isNeedVerification(apdu, l_transferredBuffer);
}
else if (l_ins == GET_INSTALL_PARAMS_INS)
{
getInstallParams(apdu);
}
else if (l_ins == GET_REMAINING_PIN_TRIES_INS)
{
getPinTriesRemaining(apdu);
}
else
{
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
private void isNeedVerification(APDU apdu, byte[] buffer)
{
// The structure for the response request is
// ---------------------
// | response |
// | 1 byte |
// ---------------------
getRequest(apdu, buffer);
byte[] l_needVerificationResponse = new byte[1];
boolean l_validated = m_pin.isValidated();
if (l_validated)
{
l_needVerificationResponse[0] = 1;
}
else
{
l_needVerificationResponse[0] = 0;
}
apdu.setOutgoing();
apdu.setOutgoingLength((short)l_needVerificationResponse.length);
apdu.sendBytesLong(l_needVerificationResponse, (short)0, (short)l_needVerificationResponse.length);
}
private byte[] getRequest(APDU apdu, byte[] transferredBuffer)
{
short l_setIncomingAndReceive = apdu.setIncomingAndReceive();
byte[] request = new byte[l_setIncomingAndReceive];
for (short i = 0; i < request.length; i++)
{
short l_j = (short)(ISO7816.OFFSET_CDATA + i);
request[i] = transferredBuffer[l_j];
}
return request;
}
...
}
Is my card blocked? 我的卡被封了吗? I can see that my AID runs in state 7...what does that mean.
我可以看到我的AID在状态7中运行......这是什么意思。 Is it connected to my OwnerPIN object?
它是否连接到我的OwnerPIN对象?
Thanks for your help! 谢谢你的帮助! Jan
一月
The problematic line is this one: 问题是这一行:
private static byte[] testdata;
Remember, static
references to persistent objects are EVIL AND DANGEROUS . 请记住,对持久对象的
static
引用是邪恶的和危险的 。 They are always there, even after the Applet
instance is uninstalled and garbage collected. 即使在卸载
Applet
实例并收集垃圾后,它们也始终存在。 That is why the referenced object (byte array in your case) is never garbage collected, the persistent memory is never released and thus the deletion command fails. 这就是为什么引用的对象(在你的情况下为字节数组)永远不会被垃圾收集,持久性内存永远不会释放,因此删除命令失败。
If you can avoid using static
references, do so . 如果可以避免使用
static
引用, 请执行此操作 。
If you cannot avoid it, use AppletEvent
interface: 如果你无法避免它,请使用
AppletEvent
接口:
public final class MyApplet extends Applet implements AppletEvent {
private static byte[] testdata;
...
//This method is called in the moment of uninstallation
public final void uninstall() {
testData = null; //release the reference --> testData can be GC
}
...
}
I installed your applet on two different JavaCards and then I deleted it and installed it again and again successfully. 我在两个不同的JavaCards上安装了你的applet,然后我将其删除并再次成功安装。
First of all please download the GlobalPlatformPro tool. 首先,请下载GlobalPlatformPro工具。 (It's free and if you are working in Windows platform, then
gp.exe
is enough for your case.) (它是免费的,如果您在Windows平台上工作,那么
gp.exe
足以满足您的需求。)
After downloading try these commands in the command-line: 下载后,在命令行中尝试以下命令:
List you installed applets and their packages AID: 列出你安装的applet及其包AID:
G:\BasicTestTools\SmartCardTools>gp -key 404142434445464748494a4b4c4d4e4f -list
AID: A000000151000000 (|....Q...|)
ISD OP_READY: Security Domain, Card lock, Card terminate, Default selected, CVM (PIN) management
AID: 010203040503 (|......|)
App SELECTABLE: (none)
AID: A0000001515350 (|....QSP|)
ExM LOADED: (none)
A000000151535041 (|....QSPA|)
AID: 0102030405 (|.....|)
ExM LOADED: (none)
010203040503 (|......|)
Note that in the above output, those AIDs that are marked with App
, are applets and those AIDs that are marked with ExM
are Executable Modules (Packages). 请注意,在上面的输出中,那些用
App
标记的AID是applet,而那些用ExM
标记的ExM
是可执行模块 (Packages)。
The 0102030405
and 010203040503
in the results are Pack AID and App AID of your program in my card. 结果中的
0102030405
和010203040503
是我的卡中程序的Pack AID和App AID。
Deleting the package by alone, without deleting its applet: 单独删除包,而不删除其applet:
If I try to delete the package without deleting its applet, then it fails and I receive the same error that you receive: 如果我尝试删除包而不删除其applet,则它会失败并且我收到您收到的相同错误:
G:\BasicTestTools\SmartCardTools>gp -key 404142434445464748494a4b4c4d4e4f -delete 0102030405
Could not delete AID: 0102030405
TIP: Maybe try with --deletedeps
pro.javacard.gp.GPException: Deletion failed SW: 6985
at pro.javacard.gp.GlobalPlatform.check(GlobalPlatform.java:1092)
at pro.javacard.gp.GlobalPlatform.deleteAID(GlobalPlatform.java:867)
at pro.javacard.gp.GPTool.main(GPTool.java:390)
There are two ways to delete it: 有两种方法可以删除它:
Deleting the package and the applet simultaneously: 同时删除包和applet:
I choose the second solution (a parameter -deletedeps
added to the delete command): 我选择第二个解决方案(一个参数
-deletedeps
添加到delete命令):
G:\BasicTestTools\SmartCardTools>gp -key 404142434445464748494a4b4c4d4e4f -delete 0102030405 -deletedeps
G:\BasicTestTools\SmartCardTools>gp -key 404142434445464748494a4b4c4d4e4f -list
AID: A000000151000000 (|....Q...|)
ISD OP_READY: Security Domain, Card lock, Card terminate, Default selected, CVM (PIN) management
AID: A0000001515350 (|....QSP|)
ExM LOADED: (none)
A000000151535041 (|....QSPA|)
Installing the same applet with the same AIDs for the Package and the Applet again: 再次使用相同的AID为Package和Applet安装相同的applet:
As you see, your package and the applet are deleted. 如您所见,您的包和小程序将被删除。 Now I install it again:
现在我再次安装它:
G:\BasicTestTools\SmartCardTools>gp -key 404142434445464748494a4b4c4d4e4f -install C:\NetBeansProjects\test2\dist\test2.cap
G:\BasicTestTools\SmartCardTools>gp -key 404142434445464748494a4b4c4d4e4f -list
AID: A000000151000000 (|....Q...|)
ISD OP_READY: Security Domain, Card lock, Card terminate, Default selected, CVM (PIN) management
AID: 010203040503 (|......|)
App SELECTABLE: (none)
AID: A0000001515350 (|....QSP|)
ExM LOADED: (none)
A000000151535041 (|....QSPA|)
AID: 0102030405 (|.....|)
ExM LOADED: (none)
010203040503 (|......|)
Well, As you see the applet installed successfully again. 好吧,正如您看到applet再次成功安装。
Note that you must replace my card's authentication keys with your card's authentication keys(I mean replace 404142...4f
with your card's keys) 请注意,您必须使用卡的身份验证密钥替换我的卡的身份验证密钥(我的意思是用您的卡的密钥替换
404142...4f
)
Anyway, if in the first step (Listing installed applets) you faced with the 0x6985
error, that means your keys are not correct. 无论如何,如果在第一步(列出已安装的applet)中遇到
0x6985
错误,则表示您的密钥不正确。 For example if I put a random number for the key
parameter in the command the I will face this result: 例如,如果我在命令中为
key
参数添加一个随机数,我将面对这个结果:
G:\BasicTestTools\SmartCardTools>gp -key 00112233445566778899aabbccddeeff -list
pro.javacard.gp.GPException: STRICT WARNING: Card cryptogram invalid!
Card: 7F9CFF3D61110EF2
Host: 9EE2CDBF4A088053
!!! DO NOT RE-TRY THE SAME COMMAND/KEYS OR YOU MAY BRICK YOUR CARD !!!
at pro.javacard.gp.GlobalPlatform.printStrictWarning(GlobalPlatform.java:184)
at pro.javacard.gp.GlobalPlatform.openSecureChannel(GlobalPlatform.java:515)
at pro.javacard.gp.GPTool.main(GPTool.java:371)
And as it indicate in the output, you have limited tries for the value of key
. 正如它在输出中指出的那样,你对
key
的值的尝试有限。 Typically after 10 wrong tries, your card will be locked and the lock life cycle is irreversible. 通常在10次错误尝试后,您的卡将被锁定并且锁定生命周期不可逆转。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.