ISOExceptions
Hi all, can anyone please help me with a problem I've encountered with my applet. I've been attempting to write some exception handling, simple enough you'd think?
Anyway within my method(for retrieving a byte array from my card), I check to ensure that the array has been initialised. If the field isn't initialised I would like to return an ISOException with my own defined informative status word, SW(). From what I've seen this can be performed by testing the condition and then invoking ISOException.throwIt(reason).
However when this is attempted it causes CREF to crash with an invalid page fault.
The only way I've seen to prevent this is to utilise a try-catch statement but then the only response I'm getting is the 6F00, undefined error message, which isn't very useful.
Any response would be appreciated, thanks
Tony
Hello!
Can you Send the Detail code so that I can tell you where you are going wrong.This can help me to solve it in a better way.
Neelesh
Similar Messages
-
Unable to delete applet.....
Hi all,
I am unable to delete one applet which I have loaded in the card.
There are 2 applets, one is purse and other is loyalty. And am using shareable interface in which loyalty is the server and purse is the client. I can delete the purse applet but i can't delete the loyalty from the card.
Here is my code : There are in all 3 codes, one is purse, second is loyalty code and third is the shareable interface code. Can some one look at the code and tell me what's wrong in this programs.
package com.gemplus.examples.loyalty;
import javacard.framework.*;
import visa.openplatform.*;
public class Loyalty extends javacard.framework.Applet implements TestInterface
static byte points ;
protected Loyalty(byte[] buffer, short offset, byte length)
// data offset is used for application specific parameter.
// initialization with default offset (AID offset).
short dataOffset = offset;
if(length > 9) {
// Install parameter detail. Compliant with OP 2.0.1.
// | size | content
// |------|---------------------------
// | 1 | [AID_Length]
// | 5-16 | [AID_Bytes]
// | 1 | [Privilege_Length]
// | 1-n | [Privilege_Bytes] (normally 1Byte)
// | 1 | [Application_Proprietary_Length]
// | 0-m | [Application_Proprietary_Bytes]
// shift to privilege offset
dataOffset += (short)(1 + buffer[offset]);
// finally shift to Application specific offset
dataOffset += (short)(1 + buffer[dataOffset]);
// checks wrong data length
if(buffer[dataOffset] != 4)
// return received proprietary data length in the reason
ISOException.throwIt((short)(ISO7816.SW_WRONG_LENGTH + offset + length - dataOffset));
// go to proprietary data
dataOffset++;
// points = 0;
// register this instance
register(buffer, (short)(offset + 1), (byte)buffer[offset]);
* Method installing the applet.
* @param bArray the array constaining installation parameters
* @param bOffset the starting offset in bArray
* @param bLength the length in bytes of the data parameter in bArray
public static void install(byte[] bArray, short bOffset, byte bLength) throws ISOException
/* applet instance creation */
new Loyalty (bArray, bOffset, (byte)bLength);
* Select method returning true if applet selection is supported.
* @return boolean status of selection.
public boolean select()
/* return status of selection */
return true;
* Deselect method.
public void deselect()
return;
public void process(APDU apdu) throws ISOException
// check valid Applet state
if(OPSystem.getCardContentState() == OPSystem.APPLET_BLOCKED)
ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
apdu.setIncomingAndReceive();
byte[] apduBuffer = apdu.getBuffer();
// writes the balance into the APDU buffer after the APDU command part
creditPoints((byte)0x00);
apduBuffer[5] = (byte)(points >> 8) ;
apduBuffer[6] = (byte)points ;
// sends the APDU response
// switches to output mode
apdu.setOutgoing() ;
// 2 bytes to return
apdu.setOutgoingLength((short)2) ;
// offset and length of bytes to return in the APDU buffer
apdu.sendBytes((short)5, (short)2) ;
public void creditPoints(byte pTobeCredited)
points += pTobeCredited;
public Shareable getShareableInterfaceObject(AID client, byte param){
if(param != (byte)0x00)
return null;
return (this);
second code is :
package com.gemplus.examples.oppurse;
* Imported packages
import javacard.framework.*;
import visa.openplatform.*;
import com.gemplus.examples.loyalty.*;
public class OPPurse extends javacard.framework.Applet
// the APDU constants for all the commands.
private final static byte INS_GET_BALANCE = (byte)0x30 ;
private final static byte INS_DEBIT = (byte)0x31 ;
private final static byte INS_CREDIT = (byte)0x32 ;
private final static byte INS_VERIFY_PIN = (byte)0x33 ;
private final static byte INS_SET_NAME = (byte)0x34 ;
private final static byte INS_GET_NAME = (byte)0x35 ;
// the OP/VOP specific instruction set for mutual authentication
private final static byte CLA_INIT_UPDATE = (byte)0x80 ;
private final static byte INS_INIT_UPDATE = (byte)0x50 ;
private final static byte CLA_EXTERNAL_AUTHENTICATE = (byte)0x84 ;
private final static byte INS_EXTERNAL_AUTHENTICATE = (byte)0x82 ;
// the PIN validity flag
private boolean validPIN = false;
// SW bytes for PIN Failed condition
// the last nibble is replaced with the number of remaining tries
private final static short SW_PIN_FAILED = (short)0x63C0;
private final static short SW_FAILED_TO_OBTAIN_SIO = (short)0x63D0;
private final static short SW_LOYALTY_APP_NOT_EXIST = (short)0x63E0;
// the illegal amount value for the exceptions.
private final static short ILLEGAL_AMOUNT = 1;
// the maximum balance in this purse.
private static final short maximumBalance = 10000;
// the current balance in this purse.
private static short balance;
/* byte[] loyaltyAID = new byte[]{ (byte)0xA0,(byte)0x00,(byte)0x00,(byte)0x00,
(byte)0x19,(byte)0xFF,(byte)0x00,(byte)0x00,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
(byte)0x00,(byte)0x00,(byte)0x02,(byte)0x02};*/
/* Security part of declarations */
// the Security Object necessary to credit the purse
private ProviderSecurityDomain securityObject = null;
// the security channel number
byte secureChannel = (byte)0xFF;
// the authentication status
private boolean authenticationDone = false;
// the secure channel status
private boolean channelOpened = false;
private byte[] nameBuffer = new byte[6];
* Only this class's install method should create the applet object.
protected OPPurse(byte[] buffer, short offset, byte length)
// data offset is used for application specific parameter.
// initialization with default offset (AID offset).
short dataOffset = offset;
if(length > 9) {
// Install parameter detail. Compliant with OP 2.0.1.
// | size | content
// |------|---------------------------
// | 1 | [AID_Length]
// | 5-16 | [AID_Bytes]
// | 1 | [Privilege_Length]
// | 1-n | [Privilege_Bytes] (normally 1Byte)
// | 1 | [Application_Proprietary_Length]
// | 0-m | [Application_Proprietary_Bytes]
// shift to privilege offset
dataOffset += (short)( 1 + buffer[offset]);
// finally shift to Application specific offset
dataOffset += (short)( 1 + buffer[dataOffset]);
// checks wrong data length
if(buffer[dataOffset] != 2)
// return received proprietary data length in the reason
ISOException.throwIt((short)(ISO7816.SW_WRONG_LENGTH + offset + length - dataOffset));
// go to proprietary data
dataOffset++;
} else {
// Install parameter compliant with OP 2.0.
if(length != 2)
ISOException.throwIt((short)(ISO7816.SW_WRONG_LENGTH + length));
// retreive the balance value from the APDU buffer
short value = (short)(((buffer[(short)(dataOffset + 1)]) & 0xFF)
| ((buffer[dataOffset] & 0xFF) << 8));
// checks initial balance value
if(value > maximumBalance)
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
// initializes the balance with the APDU buffer contents
balance = value;
// register this instance as an installed Applet
register();
// ask the system for the Security Object associated to the Applet
securityObject = OPSystem.getSecurityDomain();
// applet is personalized and its state can change
OPSystem.setCardContentState(OPSystem.APPLET_PERSONALIZED);
// build the new ATR historical bytes
byte[] newATRHistory = new byte[]
// put "OPPurse" in historical bytes.
(byte)0x4F, (byte)0x50, (byte)0x50, (byte)0x75, (byte)0x72, (byte)0x73, (byte)0x65
// !!! ACTIVATED IF INSTALL PRIVILEGE IS "Default Selected" (0x04). !!!
// change the default ATR to a personalized's one
OPSystem.setATRHistBytes(newATRHistory, (short)0, (byte)newATRHistory.length);
* Method installing the applet.
* @param installparam the array constaining installation parameters
* @param offset the starting offset in installparam
* @param length the length in bytes of the data parameter in installparam
public static void install(byte[] installparam, short offset, byte length )
throws ISOException
// applet instance creation with the initial balance
new OPPurse(installparam, offset, length );
* Select method returning true if applet selection is supported.
* @return boolean status of selection.
public boolean select()
validPIN = false;
// reset security if used.
// In case of reset deselect is not called
reset_security();
// return status of selection
return true;
* Deselect method.
public void deselect()
// reset security if used.
reset_security();
return;
* Method processing an incoming APDU.
* @see APDU
* @param apdu the incoming APDU
* @exception ISOException with the response bytes defined by ISO 7816-4
public void process(APDU apdu) throws ISOException
// get the APDU buffer
// the APDU data is available in 'apduBuffer'
byte[] apduBuffer = apdu.getBuffer();
// the "try" is mandatory because the debit method
// can throw a javacard.framework.UserException
try
switch(apduBuffer[ISO7816.OFFSET_INS])
case INS_VERIFY_PIN :
verifyPIN(apdu);
break ;
case INS_GET_BALANCE :
getBalance(apdu) ;
break ;
case INS_DEBIT :
debit(apdu) ;
break ;
case INS_SET_NAME :
setName(apdu);
break;
case INS_GET_NAME :
getName(apdu);
break ;
case INS_CREDIT :
credit(apdu) ;
break ;
case INS_INIT_UPDATE :
if(apduBuffer[ISO7816.OFFSET_CLA] == CLA_INIT_UPDATE)
// call initialize/update security method
init_update(apdu) ;
else
// wrong CLA received
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
break ;
case INS_EXTERNAL_AUTHENTICATE :
if(apduBuffer[ISO7816.OFFSET_CLA] == CLA_EXTERNAL_AUTHENTICATE)
// call external/authenticate security method
external_authenticate(apdu) ;
else
// wrong CLA received
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
break ;
case ISO7816.INS_SELECT :
break ;
default :
// The INS code is not supported by the dispatcher
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED) ;
break ;
} // end of the switch
} // end of the try
catch(UserException e)
// translates the UserException in an ISOException.
if(e.getReason() == ILLEGAL_AMOUNT)
throw new ISOException ( ISO7816.SW_DATA_INVALID ) ;
//- P R I V A T E M E T H O D S -
* Handles Verify Pin APDU.
* @param apdu APDU object
private void verifyPIN(APDU apdu)
// get APDU data
apdu.setIncomingAndReceive();
// get APDU buffer
byte[] apduBuffer = apdu.getBuffer();
// check that the PIN is not blocked
if(OPSystem.getTriesRemaining() == 0)
OPSystem.setCardContentState(OPSystem.APPLET_BLOCKED);
// Pin format for OP specification
// |type(2),length|nible(1),nible(2)|nible(3),nible(4)|...|nible(n-1),nible(n)|
// get Pin length
byte length = (byte)(apduBuffer[ISO7816.OFFSET_LC] & 0x0F);
// pad the PIN ASCII value
for(byte i=length; i<0x0E; i++)
// only low nibble of padding is used
apduBuffer[ISO7816.OFFSET_CDATA + i] = 0x3F;
// fill header TAG
apduBuffer[0] = (byte)((0x02 << 4) | length);
// parse ASCII Pin code
for(byte i=0; i<0x0E; i++)
// fill bytes with ASCII Pin nibbles
if((i & 0x01) == 0)
// high nibble
apduBuffer[(i >> 1)+1] = (byte)((apduBuffer[ISO7816.OFFSET_CDATA + i] & 0x0F) << 4);
else
// low nibble
apduBuffer[(i >> 1)+1] |= (byte)(apduBuffer[ISO7816.OFFSET_CDATA + i] & 0x0F);
// verify the received PIN
// !!! WARNING PIN HAS TO BE INITIALIZED BEFORE USE !!!
if(OPSystem.verifyPin(apdu, (byte)0))
// set PIN validity flag
validPIN = true;
// if applet state is BLOCKED then restore previous state (PERSONALIZED)
if(OPSystem.getCardContentState() == OPSystem.APPLET_BLOCKED)
OPSystem.setCardContentState(OPSystem.APPLET_PERSONALIZED);
return;
// the last nibble of returned code is the number of remaining tries
ISOException.throwIt((short)(SW_PIN_FAILED + OPSystem.getTriesRemaining()));
* Performs the "getBalance" operation on this counter.
* @param apdu The APDU to process.
private void getBalance( APDU apdu )
// check valid Applet state
if(OPSystem.getCardContentState() == OPSystem.APPLET_BLOCKED)
ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
// get the APDU buffer
byte[] apduBuffer = apdu.getBuffer();
// writes the balance into the APDU buffer after the APDU command part
apduBuffer[5] = (byte)(balance >> 8) ;
apduBuffer[6] = (byte)balance ;
// sends the APDU response
// switches to output mode
apdu.setOutgoing() ;
// 2 bytes to return
apdu.setOutgoingLength((short)2) ;
// offset and length of bytes to return in the APDU buffer
apdu.sendBytes((short)5, (short)2) ;
private void setName(APDU apdu)
// check valid Applet state
if(OPSystem.getCardContentState() == OPSystem.APPLET_BLOCKED)
ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
// the operation is allowed only if master pin is validated
if(!validPIN)
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
byte[] apduBuffer = apdu.getBuffer();
apdu.setIncomingAndReceive();
for(short i=0,k=5;i<6;i++,k++)
nameBuffer[i] = apduBuffer[k];
}//end of setName
private void getName(APDU apdu)
// check valid Applet state
if(OPSystem.getCardContentState() == OPSystem.APPLET_BLOCKED)
ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
byte[] apduBuffer = apdu.getBuffer();
for(short i=5, k=0;i<11;i++,k++)
apduBuffer=nameBuffer[k];
apdu.setOutgoing();
apdu.setOutgoingLength((short)6);
apdu.sendBytes((short)5,(short)6);
}//end of storeName
* Performs the "debit" operation on this counter.
* @param apdu The APDU to process.
* @exception ISOException If the APDU is invalid.
* @exception UserException If the amount to debit is invalid.
private void debit(APDU apdu) throws ISOException, UserException
// check valid Applet state
if(OPSystem.getCardContentState() == OPSystem.APPLET_BLOCKED)
ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
// the operation is allowed only if master pin is validated
if(!validPIN)
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
// get the APDU buffer
byte[] apduBuffer = apdu.getBuffer();
// Gets the length of bytes to recieved from the terminal and receives them
// If does not receive 4 bytes throws an ISO.SW_WRONG_LENGTH exception
if(apduBuffer[4] != 2 || apdu.setIncomingAndReceive() != 2)
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH) ;
// Reads the debit amount from the APDU buffer
// Starts at offset 5 in the APDU buffer since the 5 first bytes
// are used by the APDU command part
short amount = (short)(((apduBuffer[6]) & (short)0x000000FF)
| ((apduBuffer[5] << 8 ) & (short)0x0000FF00));
// tests if the debit is valid
if((balance >= amount) && (amount > 0))
// does the debit operation
balance -= amount ;
// writes the new balance into the APDU buffer
// (writes after the debit amount in the APDU buffer)
apduBuffer[7] = (byte)(balance >> 8) ;
apduBuffer[8] = (byte)balance ;
// sends the APDU response
apdu.setOutgoing() ; // Switches to output mode
apdu.setOutgoingLength((short)2) ; // 2 bytes to return
// offset and length of bytes to return in the APDU buffer
apdu.sendBytes((short)7, (short)2) ;
/*short points = 10;
AID loyaltyID = JCSystem.lookupAID(loyaltyAID, (short)0, (byte)loyaltyAID.length);
if(loyaltyID == null)
ISOException.throwIt((short)(SW_LOYALTY_APP_NOT_EXIST));
TestInterface sio = (TestInterface)(JCSystem.getAppletShareableInterfaceObject(loyaltyID, (byte)0x00));
if(sio == null)
ISOException.throwIt((short)(SW_FAILED_TO_OBTAIN_SIO));
sio.creditPoints(points);*/
else
// throw a UserException with illegal amount as reason
throw new UserException(ILLEGAL_AMOUNT) ;
/* byte points = (byte)0x0A;
//short points = 10;
AID loyaltyID = JCSystem.lookupAID(loyaltyAID, (short)0, (byte)loyaltyAID.length);
if(loyaltyID == null)
ISOException.throwIt((short)(SW_LOYALTY_APP_NOT_EXIST));
TestInterface sio = (TestInterface)JCSystem.getAppletShareableInterfaceObject(loyaltyID, (byte)0x00);
if(sio == null)
ISOException.throwIt((short)(SW_FAILED_TO_OBTAIN_SIO));
sio.creditPoints(points);*/
* Performs the "credit" operation on this counter. The operation is allowed only
* if master pin is validated
* @param apdu The APDU to process.
* @exception ISOException If the APDU is invalid or if the amount to credit
* is invalid.
private void credit(APDU apdu) throws ISOException
// check valid Applet state
if(OPSystem.getCardContentState() == OPSystem.APPLET_BLOCKED)
ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
// the operation is allowed only if master pin is validated and authentication is done
if (!validPIN || !authenticationDone)
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
// get the APDU buffer
byte[] apduBuffer = apdu.getBuffer();
// gets the length of bytes to recieved from the terminal and receives them
// if does not receive 2 bytes throws an ISO.SW_WRONG_LENGTH exception
if(apduBuffer[4] != 2 || apdu.setIncomingAndReceive() != 2)
throw new ISOException(ISO7816.SW_WRONG_LENGTH) ;
// reads the credit amount from the APDU buffer
// starts at offset 5 in the APDU buffer since the 5 first bytes
// are used by the APDU command part
short amount = (short)(((apduBuffer[6]) & (short)0x000000FF)
| ((apduBuffer[5] << 8) & (short)0x0000FF00));
// tests if the credit is valid
if(((short)(balance + amount) > maximumBalance) || (amount <= (short)0))
throw new ISOException(ISO7816.SW_DATA_INVALID) ;
else
// does the credit operation
balance += amount ;
* Performs the "init_update" security operation.
* @param apdu The APDU to process.
private void init_update( APDU apdu )
// receives data
apdu.setIncomingAndReceive();
// checks for existing active secure channel
if(channelOpened)
// close the openned security channel
try
securityObject.closeSecureChannel(secureChannel);
catch(CardRuntimeException cre2)
// channel number is invalid. this case is ignored
// set the channel flag to close
channelOpened = false;
try
// open a new security channel
secureChannel = securityObject.openSecureChannel(apdu);
// set the channel flag to open
channelOpened = true;
// get expected length
short expected = apdu.setOutgoing();
// send authentication result
// expected length forced to 0x1C
apdu.setOutgoingLength((byte)0x1C);
apdu.sendBytes(ISO7816.OFFSET_CDATA, (byte)0x1c);
catch(CardRuntimeException cre)
// no available channel or APDU is invalid
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
* Performs the "external_authenticate" security operation.
* @param apdu The APDU to process.
private void external_authenticate( APDU apdu )
// receives data
apdu.setIncomingAndReceive();
// checks for existing active secure channel
if(channelOpened)
try
// try to authenticate the client
securityObject.verifyExternalAuthenticate(secureChannel, apdu);
// authentication succeed
authenticationDone = true;
catch(CardRuntimeException cre)
// authentication fails
// set authentication flag to fails
authenticationDone = false;
// close the openned security channel
try {
securityObject.closeSecureChannel(secureChannel);
} catch(CardRuntimeException cre2) {
// channel number is invalid. this case is ignored
// set the channel flag to close
channelOpened = false;
// send authentication result
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
// send authentication result
ISOException.throwIt(ISO7816.SW_NO_ERROR);
else
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
* The "reset_security" method close an opened secure channel if exist.
* @return void.
public void reset_security()
// close the secure channel if openned.
if(secureChannel != (byte)0xFF)
try
// close the openned security channel
securityObject.closeSecureChannel(secureChannel);
catch(CardRuntimeException cre2)
// channel number is invalid. this case is ignored
// reset security parameters
secureChannel = (byte)0xFF;
channelOpened = false;
authenticationDone = false;
return;
and the 3rd code is:
package com.gemplus.examples.loyalty;
import javacard.framework.Shareable;
public interface TestInterface extends Shareable
// public void creditPoints(byte points) ;
public void creditPoints(byte points) ;
Thanks in advance......Thanks. I know they are not the same thing. A package cannot be deleted if it contains one or more applets.
I tried to delete by typing in the applet AID first, but it just doesn't work. And of course it doesn't work for package AID.
Both the package and applet AID are generated in JBuilder, which looks like this, package AID(6D 79 70 61 63 6B 61 67 31),
applet AID(6D 79 70 61 63 30 30 30 31),
instance AID(6D 79 70 61 63 30 30 30 31)
I've tried those three AIDs, it's not working.
Thanks. -
I made a simple applet to test the speed of adding arrays, depending whether they are saved in EEPROM or RAM. Since working with variables stored in RAM should be faster, I was really surprised when I noticed no difference between them. I would really like to know where I went wrong, but simply can-t figure it out, so any help would be really appreciated. I used Eclipse 3.2 with JCOP Tools 3.1.1b and JCOP31 v2.2 JavaCard. The code I produced is:
package test;
import javacard.framework.APDU;
import javacard.framework.ISO7816;
import javacard.framework.Applet;
import javacard.framework.ISOException;
import javacard.framework.JCSystem;
public class SimpleMemoryTest extends Applet {
private static final short ARRAY_SIZE = 32;
byte[] eeprom_a, eeprom_b, eeprom_c;
byte[] ram_a, ram_b, ram_c;
short[] mem;
private SimpleMemoryTest() {
this.mem = new short[2];
public static void install(byte[] bArray, short bOffset, byte bLength) {
new SimpleMemoryTest().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
public void process(APDU apdu) {
if (selectingApplet()) return;
byte[] buf = apdu.getBuffer();
switch (buf[ISO7816.OFFSET_INS]) {
case (byte) 0x00: { // Print memory info to verify where arrays are stored
mem[0] = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
mem[1] = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);
buf[0] = (byte)(mem[0] / 256);
buf[1] = (byte)(mem[0] % 256);
buf[2] = (byte)(mem[1] / 256);
buf[3] = (byte)(mem[1] % 256);
apdu.setOutgoingAndSend((short)0, (short)4);
break;
case (byte) 0x01: { // Put arrays in EEPROM.
this.eeprom_a = new byte[ARRAY_SIZE];
this.eeprom_b = new byte[ARRAY_SIZE];
this.eeprom_c = new byte[ARRAY_SIZE];
break;
case (byte) 0x02: { // Put arrays in RAM.
this.ram_a = JCSystem.makeTransientByteArray(ARRAY_SIZE, JCSystem.CLEAR_ON_DESELECT);
this.ram_b = JCSystem.makeTransientByteArray(ARRAY_SIZE, JCSystem.CLEAR_ON_DESELECT);
this.ram_c = JCSystem.makeTransientByteArray(ARRAY_SIZE, JCSystem.CLEAR_ON_DESELECT);
break;
case (byte) 0x03: { // Add arrays in EEPROM 100 times
short i, j;
for (i = (short) 0; i < (short) 100; i++) {
for (j = (short) 0; j < (short) ARRAY_SIZE; j++) {
eeprom_c[j] = (byte)(eeprom_a[j] + eeprom_b[j]);
break;
case (byte) 0x04: { // Add arrays in RAM 100 times
short i, j;
for (i = (short) 0; i < (short) 100; i++) {
for (j = (short) 0; j < (short) ARRAY_SIZE; j++) {
ram_c[j] = (byte)(ram_a[j] + ram_b[j]);
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}When you create a byte array, all values are initialized to 0. Looking at your loops, it seems you're adding 0's only. Smart card operating systems normally do a read before write, to make sure not the same value is written. It saves time, and in case of EEPROM also to prolong the lifetime. I think this is the reason why you see no difference .. because there is no writing. Do something like
eeprom_c[j] = (byte)(i + j);
Matjaz wrote: case (byte) 0x03: { // Add arrays in EEPROM 100 times
short i, j;
for (i = (short) 0; i < (short) 100; i++) {
for (j = (short) 0; j < (short) ARRAY_SIZE; j++) {
eeprom_c[j] = (byte)(eeprom_a[j] + eeprom_b[j]);
break;
case (byte) 0x04: { // Add arrays in RAM 100 times
short i, j;
for (i = (short) 0; i < (short) 100; i++) {
for (j = (short) 0; j < (short) ARRAY_SIZE; j++) {
ram_c[j] = (byte)(ram_a[j] + ram_b[j]);
break; -
How can I use the security package in JCOP41V2.2?
Hi all, I'm a newbie in javacard programming. I'm trying to develop a project with RSA_signature. But I found, the exception NO_SUCH_ALGORITHM will be thrown out when I new an instance of KeyPair.
My java file Temp_1.java following:
package temp;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.APDU;
import javacard.security.*;
* @author lujj
public class Temp_1 extends Applet {
KeyPair myKeyPair = null;
public static void install(byte[] bArray, short bOffset, byte bLength) {
// GP-compliant JavaCard applet registration
new Temp_1().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
public void process(APDU apdu) throws ISOException{
// Good practice: Return 9000 on SELECT
if (selectingApplet()) {
return;
byte[] buf = apdu.getBuffer();
if(buf[ISO7816.OFFSET_CLA] == (byte)0xEE)
try
myKeyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_1024);
catch(CryptoException e)
ISOException.throwIt((short)(0x6F00+e.getReason()));
return;
switch (buf[ISO7816.OFFSET_INS]) {
case (byte) 0x00:
break;
default:
// good practice: If you don't know the INStruction, say so:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
This package can be upload and the applet can be installed successfully.
But if I send the apdu "EE 00 00 00 00" after selected the applet, "6F 03" will be returned.
Is there anyone can help me? Thanks a lot.Thank you so much~
Actually, it's only an applet for test. I cannot get the error code if I new the KeyPair in install function or Applet construct function. It will return "6A 80" when install the applet.
And, I found that it support few algorithm. For example, it does not support ALG_DES_MAC4_ISO9797_M2,etc. Is there anything I can do if I want to use the algorithm? Shall I rewrite security package by myself?
5555, security package is the standard package in JAVACARD API 2.1.1. -
How to return the message in MTI and bitmap?
Here we receive xml message from client but the problem is this coding is for the first time it receive MTI message, so how can i do if i receive from client in xml type then convert to MTI then response it as xml again to client.
Is it too hard to understand?????
* Waits and receive an ISOMsg over the TCP/IP session
* @return the Message received
* @exception IOException
* @exception ISOException
public ISOMsg receive() throws IOException, ISOException {
byte[] b=null;
byte[] header=null;
LogEvent evt = new LogEvent (this, "receive");
ISOMsg m = createMsg ();
Socket socket = getSocket();
m.setSource (this);
try {
if (!isConnected())
throw new ISOException ("unconnected ISOChannel");
synchronized (serverIn) {//read byte/array of byte
int len = getMessageLength();
int hLen = getHeaderLength();
if (len == -1) {
if (hLen > 0) {
header = readHeader(hLen);//read in message header
b = streamReceive();
else if (len > 0 && len <= 10000) {
if (hLen > 0) {
// ignore message header (TPDU)
// Note header length is not necessarily equal to hLen (see VAPChannel)
header = readHeader(hLen);//header lenght read the message header
len -= header.length;
b = new byte[len];
serverIn.readFully(b, 0, len);//get the input from user with byte type,0 length into lenght,read the byte to server in.
getMessageTrailler();
else
throw new ISOException(
"receive length " +len + " seems strange");
*// TODO:*
* // prefix with standard ISO MTI and bitmap*
*// using ISOMsg setters*
m.setPackager (getDynamicPackager(b));//msg receive
m.setHeader (getDynamicHeader(header));
if (b.length > 0 && !shouldIgnore (header)) // Ignore NULL messages
m.unpack (b);//raw message
m.setDirection(ISOMsg.INCOMING);//set the direction for incoming msg into isoMsg
m = applyIncomingFilters (m, header, b, evt);//remove the incoming filter to isoMsg
m.setDirection(ISOMsg.INCOMING);
evt.addMessage (m);
cnt[RX]++;
setChanged();
notifyObservers(m);
catch {
return m;
}check this link, and use as per you requirement
XI: How-to on JDBC receiver response
JDBC Receiver Adapter -- Synchronous Select Step by Step
Regards
Chilla -
Sending data to the card in a byte array
I am trying to store a variable dataCI[] with the data that comes into the buffer. I send this:
/send 0003000A0102030405
(INS=03)
Afterwards I want dataCI[] to have this value= "0102030405"
Here is my code. But when I am sending the bytes, it gives me an error of wrong length and does not matter how many bytes I send :/
DATA_LENGTH = 10;
lDate= apdu.setIncomingAndReceive();
if(lDate != DATA_LENGTH){
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
Util.arrayCopy(buffer, ISO7816.OFFSET_CDATA, dataCI, (short) 0, lDate);
return;
Also I tried with (lDate > DATA_LENGTH) and (lDate < DATA_LENGTH) but nothing works, it always gives me the error of wrong_length.
Can anybody tell me what am I doing wrong????Let's break down your apdu command....
"send 0003000A0102030405"
We agree that you are sending 5 bytes, so your Lc should = 5 not 0a
CLA = 00
INS = 03
P1 = 00
P2 = 0A <-- This should be your Lc !
Lc = 01 <--- This says there is 1 byte of data
CData = 02
Le = 03 <- This states there is 3 bytes coming back.
Lost in la la land data 04 05
So your command should read...
00 03 00 00 05 01 02 03 04 05; -
How can I read Extended APDU input to the same buffer
The following is the code I am currently using where inBuffer is an intermediate array of 1000 length. However, I do not want to allocate any buffers at all, and just want to send a command apdu of 1000 byte length and modify it in the code and return the modified buf in the response APDU.
// Read extended APDU input
byte[] buf = apdu.getBuffer();
short bytesRead = apdu.setIncomingAndReceive();
short dataOffset = apdu.getOffsetCdata();
// store first chunk in our intermediate byte array <-- how do i get rid of the intermediate array
Util.arrayCopyNonAtomic(buf, dataOffset, inBuffer, (short) 0, bytesRead);
// what is the overall length?
short overallLength = apdu.getIncomingLength();
short messageOffset = bytesRead;
if (bytesRead != overallLength){ // otherwise we're finished, all bytes received
short received = 0;
do{
received = apdu.receiveBytes((short)0);
Util.arrayCopyNonAtomic(buf, (short)0, inBuffer, messageOffset, received);
messageOffset += received;
} while(received != 0);
* REST OF CODE IN PROCESS METHOD
I have also tried replacing the above code with the following
short bytesLeft = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
if (bytesLeft < (short)55) ISOException.throwIt( ISO7816.SW_WRONG_LENGTH );
short readCount = apdu.setIncomingAndReceive();
while ( bytesLeft > 0){
// process bytes in buffer[5] to buffer[readCount+4];
bytesLeft -= readCount;
readCount = apdu.receiveBytes ( ISO7816.OFFSET_CDATA );
as shown in the javadocs API, but it does not compile.
This is my command APDU:
/send 800100000003E8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E8
As you can see:
CLA - 80
INS - 01
P1 & P2 - 00
LC - 0003E8
Data - 1000 0s
LE - 03E8
I am using JavaCard 3.0 with JCOP in Eclipse. How can I read the extended length apdu to the same buffer? I have no problem in returning an extended length response APDU. Thanks a lot for the help.You should not call the convenience method setIncomingAndReceive() in your first code. Please find out about the different APDU states. Furthermore, your Applet should implement the ExtendedLength tagging interface.
-
How to load the .cap file in a Smart Card?
Dear All,
Hello..!!
I am using JCDK 2.2 and have used Eclipse JCDK.
I have written a simple read/write applet and created a .cap file using Eclipse's Converter Java Card tool.
What is the next step to be done?
I have a smart card device and have installed its drivers.
When do the APDU commands come into picture?
Expecting help.
Thanks a lot.
Regards,
SurilSuril Sarvaiya wrote:
Hi Shane....
Thnx a lot....
I have downloaded GP-Shell 1.4.4
When I open its application and write any command and press enter ; the app window closes immendiately.
Can you please help me on this?
One more thing Shane......
I'm writig a java class using javax.smartcardio
I have installed drivers of Omnikey 3021
but the TerminalFactory is not detecting it?
Any idea on that?
Thanks again...
Regards,
SurilHi all,
Is Mr. thread starter has solved his problem?
I profit this thread to post my question. I'm working with new environment and I have problem loading cap file into my smartcard.
specification come first :-)
- My smartcard is said to be JC2.2.1 and GP2.1.1 compatible
- My code (for testing) is written in Java under eclipse Helios service 2 with JavaCard plugin (for JC2.2.2)
I compile my code with JDK 1.3 (for compatible version) and using the JC plugin to generate cap file (along with exp and jca).
My problem is exactly the same as one that was posted in this forum about 2 years ago but is not answered :-)
[Problem Loading Application to Card |http://forums.oracle.com/forums/thread.jspa?threadID=1749334&tstart=420]
+ I successfully authenticate with smartcard
+ APDU command Install for Load is executed successfully
+ BUT the APDU command LOAD file fails with returned status word is 6424
For details, I post here my javacard applet code and APDU command executed with my tool:
package mksAuthSys;
import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.OwnerPIN;
public class Jcardlet extends Applet {
private final static byte[] myPIN = { (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04};
final static byte Jcardlet_CLA =(byte)0xB0;
final static byte VERIFY = (byte) 0x20;
final static byte PIN_TRY_LIMIT =(byte)0x03;
final static byte MAX_PIN_SIZE =(byte)0x08;
final static short SW_VERIFICATION_FAILED = 0x6300;
OwnerPIN pin;
private Jcardlet() {
pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
pin.update(myPIN, (byte) 0, (byte) 4 );
register();
public static void install(byte bArray[], short bOffset, byte bLength)
throws ISOException {
new Jcardlet().register();
public boolean select() {
if ( pin.getTriesRemaining() == 0 ) return false;
return true;
public void deselect(){
pin.reset();
//@Override
public void process(APDU apdu) throws ISOException {
// TODO Auto-generated method stub
byte[] buffer = apdu.getBuffer();
if ((buffer[ISO7816.OFFSET_CLA] == 0) &&
(buffer[ISO7816.OFFSET_INS] == (byte)(0xA4))) return;
if (buffer[ISO7816.OFFSET_CLA] != Jcardlet_CLA)
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
switch (buffer[ISO7816.OFFSET_INS]) {
case VERIFY: verify(apdu);
return;
default: ISOException.throwIt (ISO7816.SW_INS_NOT_SUPPORTED);
private void verify(APDU apdu) {
// TODO Auto-generated method stub
byte[] buffer = apdu.getBuffer();
// retrieve the PIN data for validation.
byte byteRead = (byte)(apdu.setIncomingAndReceive());
// check pin
// the PIN data is read into the APDU buffer
// at the offset ISO7816.OFFSET_CDATA
// the PIN data length = byteRead
if ( pin.check(buffer, ISO7816.OFFSET_CDATA,byteRead) == false )
ISOException.throwIt(SW_VERIFICATION_FAILED);
}And my APDU command:
Loading "D:\mksAuthSys.cap" ...
T - 80F28000024F00
C - 08A000000003000000079E9000
ISD AID : A000000003000000
T - 80E602001508F23412345610000008A00000000300000000000000
C - 009000
T - 80E80000C8C482018B010012DECAFFED010204000108F23412345610000002001F0012001F000C001500420012009D0011001C0000009F00020001000402010004001502030107A0000000620101000107A000000062000103000C0108F234123456100001002306001200800301000104040000003DFFFF0030004507009D000510188C0003188F00013D0610088C00028700AD007B000403078B0005188B00067A02308F00073D8C00088B00067A0110AD008B00096104037804780110AD008B000A7A0221198B000B2D1A0300
C - 6424
Stopped loading due to unexpected status words.Urgently look forward to hearing from you.
Thanks a bunch in advance
Best Regards,
JDL -
Error while sending an APDU 6d 00
Hello,
I'm testing Javacard and i just want to send vie smartcard io an apdu command 0x80 0x07 0x00 0x00.
As an response i should get: a simple string back.
However, it doesen't work. After I selected more or less every ins byt eI'm sending results in an 6d00.
But if I'm sending it via the APDUTOOL I'm getting the correct answer??
Must have something to do with the transformation from in to byte. But I don't see where...
Here is the java code:
public class SCcommunication {
private TerminalFactory factory;
private List<CardTerminal> terminals;
private CardTerminal terminal;
private Card card;
private CardChannel channel;
private ResponseAPDU response;
private boolean protocollType;
private int sendLength;
private int selectLength; //00 A4 04 00 + LE + aid
private byte send[], select[];
private CommandAPDU command;
//generate a factory, get terminal list, and take the first terminal available (get(0))!
public SCcommunication(){
factory= TerminalFactory.getDefault();
try{
terminals = factory.terminals().list();
catch (CardException ec){
ec.printStackTrace();
terminal = terminals.get(0);
//if protocolltype=flase then protocoll is T0 else T1
protocollType=false;
selectLength=13;
sendLength=133;
select= new byte[selectLength];
select[0]=(byte)(0x00);select[1]=(byte)(0xA4);select[2]=(byte)(0x04);select[3]=(byte)(0x0); select[4]=(byte)(8);
select[5]=(byte)(0xAB); select[6]=(byte)(0xCD); select[7]=(byte)(0xEF); select[8]=(byte)(0xFE); select[9]=(byte)(0xDC); select[10]=(byte)(0x12);
select[11]=(byte)(0x34); select[12]=(byte)(0x56); //select[13]=(byte)(0x01); select[14]=(byte)(0x01);
send= new byte[sendLength];
public void switchProtocoll(){
if (!protocollType==true)
protocollType=false;
else
protocollType=true;
public void selectApplet(byte selectAPDU[]){
try{
if (protocollType)
card = terminal.connect("T=0");
else
card = terminal.connect("T=1");
channel= card.getBasicChannel();
response=channel.transmit(new CommandAPDU(select));
byte respByte[]=response.getBytes();
System.out.print("The response: ");
System.out.println();
for (int i=0;i<respByte.length;i++){
System.out.print(Integer.toHexString(respByte&0xff)+"||");
System.out.println();
// the card is not reseted after disconnect, due to false
card.disconnect(false);
catch (CardException ec){
ec.printStackTrace();
public void sendToCard(){
try{
if (protocollType)
card=terminal.connect("T=0");
else
card=terminal.connect("T=1");
channel= card.getBasicChannel();
//response=channel.transmit(new CommandAPDU(send));
send[0]=(byte)0x80; send[1]=(byte)0x07; send[2]=(byte)(0x00);send[3]=(byte)(0x00); send[4]=(byte)(128);
System.out.println("The response: ");
response=channel.transmit(new CommandAPDU(send));
byte respByte[]=response.getBytes();
for (int i=0;i<respByte.length;i++){
System.out.print(Integer.toHexString(respByte[i]&0xff)+"||");
System.out.println();
System.out.println("Done");
// the card is not reseted after disconnect, due to false
card.disconnect(false);
catch (CardException ec){
ec.printStackTrace();
public static void main (String args[]){
SCcommunication sc = new SCcommunication();
sc.switchProtocoll();
sc.selectApplet(sc.select);
sc.sendToCard();
Here is the corresponending Java Card code:
public void process(APDU apdu) throws ISOException {
// this is the text string which will send back from the ICC to the IFD
final byte[] text = {(byte) 'H', (byte) 'l', (byte) 'l', (byte) ' ',
(byte) 'o', (byte) 'M', (byte) 'n', (byte) 'a', (byte) 'm', (byte) ' ',
(byte) 'e', (byte) 'i', (byte) 's', (byte) 'C',
(byte) 'h', (byte) 'a', (byte) 'r', (byte) 'l', (byte) 'y'};
// this is the install method which will be called once for installation
// and registration of the applet
// this is the method, which will be called from JCRE
// the cmd_apdu variable is used because of performance reasons
byte[] cmd_apdu = apdu.getBuffer();
if (cmd_apdu[0] ==(byte)0x80) { // it is the rigth class
short len_text = (short)text.length; // the len_text variable is used because of performance reasons
apdu.setOutgoing(); // set transmission to outgoing data
apdu.setOutgoingLength((short)len_text); // set the number of bytes to send to the IFD
apdu.sendBytesLong(text, (short)0, (short)len_text);
} // if
else{
ISOException.throwIt(ISO7816.SW_NO_ERROR);
} // process
Does anybode have any idea?
Best regardsRepost with code tgas:
866393 wrote:
Hello,
I'm testing Javacard and i just want to send vie smartcard io an apdu command 0x80 0x07 0x00 0x00.
As an response i should get: a simple string back.
However, it doesen't work. After I selected more or less every ins byt eI'm sending results in an 6d00.
But if I'm sending it via the APDUTOOL I'm getting the correct answer??
Must have something to do with the transformation from in to byte. But I don't see where...
Here is the java code:
public class SCcommunication {
private TerminalFactory factory;
private List<CardTerminal> terminals;
private CardTerminal terminal;
private Card card;
private CardChannel channel;
private ResponseAPDU response;
private boolean protocollType;
private int sendLength;
private int selectLength; //00 A4 04 00 + LE + aid
private byte send[], select[];
private CommandAPDU command;
//generate a factory, get terminal list, and take the first terminal available (get(0))!
public SCcommunication(){
factory= TerminalFactory.getDefault();
try{
terminals = factory.terminals().list();
catch (CardException ec){
ec.printStackTrace();
terminal = terminals.get(0);
//if protocolltype=flase then protocoll is T0 else T1
protocollType=false;
selectLength=13;
sendLength=133;
select= new byte[selectLength];
select[0]=(byte)(0x00);select[1]=(byte)(0xA4);select[2]=(byte)(0x04);select[3]=(byte)(0x0); select[4]=(byte)(8);
select[5]=(byte)(0xAB); select[6]=(byte)(0xCD); select[7]=(byte)(0xEF); select[8]=(byte)(0xFE); select[9]=(byte)(0xDC); select[10]=(byte)(0x12);
select[11]=(byte)(0x34); select[12]=(byte)(0x56); //select[13]=(byte)(0x01); select[14]=(byte)(0x01);
send= new byte[sendLength];
public void switchProtocoll(){
if (!protocollType==true)
protocollType=false;
else
protocollType=true;
public void selectApplet(byte selectAPDU[]){
try{
if (protocollType)
card = terminal.connect("T=0");
else
card = terminal.connect("T=1");
channel= card.getBasicChannel();
response=channel.transmit(new CommandAPDU(select));
byte respByte[]=response.getBytes();
System.out.print("The response: ");
System.out.println();
for (int i=0;i<respByte.length;i++){
System.out.print(Integer.toHexString(respByte&0xff)+"||");
System.out.println();
// the card is not reseted after disconnect, due to false
card.disconnect(false);
catch (CardException ec){
ec.printStackTrace();
public void sendToCard(){
try{
if (protocollType)
card=terminal.connect("T=0");
else
card=terminal.connect("T=1");
channel= card.getBasicChannel();
//response=channel.transmit(new CommandAPDU(send));
send[0]=(byte)0x80; send[1]=(byte)0x07; send[2]=(byte)(0x00);send[3]=(byte)(0x00); send[4]=(byte)(128);
System.out.println("The response: ");
response=channel.transmit(new CommandAPDU(send));
byte respByte[]=response.getBytes();
for (int i=0;i<respByte.length;i++){
System.out.print(Integer.toHexString(respByte[i]&0xff)+"||");
System.out.println();
System.out.println("Done");
// the card is not reseted after disconnect, due to false
card.disconnect(false);
catch (CardException ec){
ec.printStackTrace();
public static void main (String args[]){
SCcommunication sc = new SCcommunication();
sc.switchProtocoll();
sc.selectApplet(sc.select);
sc.sendToCard();
Here is the corresponending Java Card code:
public void process(APDU apdu) throws ISOException {
// this is the text string which will send back from the ICC to the IFD
final byte[] text = {(byte) 'H', (byte) 'l', (byte) 'l', (byte) ' ',
(byte) 'o', (byte) 'M', (byte) 'n', (byte) 'a', (byte) 'm', (byte) ' ',
(byte) 'e', (byte) 'i', (byte) 's', (byte) 'C',
(byte) 'h', (byte) 'a', (byte) 'r', (byte) 'l', (byte) 'y'};
// this is the install method which will be called once for installation
// and registration of the applet
// this is the method, which will be called from JCRE
// the cmd_apdu variable is used because of performance reasons
byte[] cmd_apdu = apdu.getBuffer();
if (cmd_apdu[0] ==(byte)0x80) { // it is the rigth class
short len_text = (short)text.length; // the len_text variable is used because of performance reasons
apdu.setOutgoing(); // set transmission to outgoing data
apdu.setOutgoingLength((short)len_text); // set the number of bytes to send to the IFD
apdu.sendBytesLong(text, (short)0, (short)len_text);
} // if
else{
ISOException.throwIt(ISO7816.SW_NO_ERROR);
} // process
Does anybode have any idea?
Best regards -
Is there ANYONE who have REAL knowelage with JAVA CARD OS?
It is serious problem. Same problem like this one:
http://forums.sun.com/thread.jspa?threadID=5344671&tstart=30
Anyway. Main problem is that if you want to use several times encryption using different key every time
soon or later card will BLOCK itself!!!
Well it will return code 6F00 and ONLY whole reprograming of card will help!!!
Here is simple code:
package com.cpit.javacard;
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 javacard.security.AESKey;
import javacard.security.DESKey;
import javacard.security.Key;
import javacard.security.KeyBuilder;
import javacard.security.MessageDigest;
import javacard.security.RSAPrivateCrtKey;
import javacardx.crypto.Cipher;
public class DES3a extends Applet
byte[] staticKey = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47};
byte[] inData ={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
byte[] outData ={(byte) 0xF1,(byte) 0xD7,(byte) 0x5E,(byte) 0x4F,(byte) 0x0D,(byte) 0x37,(byte) 0xC2,(byte) 0x2C,(byte) 0xB8,(byte) 0xD5,(byte) 0x4E,(byte) 0x62,(byte) 0x53,(byte) 0xBB,(byte) 0x40,(byte) 0xB1};
byte[] dummy = new byte[4024];
//constructor
private DES3a (byte bArray[], short bOffset, byte bLength)
register(bArray, (short) (bOffset + 1), bArray[bOffset]);
// install
public static void install(byte bArray[], short bOffset, byte bLength)
new DES3a (bArray, bOffset, bLength);
public void process(APDU apdu)
byte[] buf = apdu.getBuffer();
// Good practice: Return 9000 on SELECT
if (selectingApplet())
return;
if (buf[ISO7816.OFFSET_CLA] != (byte) (0xB0)) ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
if (buf[ISO7816.OFFSET_INS] != (byte) (0xAA)) ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
byte buffer[] = apdu.getBuffer();
Crypt_DES(apdu);
private void Crypt_DES(APDU apdu)
byte[] buffer = apdu.getBuffer();
for( short i = 0; i<(short)50; i++) {
generateSessionKey(inData, staticKey, buffer);
if (Util.arrayCompare(buffer,(short) 0, outData, (short)0x0, (short)16) != 0 ) break;
Util.arrayCopy(outData, (short)(0), buffer, (short)16, (short)16);
apdu.setOutgoing();
apdu.setOutgoingLength((byte) 0x30);
apdu.sendBytes((short) 0, (byte) 0x30);
return;
private void generateSessionKey(byte[] derivationData, byte[] staticKey,byte[] sessionKey){
DESKey key = ( DESKey )KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_2KEY, false );
key.setKey( staticKey, (short)0 );
Cipher cipher = Cipher.getInstance( Cipher.ALG_DES_ECB_NOPAD, true );
cipher.init( key, Cipher.MODE_ENCRYPT );
cipher.doFinal(derivationData, (short)0, (short)16, sessionKey, (short)0);
key.clearKey();
It seems that problem is in KeyBuilder?! . Is this function allocates EEPROM??? how can be that memory
deallocated? Even worst is if it used TYPE_DES_TRANSIENT_DESELECT insead TYPE_DES!!!
In example from above in loop top value is 50. On some cards (depend on EEPROM size) it can be even
1000 ! but still it will crash on the end!
Also increasing size of "dummy" it will reduce number of DES runs.
Here is results:
cm> /select 11223344556677
=> 00 A4 04 00 07 11 22 33 44 55 66 77 00 ......"3DUfw.
(20215 usec)
<= 90 00 ..
Status: No Error
cm> send b0aa000000
=> B0 AA 00 00 00 .....
(14394373 usec)
<= F1 D7 5E 4F 0D 37 C2 2C B8 D5 4E 62 53 BB 40 B1 ..^O.7.,..NbS.@.
F1 D7 5E 4F 0D 37 C2 2C B8 D5 4E 62 53 BB 40 B1 ..^O.7.,..NbS.@.
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
90 00 ..
Status: No Error
cm> send b0aa000000
=> B0 AA 00 00 00 .....
(15024947 usec)
<= F1 D7 5E 4F 0D 37 C2 2C B8 D5 4E 62 53 BB 40 B1 ..^O.7.,..NbS.@.
F1 D7 5E 4F 0D 37 C2 2C B8 D5 4E 62 53 BB 40 B1 ..^O.7.,..NbS.@.
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
90 00 ..
Status: No Error
cm> send b0aa000000
=> B0 AA 00 00 00 .....
(15632306 usec)
<= F1 D7 5E 4F 0D 37 C2 2C B8 D5 4E 62 53 BB 40 B1 ..^O.7.,..NbS.@.
F1 D7 5E 4F 0D 37 C2 2C B8 D5 4E 62 53 BB 40 B1 ..^O.7.,..NbS.@.
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
90 00 ..
Status: No Error
cm> send b0aa000000
=> B0 AA 00 00 00 .....
(8572462 usec)
<= 6F 00 o.
Status: No precise diagnosis
As you can see that card (jcop41) can run correct less than 200 times!!!
On gemplus 64k it can run less than 1200 times!!!
So is there any method for dealocating EEPROM that is used by KeyBuilder?
Or to use RAM (Using TYPE_DES_TRANSIENT_DESELECT is even worst!)
That is problem with EEPROM here is proof:
On halted card when is application deleted it takes more time !!!
;HALTED CARD
cm> ext-auth plain
=> 84 82 00 00 10 B0 B9 D5 5A FC D3 BA 3F AE 85 CD ........Z...?...
9F 24 25 A5 04 .$%..
(123134 usec)
<= 90 00 ..
Status: No Error
cm> delete 11223344556677
=> 80 E4 00 00 09 4F 07 11 22 33 44 55 66 77 00 .....O.."3DUfw.
(3235735 usec)
<= 00 90 00 ...
Status: No Error
cm> delete 112233445566
=> 80 E4 00 00 08 4F 06 11 22 33 44 55 66 00 .....O.."3DUf.
(940978 usec)
<= 00 90 00 ...
Status: No Error
NORMAL CARD
cm> ext-auth plain
=> 84 82 00 00 10 96 4D 17 94 84 41 0B 03 62 BF AC ......M...A..b..
3D 72 41 E0 D4 =rA..
(67224 usec)
<= 90 00 ..
Status: No Error
cm> delete 11223344556677
=> 80 E4 00 00 09 4F 07 11 22 33 44 55 66 77 00 .....O.."3DUfw.
(930056 usec)
<= 00 90 00 ...
Status: No Error
cm> delete 112233445566
=> 80 E4 00 00 08 4F 06 11 22 33 44 55 66 00 .....O.."3DUf.
(946824 usec)
<= 00 90 00 ...
Status: No Error
As you can see 3235735 usec vs 930056 usec
Any help?
regardsOk, thanks for hints & help, here is a tested working example:
static byte DES_flag = 0xa5;
DESKey key ;
Cipher cipher;
//constructor
// because I dont know how "install" handles functions i've use "selectingApplet"
if (selectingApplet())
if (DES_flag ==0xa5){
cipher = Cipher.getInstance( Cipher.ALG_DES_ECB_NOPAD, false ); //instead true!
key = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES_TRANSIENT_DESELECT , KeyBuilder.LENGTH_DES3_2KEY, true );
DES_flag =0;
return;
private void generateSessionKey(byte[] derivationData, byte[] staticKey,byte[] sessionKey){
key.setKey( staticKey, (short)0 );
cipher.init( key, Cipher.MODE_ENCRYPT );
cipher.doFinal(derivationData, (short)0, (short)16, sessionKey, (short)0);
key.clearKey();
Regards -
Rsa Decrypt Not Working.. Please Help
Hi everyone,
I am new to java card development. I have been trying to use RSA encryption in my Applet. I finally got the encryption working but the decryption is showing Illegal Use Error. Any kind of help is appreciated.
public class RSAsample extends Applet{
byte[] rsaPublic = new byte[4];
byte[] rsaPrivate = new byte[4];
byte[] rsaPublicMod = new byte[4];
RSAPrivateKey pri ;
RSAPublicKey pub ;
private final static byte INS_ENCRYPT = (byte) 0x20;
private final static byte INS_DECRYPT = (byte) 0x30;
KeyPair pair ;
private RSAsample() {
super();
register();
public static void install(byte bArray[], short bOffset, byte bLength)
throws ISOException {
new RSAsample();
public boolean select() {
pair = new KeyPair(KeyPair.ALG_RSA, (short) 512);
pair.genKeyPair();
pri = (RSAPrivateKey) pair.getPrivate();
pub = (RSAPublicKey) pair.getPublic();
return super.select();
public void deselect() {
super.deselect();
public void process(APDU apdu) throws ISOException {
byte[] buffer = apdu.getBuffer();
switch(buffer[ISO7816.OFFSET_INS])
case INS_ENCRYPT:
encrypt(apdu);
break;
case INS_DECRYPT:
decrypt(apdu);
break;
private void decrypt(APDU apdu) {
byte[] buffer = apdu.getBuffer();
byte byteRead = (byte)(apdu.setIncomingAndReceive());
short size = 0;
try{
Cipher cipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
cipher.init(pri, Cipher.MODE_DECRYPT);
size = cipher.doFinal(buffer, ISO7816.OFFSET_CDATA, (short)byteRead, buffer,
(short) 0);
catch(CryptoException e)
switch(e.getReason())
case CryptoException.ILLEGAL_USE:
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
break;
case CryptoException.ILLEGAL_VALUE:
ISOException.throwIt(ISO7816.SW_FILE_INVALID);
break;
case CryptoException.INVALID_INIT:
ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
break;
case CryptoException.NO_SUCH_ALGORITHM:
ISOException.throwIt(ISO7816.SW_FILE_INVALID);
break;
case CryptoException.UNINITIALIZED_KEY:
ISOException.throwIt(ISO7816.SW_FILE_FULL);
break;
default:
ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
break;
apdu.setOutgoing();
apdu.setOutgoingLength(size);
apdu.sendBytes((short)0, size);
private void encrypt(APDU apdu) {
byte[] buffer = apdu.getBuffer();
byte byteRead = (byte)(apdu.setIncomingAndReceive());
short size = 0;
try{
Cipher cipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
cipher.init(pub, Cipher.MODE_ENCRYPT);
size = cipher.doFinal(buffer, ISO7816.OFFSET_CDATA, (short)byteRead, buffer,
(short) 0);
catch(CryptoException e)
switch(e.getReason())
case CryptoException.ILLEGAL_USE:
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
break;
case CryptoException.ILLEGAL_VALUE:
ISOException.throwIt(ISO7816.SW_FILE_INVALID);
break;
case CryptoException.INVALID_INIT:
ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
break;
case CryptoException.NO_SUCH_ALGORITHM:
ISOException.throwIt(ISO7816.SW_FILE_INVALID);
break;
case CryptoException.UNINITIALIZED_KEY:
ISOException.throwIt(ISO7816.SW_FILE_FULL);
break;
default:
ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
break;
apdu.setOutgoing();
apdu.setOutgoingLength(size);
apdu.sendBytes((short)0, size);
Also if this is wrong can you share a sample code using RSA Encryption and Decryption.
ThanksHi,
You code looks perfectly fine.
Looking at the error code i think you are sending some invalid data for decryption operation.
You should send data which was encrypted using the same PublicKey other wise it will fail while matching the Padding or Data Blocks.
For better understanding Encrypt some data and immediately use the output data for Decrypt operation and it should work fine.
Let me know if you face any difficulties.
BR,
PPT -
I can�t decrypt a text encrypted (using RSA) with keys on smartcard.
I use a Cyberflex Access e-gate smartcard and I can encrypt and decrypt any text on the card but if I encrypt a text outside using the exported public key, card is not able to decrypt the message.
On the card side:
�
RSAPrivateCrtKey privateKey;
RSAPublicKey publicKey;
Cipher cipherRSA;
�
private MyIdentity (byte buffer[], short offset, byte length){
// initialise PIN
pin = new OwnerPIN(PinTryLimit, MaxPinSize);
pin.resetAndUnblock();
// Key Pair
KeyPair kp = new KeyPair(KeyPair.ALG_RSA_CRT, (short)1024);
kp.genKeyPair();
privateKey = (RSAPrivateCrtKey) kp.getPrivate();
publicKey = (RSAPublicKey) kp.getPublic();
cipherRSA = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
if (buffer[offset] == (byte)0) {
register();
} else {
register(buffer, (short)(offset+1) ,(byte)(buffer[offset]));
private void GetPublicKey (APDU apdu) {
if (pin.isValidated()){
byte apduBuffer[] = apdu.getBuffer();
// short byteRead = (short)(apdu.setIncomingAndReceive());
short bytesMod = publicKey.getModulus(apduBuffer, (short) 0);
short bytesExp = publicKey.getExponent(apduBuffer,bytesMod);
short outbytes = (short) (bytesMod + bytesExp);
// Send results
apdu.setOutgoing();
// indicate the number of bytes in the data field
apdu.setOutgoingLength((short)outbytes);
// at offset 0 send 128 byte of data in the buffer
apdu.sendBytesLong(apduBuffer, (short)APDUDATA, (short)outbytes);
} else {
ISOException.throwIt (ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
private void Decrypt (APDU apdu) {
byte apduBuffer[] = apdu.getBuffer();
short byteRead = (short)(apdu.setIncomingAndReceive());
cipherRSA.init(privateKey, Cipher.MODE_DECRYPT);
cipherRSA.doFinal(apduBuffer,(short)APDUDATA, byteRead, apduBuffer, (short)APDUDATA);
// Send results
apdu.setOutgoing();
// indicate the number of bytes in the data field
apdu.setOutgoingLength(byteRead);
// at offset 0 send x byte of data in the buffer
apdu.sendBytesLong(apduBuffer, (short)APDUDATA, byteRead);
}Off the card, I have a java client:
public void getPublicKey () {
int CLA, INS, P1, P2;
int iArray[] = new int[0];
short sArray[] = new short[0];
String ss = new String("");
String s;
byte [] sBytes = null;
byte [] myModulus = new byte[128];
byte [] myExponent = new byte[3];
try {
CLA = 0x68;
INS = 0x78;
P1 = 0;
P2 = 0;
sArray = iopCard.SendCardAPDU(CLA,INS,P1,P2,iArray,0x83);
int iErrorCode = iopCard.GetLastErrorCode();
if (iErrorCode != 0x9000) {
if (iErrorCode == 0x6300) {
System.out.println("Wrong PIN");
} else {
s = iopCard.GetErrorMessage();
System.out.println("SendCardAPDU: " + s);
} else {
System.out.println("Getting Public Key...");
if (sArray != null) {
sBytes = new byte[sArray.length];
for (int i = 0; i < sArray.length; i++) {
sBytes[i] = (byte)sArray;
ss = new String(sBytes);
System.out.println ("------ BEGIN PUBLIC KEY -------------------");
for (int i=0; i < sArray.length; i++){
System.out.print(Integer.toHexString(ss.charAt(i)).toUpperCase());
System.out.println ();
System.out.println ("------ END PUBLIC KEY -------------------");
} else {
System.out.println("Nothing.");
} catch (slbException b) {
s = b.getMessage();
System.out.println("Validate error: " + s);
for (int i=0; i<128; i++){
myModulus[i] = (byte) sArray[i];
for (int i=0; i<3; i++){
myExponent[i] = (byte) sArray[128+i];
BigInteger modulus = new BigInteger (1,myModulus);
BigInteger exponent = new BigInteger ("65537"); // there is a well-known bug in getExponent
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory keyFactory =null;
try {
keyFactory = KeyFactory.getInstance("RSA");
publicKey = keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e) {
System.out.println(e.getMessage ());
} catch (InvalidKeySpecException e) {
System.out.println(e.getMessage ());
System.out.println("------------------ BEGIN ------------------");
ss = new String(publicKey.getEncoded());
for (int i=0; i < publicKey.getEncoded().length; i++){
System.out.print(Integer.toHexString(ss.charAt(i)).toUpperCase());
System.out.println ();
System.out.println("------------------ END ------------------");
// to a file
try {
//Store in raw format
FileWriter fw = new FileWriter("public_raw.txt");
for (int i=0; i < publicKey.getEncoded().length; i++){
fw.write(Integer.toHexString(ss.charAt(i)).toUpperCase());
fw.close();
//could also store it as a Public key
System.out.println("Public key saved to file");
} catch(Exception e) {
System.out.println("Error opening and writing Public key to file : "+e.getMessage());
public void encrypt () {
byte cadena[] = {0x01,0x02,0x03,0x04};
byte resultado[] = new byte[256];
// Create Cipher
try {
cipherRSA.init(Cipher.ENCRYPT_MODE, publicKey);
resultado = cipherRSA.doFinal (cadena);
} catch (InvalidKeyException e) {
System.out.println(e.getMessage());
} catch (BadPaddingException e) {
System.out.println(e.getMessage());
} catch (IllegalBlockSizeException e) {
System.out.println(e.getMessage());
String ss = new String (resultado);
System.out.println("------------------ BEGIN 4 ------------------");
for (int i=0; i < resultado.length; i++){
System.out.print(Integer.toHexString(ss.charAt(i)).toUpperCase());
System.out.println ();
System.out.println("------------------ END 4 ------------------");
Another question is that I don�t understand why I get a constant length string when I encrypt a text on the card and variable length string when I encrypt off the cardI thought that exponent was 3 bytes long...
On the card I have the following code:
private void GetExponent (APDU apdu) {
if (pin.isValidated()){
byte apduBuffer[] = apdu.getBuffer();
short bytesExp = publicKey.getExponent(apduBuffer, (short) 0);
// Send results
apdu.setOutgoing();
// indicate the number of bytes in the data field
apdu.setOutgoingLength((short)bytesExp);
// at offset 0 send 128 byte of data in the buffer
apdu.sendBytesLong(apduBuffer, (short)APDUDATA, (short)bytesExp);
} else {
ISOException.throwIt (ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
}And if I don't send an APDU with length expected, I get the exception 6C03 (Correct Expected Length (Le) = 0x6C00) so I send APDU with 03 length and I receive the exponent. The problem is that there is a well know bug in getExponent and it returns 00 00 00... so I set it up to 65537 outside the card. -
RSA Keypair cannot be generated in javacard ?
Hello
I got a problem about how to generate a RSA keypair in JAVACARD, I tried many different parametres, but I cannot install my applet in my emulator.
public class RSAencry extends Applet {
RSAPrivateKey rsa_PrivateKey;
RSAPublicKey rsa_PublicKey;
KeyPair rsa_KeyPair;
Cipher cipherRSA;
//private byte buffer[];
//byte TheBuffer[];
final short dataOffset = (short) ISO7816.OFFSET_CDATA;
//constructor
private RSAencry()
//generate own rsa_keypair
//rsa_KeyPair = new KeyPair( KeyPair.ALG_RSA_CRT, KeyBuilder.LENGTH_RSA_2048 );
//super();
try
//TheBuffer = new byte[100];
rsa_KeyPair = new KeyPair( KeyPair.ALG_RSA_CRT, KeyBuilder.LENGTH_RSA_512 );
//rsa_PublicKey.setExponent (TheBuffer, (short)0, (short)1);
rsa_KeyPair.genKeyPair();
rsa_PublicKey = (RSAPublicKey) rsa_KeyPair.getPublic();
//rsa_PrivateCrtKey = (RSAPrivateCrtKey) rsa_KeyPair.getPrivate();
rsa_PrivateKey = (RSAPrivateKey) rsa_KeyPair.getPrivate();
//buffer = new byte[2048];
cipherRSA = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
}catch (CryptoException ex){
ISOException.throwIt((short) (ex.getReason()));
//register(bArray, (short) (bOffset), bArray[bOffset]);
public static void install(byte[] bArray, short bOffset, byte bLength) {
// GP-compliant JavaCard applet registration
new RSAencry().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
public void process(APDU apdu) {
// Good practice: Return 9000 on SELECT
if (selectingApplet()) {
return;
byte[] buf = apdu.getBuffer();
switch (buf[ISO7816.OFFSET_INS]) {
case (byte) 0x00:
break;
default:
// good practice: If you don't know the INStruction, say so:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}The log shows as below:
(2233 usec)
<= 00 90 00 ...
Status: No Error
Load report:
1358 bytes loaded in 0.0 seconds
effective code size on card:
+ package AID 6
+ applet AIDs 15
+ classes 17
+ methods 138
+ statics 0
+ exports 0
overall 176 bytes
cm> install -i 525341656e637279 -q C9#() 525341656e63 525341656e637279
=> 80 E6 0C 00 1F 06 52 53 41 65 6E 63 08 52 53 41 ......RSAenc.RSA
65 6E 63 72 79 08 52 53 41 65 6E 63 72 79 01 00 encry.RSAencry..
02 C9 00 00 00 .....
(122771 usec)
<= 6A 80 j.
Status: Wrong data
jcshell: Error code: 6a80 (Wrong data)
jcshell: Wrong response APDU: 6A80
Unexpected error; aborting execution
I almost removed all other codes, but it still can not intalled in card emulator.
Does anyone can tell me that's why?
Edited by: 949003 on 2012-8-3 上午8:05
Edited by: 949003 on 2012-8-3 上午8:07Thanks Shane
I even removed those senteces.
public class RSAencry extends Applet {
private KeyPair rsa_KeyPair;
Cipher cipherRSA;
//constructor
private RSAencry()
try
new KeyPair( KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048 );
rsa_KeyPair.genKeyPair();
}catch (CryptoException ex){
ISOException.throwIt((short) (ex.getReason()));
//register(bArray, (short) (bOffset), bArray[bOffset]);
public static void install(byte[] bArray, short bOffset, byte bLength) {
// GP-compliant JavaCard applet registration
new RSAencry().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
public void process(APDU apdu) {
// Good practice: Return 9000 on SELECT
if (selectingApplet()) {
return;
byte[] buf = apdu.getBuffer();
switch (buf[ISO7816.OFFSET_INS]) {
case (byte) 0x00:
break;
default:
// good practice: If you don't know the INStruction, say so:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}and I still got this log
Status: No Error
Load report:
1089 bytes loaded in 0.0 seconds
effective code size on card:
+ package AID 6
+ applet AIDs 15
+ classes 17
+ methods 101
+ statics 0
+ exports 0
overall 139 bytes
cm> install -i 525341656e637279 -q C9#() 525341656e63 525341656e637279
=> 80 E6 0C 00 1F 06 52 53 41 65 6E 63 08 52 53 41 ......RSAenc.RSA
65 6E 63 72 79 08 52 53 41 65 6E 63 72 79 01 00 encry.RSAencry..
02 C9 00 00 00 .....
(7334 usec)
<= 6A 80 j.
Status: Wrong data
jcshell: Error code: 6a80 (Wrong data)
jcshell: Wrong response APDU: 6A80
Unexpected error; aborting execution -
Newbie Simple app issue most likely related to user coding error
I'm fairly new to the Cyberflex infrastructure and most likely the issue is with my CODE. Basically, I wrote a simple java cardlet without much error checking to try to retrieve a stored object on the card such as a userId. What I think I'm missing or don't understand is how to capture the incoming APDU and respond to it within the process method.
Error:
I keep getting a [6C 01] status word return code? Is this a valid Status Word?
Environment Setup:
Compiler: jdk1.3.1
Axalto SDK: 4.4
Card: Cyberflex e-gate 32k (not personalized and it has no pin assigned to it)
OS: Windows 2K
Any help will be greatly appreciated.
Thank you in advance,
Alfredo
Here is the code:
package Simple.JavaCard;
import javacard.framework.*;
public class SimpleJcardTest extends javacard.framework.Applet
/**======================================
*Global/constants
*=======================================*/
byte userId[];
final static short MAX_USER_ID_SIZE = ( short )10;
/**=====================================
* Defining APDU Instructions that the
* card response to
*======================================*/
// User Defined CLA byte for the command APDU header
final static byte CLA = ( byte )0xB0;
//User Defined INS byte for the command APDU header
final static byte GET_USER_ID = ( byte )0x02;
//User Defined applet-specific return status words.
/**====================================
*Constructor -Create object,initialize
* the object, register the applet instance
*=====================================*/
protected SimpleJcardTest(byte[] bArray, short bOffset, byte bLength )
//1. Create the object(s)
userId = new byte[MAX_USER_ID_SIZE];
//2. Initialize the object(s)
userId[0] = 0x4a; // J
userId[1] = 0x6f; // o
userId[2] = 0x68; // h
userId[3] = 0x6e; // n
userId[4] = 0x00; //
userId[5] = 0x00; //
userId[6] = 0x00; //
userId[7] = 0x00; //
userId[8] = 0x00; //
userId[9] = 0x00; //
//3. Register the applet instance
register();
/**====================================
*Install the applet -- creates an instance
*of the Applet Main entry point into the applet
*=====================================*/
public static void install(byte[] bArray, short bOffset, byte bLength )
//bArray - contains installation parameters.
//bOffset - contains the starting offset into the array.
//bLength - contains the length of the parameter data in the
// array.
//installation parameters are loaded onto the smart
//card when the applet is installed
new SimpleJcardTest(bArray, bOffset, bLength);
/**====================================
*Wait in a suspended state until being selected by the JCRE
*Executed after being initialized
*=====================================*/
public boolean select()
return true;
/**=====================================
*Process an incoming APDU command
*Executed after the applet is selected
*======================================*/
public void process(APDU apdu) throws ISOException
//apdu - The JCRE creates an APDU object as a way to
// communicate a command APDU to a Java Card applet
// and to receive a response APDU from the Java Card applet.
// All incoming requests from the host application are sent
// to the applet's process method for processing.
// First five bytes CLA, INS, P1, P2, P3 ]
// [Note: minimal error checking for sample purpose]
byte[] buffer = apdu.getBuffer(); //Get a reference to the APDU buffer
this.getUserId(apdu); //Get the UserId stored on the Card
private void getUserId(APDU apdu)
byte[] buffer = apdu.getBuffer();
// Move the UserId data into the APDU buffer
// starting at the offset
// src - source byte array
// srcOff - offset within source byte array to
// start copy from
// dest - destination byte array
// destOff - offset within destination byte array
// to start copy into
// length - byte length to be copied
Util.arrayCopy(userId,(short)0,buffer,ISO7816.OFFSET_CDATA,MAX_USER_ID_SIZE);
// 1.Inform system that the applet has finished processing the
// command and the system should now prepare to construct a
// response APDU which contains data field.
// 2. Params
// ISO7816.OFFSET_CDATA
// - The offset into APDU buffer
// MAX_USER_ID_SIZE
// - The bytelength of the data to send
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, MAX_USER_ID_SIZE);An oversight on my part that was discovered by a second set of eyes.
1. Invalid expected return size was specified.
final static short MAX_USER_ID_SIZE = ( short )10;
needed to be changed to
final static short MAX_USER_ID_SIZE = ( short )0xA;
2. The calling apdu needed to be modified to
B0 02 00 00 0A
Well I hope this helps others as well -
Install error -look at the code. plz help
I have the simple applet that I'm able to compile and load on to a JCOP10 cartd. When I try to install the applet so that I can start interacting with it, I get the following error. How do I go beyond this point? I'll appreciate your help.
JCOP shell
Load report:
747 bytes loaded in 0.0 seconds
effective code size on card:
+ package AID 6
+ applet AIDs 13
+ classes 21
+ methods 470
+ statics 0
+ exports 0
overall 510 bytes
end
/set-var J 0
while ${J} < ${PKG_${I}_APP_COUNT}
install -i ${PKG_${I}_APP_${J}_INST_AID} -q C9#(${PKG_${I}_APP_${J}_INST_DATA}) ${PKG_${I}_AID} ${PKG_${I}_APP_${J}_AID}
=> 80 E6 0C 00 24 06 11 11 11 11 11 11 06 22 22 22 ....$........"""
22 22 22 06 22 22 22 22 22 33 01 00 0B C9 09 23 """."""""3.....#
42 38 47 36 74 63 76 73 00 00 B8G6tcvs..
(0 msec)
<= 6A 80 j.
Status: Wrong data
Error code: 6a80 (Wrong data)
Offending APDU: 6A80
Here is the code.
* Package: myWallet
* Filename: MyWallet.java
* Class: MyWallet
* Date: Jan 23, 2004 2:01:58 PM
package myWallet;
import javacard.framework.*;
//import javacardx.framework.*;
public class MyWallet extends Applet
/* constants declaration */
// code of CLA byte in the command APDU header
final static byte Wallet_CLA =(byte)0x80;
// codes of INS byte in the command APDU header
final static byte VERIFY = (byte) 0x20;
final static byte CREDIT = (byte) 0x30;
final static byte DEBIT = (byte) 0x40;
final static byte GET_BALANCE = (byte) 0x50;
// maximum balance
final static short MAX_BALANCE = (byte)0x7FFF;
// maximum transaction amount
final static byte MAX_TRANSACTION_AMOUNT =(byte)0x007F;
// maximum number of incorrect tries before the
// PIN is blocked
final static byte PIN_TRY_LIMIT =(byte)0x03;
// maximum size PIN
final static byte MAX_PIN_SIZE =(byte)0x08;
// signal that the PIN verification failed
final static short SW_VERIFICATION_FAILED = 0x6300;
// signal the the PIN validation is required
// for a credit or a debit transaction
final static short SW_PIN_VERIFICATION_REQUIRED = 0x6301;
// signal invalid transaction amount
// amount > MAX_TRANSACTION_AMOUNT or amount < 0
final static short SW_INVALID_TRANSACTION_AMOUNT = 0x6A83;
// signal that the balance exceed the maximum
final static short SW_EXCEED_MAXIMUM_BALANCE = 0x6A84;
// signal the the balance becomes negative
final static short SW_NEGATIVE_BALANCE = 0x6A85;
/* instance variables declaration */
OwnerPIN pin;
short balance;
private MyWallet (byte[] bArray,short bOffset,byte bLength)
// It is good programming practice to allocate
// all the memory that an applet needs during
// its lifetime inside the constructor
pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
byte iLen = bArray[bOffset]; // aid length
bOffset = (short) (bOffset+iLen+1);
byte cLen = bArray[bOffset]; // info length
bOffset = (short) (bOffset+cLen+1);
byte aLen = bArray[bOffset]; // applet data length
// The installation parameters contain the PIN
// initialization value
pin.update(bArray, (short)(bOffset+1), aLen);
register();
} // end of the constructor
public static void install(byte[] bArray, short bOffset, byte bLength){
// create a Wallet applet instance
MyWallet me = new MyWallet(bArray, bOffset, bLength);
me.register(bArray, bOffset, bLength);
} // end of install method
public boolean select()
// The applet declines to be selected
// if the pin is blocked.
if ( pin.getTriesRemaining() == 0 )
return false;
return true;
}// end of select method
public void deselect() {
// reset the pin value
pin.reset();
public void process(APDU apdu) {
// APDU object carries a byte array (buffer) to
// transfer incoming and outgoing APDU header
// and data bytes between card and CAD
// At this point, only the first header bytes
// [CLA, INS, P1, P2, P3] are available in
// the APDU buffer.
// The interface javacard.framework.ISO7816
// declares constants to denote the offset of
// these bytes in the APDU buffer
byte[] buffer = apdu.getBuffer();
// check SELECT APDU command
buffer[ISO7816.OFFSET_CLA] = (byte)(buffer[ISO7816.OFFSET_CLA] & (byte)0xFC);
if ((buffer[ISO7816.OFFSET_CLA] == 0) &&
(buffer[ISO7816.OFFSET_INS] == (byte)(0xA4)) )
return;
// verify the reset of commands have the
// correct CLA byte, which specifies the
// command structure
if (buffer[ISO7816.OFFSET_CLA] != Wallet_CLA)
ISOException.throwIt
(ISO7816.SW_CLA_NOT_SUPPORTED);
switch (buffer[ISO7816.OFFSET_INS]) {
case GET_BALANCE: getBalance(apdu);
return;
case DEBIT: debit(apdu);
return;
case CREDIT: credit(apdu);
return;
case VERIFY: verify(apdu);
return;
default: ISOException.throwIt (ISO7816.SW_INS_NOT_SUPPORTED);
} // end of process method
private void credit(APDU apdu)
// access authentication
if ( ! pin.isValidated() )
ISOException.throwIt(
SW_PIN_VERIFICATION_REQUIRED);
byte[] buffer = apdu.getBuffer();
// Lc byte denotes the number of bytes in the
// data field of the command APDU
byte numBytes = buffer[ISO7816.OFFSET_LC];
// indicate that this APDU has incoming data
// and receive data starting from the offset
// ISO7816.OFFSET_CDATA following the 5 header
// bytes.
byte byteRead =
(byte)(apdu.setIncomingAndReceive());
// it is an error if the number of data bytes
// read does not match the number in Lc byte
if ( ( numBytes != 1 ) || (byteRead != 1) )
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
// get the credit amount
byte creditAmount = buffer[ISO7816.OFFSET_CDATA];
// check the credit amount
if ( ( creditAmount > MAX_TRANSACTION_AMOUNT)
|| ( creditAmount < 0 ) )
ISOException.throwIt
(SW_INVALID_TRANSACTION_AMOUNT);
// check the new balance
if ( (short)( balance + creditAmount) > MAX_BALANCE )
ISOException.throwIt
(SW_EXCEED_MAXIMUM_BALANCE);
// credit the amount
balance = (short)(balance + creditAmount);
} // end of deposit method
private void debit(APDU apdu)
// access authentication
if ( ! pin.isValidated() )
ISOException.throwIt
(SW_PIN_VERIFICATION_REQUIRED);
byte[] buffer = apdu.getBuffer();
byte numBytes =
(byte)(buffer[ISO7816.OFFSET_LC]);
byte byteRead =
(byte)(apdu.setIncomingAndReceive());
if ( ( numBytes != 1 ) || (byteRead != 1) )
ISOException.throwIt
(ISO7816.SW_WRONG_LENGTH);
// get debit amount
byte debitAmount =
buffer[ISO7816.OFFSET_CDATA];
// check debit amount
if ( ( debitAmount > MAX_TRANSACTION_AMOUNT)
|| ( debitAmount < 0 ) )
ISOException.throwIt
(SW_INVALID_TRANSACTION_AMOUNT);
// check the new balance
if ( (short)( balance - debitAmount ) < (short)0 )
ISOException.throwIt(SW_NEGATIVE_BALANCE);
balance = (short) (balance - debitAmount);
} // end of debit method
private void getBalance(APDU apdu) {
byte[] buffer = apdu.getBuffer();
// inform system that the applet has finished
// processing the command and the system should
// now prepare to construct a response APDU
// which contains data field
short le = apdu.setOutgoing();
if ( le < 2 )
ISOException.throwIt
(ISO7816.SW_WRONG_LENGTH);
//informs the CAD the actual number of bytes
//returned
apdu.setOutgoingLength((byte)2);
// move the balance data into the APDU buffer
// starting at the offset 0
buffer[0] = (byte)(balance >> 8);
buffer[1] = (byte)(balance & 0xFF);
// send the 2-byte balance at the offset
// 0 in the apdu buffer
apdu.sendBytes((short)0, (short)2);
} // end of getBalance method
private void verify(APDU apdu) {
byte[] buffer = apdu.getBuffer();
// retrieve the PIN data for validation.
byte byteRead =(byte)(apdu.setIncomingAndReceive());
// check pin
// the PIN data is read into the APDU buffer
// at the offset ISO7816.OFFSET_CDATA
// the PIN data length = byteRead
if ( pin.check(buffer, ISO7816.OFFSET_CDATA,byteRead) == false )
ISOException.throwIt(SW_VERIFICATION_FAILED);
} // end of validate method
} // end of class WalletHow do I set a breakpoint in my install method in order to identify the error?
I've tried changing my install method and making it look exactly like the sample wallet applications accompanying the javacard kit, but I'm still getting the same error? here else could be the possible source of the error?
Thomas
Maybe you are looking for
-
Error in PipelineManager while creating new payment group
Hi Everyone, I am trying to create a new payment group for purchasing an item with the reward points. i am trying to modify the pipeline flow by overriding commercePipeline.xml. i have added the following lines of code in that xml. commercepipelin
-
How to save file in km using web dynpro abap
Hi Experts, We have a requirement that file should be saved in a folder in km, the name of the folder should be the employee number. Could you please tell me how to create folder with employee number in KM and store file in it using web dynpro abap.
-
Hi I have recently upgraded a project from CFMX7 to CF8. The problem I'm having is that I have a number of subdomains which are setup. Each of these subdomains contains an Application file at the root, and a folder called administration. This folder
-
Error in PC "Message no. RSPC065" .
Hi All, I have a problem in Process chain. When I execuite any process chain it is giving the following Error Message. Please any body can help me in this. Error message is: "Job BI_PROCESS_COMPRESS could not be scheduled. Termination with returncod
-
Some 'in msg' photos not showing
a target=_blank href="postimages/origimage_1_3137624.jpg"><img border=0 src="postimages/image_1_3137624.jpg"></a> not working in FF 7.01. Images not showing up