// SimpleOCF
// Demo for using the OCF 1.2 with PC/SC to transmit data to and from a Smart Card.
// File: SimpleOCF.java
//
// This program uses the PassThruCardService from OCF opencard.opt.util package.
// Additional informations and reference implementation see www.opencard.org.
// Testet with Towitoko Chipdrive micro on USB port and the appropriate PC/SC drivers
// from Towitoko on Windows 98. Testet with Omnikey CardMan Dongle 6020 on USB port
// and the appropriate PC/SC drivers from Omnikey on Windows 2000.
// Made with JBuilder 6 and JDK 1.3.1.
//
// Uses OCFPCSC1.DLL, OCFPCSC1.DLL, pcsc-wrapper-2.0.jar, base-core.jar, base-opt.jar
// from OCF 1.2
// The content of the file "opencard.properties" must be changed to:
// OpenCard.terminals = com.ibm.opencard.terminal.pcsc10.Pcsc10CardTerminalFactory
//
// This demo works with an ISO/IEC 7816-4 smart card with an > 10 byte transparent EF
// with FID=0001 and no access conditions direct under the MF. This demo works also with
// a simple SIM/USIM smart card, but this will throw some error mesages from the smart card.
//
// This source code is under GNU general public license (see www.opensource.org for details).
// Please send corrections and ideas for extensions to Wolfgang Rankl (www.wrankl.de)
// Copyright 2003-2004 by Wolfgang Rankl, Munich
//
// 10. July 2004 - V11, rw: some simplifications, migrate to PC/SC wrapper 2.0,
// 6th published version
// 10. March 2004 - V10, rw: minor clarifications, 5th published version
// 15. Dez. 2003 - V 9, rw: minor clarifications, add GPL statement
// 4th published version
// 23. Jan. 2003 - V 8, rw: simplifications byte to int conversion, test with new
// card reader, review of the source code, 3rd published version
// 30. Sept. 2002 - V 7, rw: documentation clarifications, 2nd published version
// 27. Sept. 2002 - V 6, rw: extended documentation, 1st published version
// 25. Sept. 2002 - V 5, rw: simplifying source, bug fix for ATR receiving
// 18. Sept. 2002 - V 4, rw: show content of ATR
// 17. Sept. 2002 - V 3, rw: usage of different commands, simplifying the code
// 16. Sept. 2002 - V 2, rw: improvement of the documentation, minor changes
// 12. Sept. 2002 - V 1, rw: initial runnable version
//---------------------------------------------------------------------------------------
import java.util.*;
import opencard.core.service.*;
import opencard.core.terminal.*;
import opencard.opt.util.*;
public class SimpleOCF {
private static final int IFD_TIMEOUT = 10; // unit: seconds
private static final int MAX_APDU_SIZE = 100; // unit: byte
// command ISO/IEC 7816-4 SELECT FILE (select the MF, with no response data = '0C')
// CLA || INS || P1 || P2 || Lc || DATA 1 (= FID high) || DATA 2 (= FID low)
final byte[] CMD_SELECT_MF = {(byte)0x00, (byte)0xA4,
(byte)0x00, (byte)0x0C, (byte)0x02,
(byte)0x3F, (byte)0x00 };
// command ISO/IEC 7816-4 SELECT FILE (select the EF with FID = 0001
// and no response data = '0C')
// CLA || INS || P1 || P2 || Lc || DATA 1 (= FID high) || DATA 2 (= FID low)
final byte[] CMD_SELECT_EF0001 ={(byte)0x00, (byte)0xA4,
(byte)0x00, (byte)0x0C, (byte)0x02,
(byte)0x00, (byte)0x01 };
// command ISO/IEC 7816-4 READ BINARY (read 16 byte with no offset from
// a selected file with transparent structure)
// CLA || INS || P1 || P2 || Le (= length of expected data)
final byte[] CMD_READ_BINARY ={(byte)0x00, (byte)0xB0,
(byte)0x00, (byte)0x00, (byte)0x10 };
private int n, x;
private byte[] i;
public SimpleOCF() {
// create system properties object
Properties sysProps = System.getProperties();
// set system properties for OCF, PC/SC and PassThruCardServce
sysProps.put ("OpenCard.terminals", "com.ibm.opencard.terminal.pcsc10.Pcsc10CardTerminalFactory");
sysProps.put ("OpenCard.services", "opencard.opt.util.PassThruCardServiceFactory");
} // SimpleOCF
public void runExample() {
try {
System.out.println("activate Smart Card");
SmartCard.start(); // activate smart card
CardRequest cr = new CardRequest(CardRequest.ANYCARD, null, PassThruCardService.class);
cr.setTimeout(IFD_TIMEOUT); // set timeout for IFD
// wait for a smart card inserted into the terminal
System.out.println("wait for smart card - insert smart card in terminal");
SmartCard sc = SmartCard.waitForCard(cr);
if (sc != null) { // no error occur and a smart card is in the terminal
PassThruCardService ptcs = (PassThruCardService) sc.getCardService(PassThruCardService.class, true);
System.out.print("ATR: ");
CardID cardID = sc.getCardID ();
i = cardID.getATR();
String s = new String();
for (n = 0; n < i.length; n++) {
x = (int) (0x000000FF & i[n]); // byte to int conversion
s = Integer.toHexString(x).toUpperCase();
if (s.length() == 1) s = "0" + s;
System.out.print(s + " ");
} // for
System.out.println("");
// set APDU buffer size
CommandAPDU command = new CommandAPDU(MAX_APDU_SIZE); // create APDU buffer and set size
//----- prepare command APDU - SELECT FILE
command.append(CMD_SELECT_MF);
// send command and receive response
ResponseAPDU response = ptcs.sendCommandAPDU(command);
// show command apdu
System.out.print("Command-APDU: ");
for (n = 0; n<command.getLength(); n++) {
s = Integer.toHexString(command.getByte(n)).toUpperCase();
if (s.length() == 1) s = "0" + s;
System.out.print(s + " ");
} // for
System.out.println("");
// show response apdu
System.out.print("Response-APDU: ");
for (n = 0; n < response.getLength(); n++) {
s = Integer.toHexString(response.getByte(n)).toUpperCase();
if (s.length() == 1) s = "0" + s;
System.out.print(s + " ");
} // for
System.out.println("");
//----- prepare command APDU - SELECT FILE
command.setLength(0);
command.append(CMD_SELECT_EF0001);
// send command and receive response
response = ptcs.sendCommandAPDU(command);
// show command apdu
System.out.print("Command-APDU: ");
for (n = 0; n < command.getLength(); n++) {
s = Integer.toHexString(command.getByte(n)).toUpperCase();
if (s.length() == 1) s = "0" + s;
System.out.print(s + " ");
} // for
System.out.println("");
// show int response apdu
System.out.print("Response-APDU: ");
for (n=0; n<response.getLength(); n++) {
s = Integer.toHexString(response.getByte(n)).toUpperCase();
if (s.length() == 1) s = "0" + s;
System.out.print(s + " ");
} // for
System.out.println("");
//----- prepare command APDU - READ BINARY
command.setLength(0);
command.append(CMD_READ_BINARY);
// send command and receive response
response = ptcs.sendCommandAPDU(command);
// show command apdu
System.out.print("Command-APDU: ");
for (n = 0; n < command.getLength(); n++) {
s = Integer.toHexString(command.getByte(n)).toUpperCase();
if (s.length() == 1) s = "0" + s;
System.out.print(s + " ");
} // for
System.out.println("");
// show response apdu
System.out.print("Response-APDU: ");
for (n = 0; n < response.getLength(); n++) {
s = Integer.toHexString(response.getByte(n)).toUpperCase();
if (s.length() == 1) s = "0" + s;
System.out.print(s + " ");
} // for
System.out.println("\ndeactivate Smart Card");
SmartCard.shutdown();
} // if
else System.out.println("could not create smart card object (e.g. no ICC in IFD)");
} // try
catch (Exception e) {
System.err.println("Caught exception '" + e.getClass() + "' - " + e.getMessage() );
} // catch
finally {
System.exit(0);
} // finally
} // run example
public static void main( String [] args ){
System.out.println("---------------\nStart SimpleOCF\n");
SimpleOCF OCFTest = new SimpleOCF();
OCFTest.runExample();
} // main
} // class