//---------------------------------------------------------------------------------------
// Useful tools for high level commands to the smart card
// file: ICC.java
// used by: EEPROMTest.java
// For comments see header of EEPROMTest.java.
//---------------------------------------------------------------------------------------
package eeppack;
import java.util.*;
import opencard.core.service.*;
import opencard.core.terminal.*;
import opencard.opt.util.*;
public class ICC {
static final int IFD_TIMEOUT = 0; // unit: seconds
static final int MAX_ATR_LEN = 32; // maximum length of the ATR
static final int MAX_APDU_SIZE = 250; // unit: byte
static final int CAPDU_P1 = 2; // index of P1 within a command APDU
static final int CAPDU_P2 = 3; // index of P2 within a command APDU
static final int CAPDU_D1 = 4 + 1; // index of data byte 1 Le within a command APDU
static final int RAPDU_SW1 = 0; // index of SW1 within a response APDU without data
// return value of some internal methods
static final byte NO_ERROR = 1;
static final byte ERROR_AFTER_WRITE = 2;
static final byte ERROR_AFTER_COMPARE = 3;
private PassThruCardService ptcs;
// proprietary command WRITE NVM
// CLA || INS || P1 (= start page) || P2 (= end page) || Lc || DATA 1 (= pattern)
static final byte[] CMD_WRITENVM = {(byte)0x00, (byte)0x01,
(byte)0x20, (byte)0x20, (byte)0x01,
(byte)0x00};
// proprietary command COMPARE NVM
// CLA || INS || P1 (= start page) || P2 (= end page) || Lc || DATA 1 (= pattern)
static final byte[] CMD_COMPNVM = {(byte)0x00, (byte)0x02,
(byte)0x20, (byte)0x20, (byte)0x01,
(byte)0x00};
// Returncode '9000': command propper executed
static final byte RC_SW1_CMD_PROPPER_EXECUTED = (byte) 0x90;
/** set properties for OCF, PC/SC and PassThruCardServce and activates the smart card
* @return ATR as byte string in hexadecimal coding
*/
public byte[] start() {
byte[] atr = new byte[MAX_ATR_LEN];
// get and set system properties for OCF, PC/SC and PassThruCardServce
Properties sysProps = System.getProperties();
sysProps.put ("OpenCard.terminals", "com.ibm.opencard.terminal.pcsc10.Pcsc10CardTerminalFactory");
sysProps.put ("OpenCard.services", "opencard.opt.util.PassThruCardServiceFactory");
try {
SmartCard.start();
CardRequest cr = new CardRequest(CardRequest.ANYCARD, null, PassThruCardService.class);
cr.setTimeout(IFD_TIMEOUT); // set timeout for IFD
SmartCard sc = SmartCard.waitForCard(cr); // wait for ICC in the IFD
if (sc != null) { // no error occured, a smart card is in the terminal
ptcs = (PassThruCardService) sc.getCardService(PassThruCardService.class, true);
CardID cardID = sc.getCardID();
atr = cardID.getATR();
} // if
} // try
catch (Exception e) {
System.err.println("caught exception '" + e.getClass() + "' - " + e.getMessage() );
} // catch
return atr;
} // start
/** deactivate the smart card
*/
public static void stop() {
try {
SmartCard.shutdown();
} // try
catch (Exception e) {
System.err.println("caught exception '" + e.getClass() + "' - " + e.getMessage() );
System.exit(0);
} // catch
} // stop
/** write a byte pattern in a whole EEPROM page from a first page to a last page
* @param pattern to write into EEPROM
* @param firstpage to write the pattern
* @param lastpage to write the pattern
* @return result of the write operation
*/
public byte write(byte pattern, byte firstpage, byte lastpage) {
CommandAPDU command = new CommandAPDU(MAX_APDU_SIZE); // create APDU buffer and set size
command.setLength(0);
command.append(CMD_WRITENVM);
command.setByte(CAPDU_P1, firstpage); // set first page to write the pattern
command.setByte(CAPDU_P2, lastpage); // set last page to write the pattern
command.setByte(CAPDU_D1, pattern); // set pattern
try {
if (EEPROMTest.DEBUG == true) {
EEPROMTest.showText ("\tDebug: " + EEPROMTest.formatCmdAPDU(command.getBytes(), command.getLength()) + "\n"); // command APDU
} //if
ResponseAPDU response = ptcs.sendCommandAPDU(command);
if (EEPROMTest.DEBUG == true) {
EEPROMTest.showText ("\tDebug: " + EEPROMTest.formatRspAPDU(response.getBytes(),response.getLength()) + "\n"); // response APDU
} // if
if ((byte) response.getByte(RAPDU_SW1) != (byte) RC_SW1_CMD_PROPPER_EXECUTED) {
// a EEPROM write error occur
return ERROR_AFTER_WRITE;
} // if
// no EEPROM write error occured
command.setLength(0);
command.append(CMD_COMPNVM);
command.setByte(CAPDU_P1, firstpage); // set first page to write the pattern
command.setByte(CAPDU_P2, lastpage); // set last page to write the pattern
command.setByte(CAPDU_D1, pattern); // set pattern
if (EEPROMTest.DEBUG == true) {
EEPROMTest.showText("\tDebug: " + EEPROMTest.formatCmdAPDU(command.getBytes(), command.getLength()) + "\n"); // command APDU
} // if
response = ptcs.sendCommandAPDU(command);
if (EEPROMTest.DEBUG == true) {
EEPROMTest.showText("\tDebug: " + EEPROMTest.formatRspAPDU(response.getBytes(),response.getLength()) + "\n"); // response APDU
} // if
if ((byte) response.getByte(RAPDU_SW1) != (byte) RC_SW1_CMD_PROPPER_EXECUTED) {
// a EEPROM write error occur
return ERROR_AFTER_COMPARE;
} // if
} // try
catch (Exception e) {
System.err.println("caught exception '" + e.getClass() + "' - " + e.getMessage() );
System.exit(0);
} // catch
return NO_ERROR;
} // write
} // class
//---------------------------------------------------------------------------------------