I completed an applet compatible with GP 2.1.1 and Java Card 2.2.1. I also have two kinds of cards to test my applet.
* When I do the test on the first kind of card, everything goes well.
** For the second kind of card,the cap file can be uploaded successfully.And the applet also works well as expected.
But every APDU I send returns 6F00.
For example, first APDU I need to send to the applet is an Initialize Update :
Command:
80500000081810D6E7AEFA77F700
Response:
000050540000001900020202002FDC5D12A22CB7A11051C5D96DA298
(6F00)
Although it returns 6F00, it works fine.
I continue to send an Ext Auth APDU, it still works as well.
What can be the cause for this odd thing?
The below is my code.
Code: Select all
import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.JCSystem;
import javacard.framework.Util;
import org.globalplatform.*;
public class SecureChannelTest extends Applet {
final static byte OWNER_CLA = (byte)0x84;
final static byte CLA_SPECIFIC_UNSEC = (byte)0x80;
final static byte INS_INIT_UPDATE = (byte)0x50;
final static byte INS_EXT_AUTH = (byte)0x82;
final static byte INS_UNWRAP_APDU = (byte)0xB4;
final static byte INS_GETSECURELEVEL_APDU = (byte)0x1A;
final static byte INS_RETURN_BUFFER = (byte)0xBB;
final static short MAX_BUFF = (short)255;
final static byte SEC_LEVEL_AUTH = (byte)0x80;
final static byte SEC_LEVEL_C_DEC = (byte)0x02;
final static byte SEC_LEVEL_C_MAC = (byte)0x01;
final static byte SEC_LEVEL_R_ENC = (byte)0x20;
final static byte SEC_LEVEL_R_MAC = (byte)0x10;
final static byte SEC_LEVEL_NO_SECURITY = (byte)0x00;
private SecureChannel secCh;
byte[] sendData;
short DataLength = 0;
private SecureChannelTest() {
this.sendData = new byte[MAX_BUFF];
register();
}
public static void install(byte bArray[], short bOffset, byte bLength)
throws ISOException {
new SecureChannelTest();
}
public boolean select()
{
this.secCh = GPSystem.getSecureChannel();
if(this.secCh == null)
{
return false;
}
return true;
}
public void process(APDU apdu) throws ISOException
{
if (selectingApplet())
{
return;
}
byte[] apdu_buffer = apdu.getBuffer();
byte secLevel = (byte)0;
switch (apdu_buffer[ISO7816.OFFSET_CLA])
{
case OWNER_CLA:
case CLA_SPECIFIC_UNSEC:
if( (apdu_buffer[ISO7816.OFFSET_INS]==INS_INIT_UPDATE) ||
(apdu_buffer[ISO7816.OFFSET_INS]==INS_EXT_AUTH))
{
apdu.setIncomingAndReceive();
short lout = this.secCh.processSecurity(apdu);
secLevel = this.secCh.getSecurityLevel();
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA,lout);
break;
}
secLevel = secCh.getSecurityLevel();
if( ((secLevel & SEC_LEVEL_AUTH) != (byte)0) ||
((secLevel & SEC_LEVEL_C_MAC) != (byte)0) ||
((secLevel & SEC_LEVEL_R_MAC) != (byte)0) )
{
switch(secLevel)
{
case (SEC_LEVEL_AUTH):
break;
case (SEC_LEVEL_AUTH | SEC_LEVEL_C_MAC):
break;
case (SEC_LEVEL_AUTH | SEC_LEVEL_C_MAC | SEC_LEVEL_C_DEC):
break;
case (SEC_LEVEL_AUTH | SEC_LEVEL_R_MAC):
break;
case (SEC_LEVEL_AUTH | SEC_LEVEL_R_MAC | SEC_LEVEL_R_ENC):
break;
default: ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
}
switch(apdu_buffer[ISO7816.OFFSET_INS])
{
case INS_RETURN_BUFFER:
apdu.setIncomingAndReceive();
byte[] Buffer = new byte[(byte)10];
Buffer[0] = (byte)0x00;
Buffer[1] = (byte)0xBB;
Buffer[2] = (byte)0xCC;
Buffer[3] = (byte)0xDD;
Buffer[4] = (byte)0xEE;
Buffer[5] = (byte)0xFF;
Buffer[6] = (byte)0x00;
Buffer[7] = (byte)0x11;
Buffer[8] = (byte)0x66;
Buffer[9] = (byte)0x55;
apdu.setOutgoing();
apdu.setOutgoingLength((short)Buffer.length);
apdu.sendBytesLong(Buffer, (short)0, (short)Buffer.length);
Buffer = null;
JCSystem.requestObjectDeletion();
break;
case INS_GETSECURELEVEL_APDU:
sendSecurityLevel(apdu);
break;
default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
else
{
ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
}
break;
default: ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
}
apdu_buffer = null;
JCSystem.requestObjectDeletion();
}
private void sendSecurityLevel(APDU apdu)
{
apdu.setIncomingAndReceive();
this.sendData[0] = (byte)secCh.getSecurityLevel();
apdu.setOutgoing();
apdu.setOutgoingLength((short)1);
apdu.sendBytesLong(this.sendData, (short)0, (short)1);
}
}