//---------------------------------------------------------------------------------------
// Useful tools for high level commands to the smart card
// file: ICC.java
// used by: ScanCmds.java
// For comments see header of ScanCmds.java.
//---------------------------------------------------------------------------------------
package scpack;
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; // maximum length of a APDU in byte
static final int CAPDU_CLA = 0; // index of class within a command APDU
static final int CAPDU_INS = 1; // index of instruction 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 CLA_NOT_FOUND = 1;
static final byte INS_NOT_FOUND = 2;
static final byte INS_FOUND = 3;
// coding and description of typical smart cards commands
static final byte[] NOTSCAN_INS = {(byte)0x02, (byte)0x07}; // not scanned instructions
private PassThruCardService ptcs;
// dummy case 1 command
// CLA || INS || P1 || P2 || P3
static final byte[] CMD_DUMMY = {(byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00 };
// Returncode '6Exx': class not supported
static final byte RC_CLA_NOT_SUPPORTED = (byte) 0x6E;
// Returncode '6Dxx': instruction not supported
static final byte RC_INS_NOT_SUPPORTED = (byte) 0x6D;
// Returncode '68xx': function in class byte not supported ???
static final byte RC_CLA_FCT_NOT_SUPPORTED = (byte) 0x68;
/** 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
/** send a command to the smart card
* @param cla class byte of the command
* @param ins instruction byte of the command
* @return evaluated return code of the command
*/
public byte sendCmd(int cla, int ins) {
byte sw1 = 0;
CommandAPDU command = new CommandAPDU(MAX_APDU_SIZE); // create APDU buffer and set size
command.setLength(0);
command.append(CMD_DUMMY);
command.setByte(CAPDU_CLA, cla); // set first page to write the pattern ????
command.setByte(CAPDU_INS, ins); // set last page to write the pattern
try {
if (ScanCmds.DEBUG == true) {
ScanCmds.showText ("\tDebug: " + ScanCmds.formatCmdAPDU(command.getBytes(), command.getLength()) + "\n"); // command APDU
} //if
ResponseAPDU response = ptcs.sendCommandAPDU(command);
sw1 = (byte) response.getByte(RAPDU_SW1);
if (ScanCmds.DEBUG == true) {
ScanCmds.showText ("\tDebug: " + ScanCmds.formatRspAPDU(response.getBytes(),response.getLength()) + "\n"); // response APDU
} // if
} // try
catch (Exception e) {
System.err.println("caught exception '" + e.getClass() + "' - " + e.getMessage() );
System.exit(0);
} // catch
if ((byte) sw1 == (byte) RC_CLA_NOT_SUPPORTED) {
return CLA_NOT_FOUND;
} // if
if ((byte) sw1 == (byte) RC_INS_NOT_SUPPORTED) {
return INS_NOT_FOUND;
} // if
return INS_FOUND;
} // sendCmd
} // class
//---------------------------------------------------------------------------------------