/*
* eID Applet Project.
* Copyright (C) 2008-2014 FedICT.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version
* 3.0 as published by the Free Software Foundation.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, see
* http://www.gnu.org/licenses/.
*/
package test.be.fedict.eid.applet;
import java.util.ArrayList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.beblue.jna.usb.LibUSB;
import org.beblue.jna.usb.usb_bus;
import org.beblue.jna.usb.usb_config_descriptor;
import org.beblue.jna.usb.usb_device;
import org.beblue.jna.usb.usb_interface;
import org.beblue.jna.usb.usb_interface_descriptor;
import org.junit.Test;
/**
* Tests for libUSB eID access
*
* @author Koen De Causmaecker
*
*/
public class LibUSBTest {
static final Log LOG = LogFactory.getLog(LibUSBTest.class);
private ArrayList<CCIDTerminal> listCCIDTerminals() throws Exception {
LibUSB.libUSB.usb_init();
LibUSB.libUSB.usb_find_busses();
LibUSB.libUSB.usb_find_devices();
usb_bus usbBus = LibUSB.libUSB.usb_get_busses();
ArrayList<CCIDTerminal> al = new ArrayList<CCIDTerminal>();
while (usbBus != null) {
usb_device usbDevice = usbBus.devices;
while (usbDevice != null) {
usb_config_descriptor[] usbConfigDescriptors = (usb_config_descriptor[]) usbDevice.config
.toArray(usbDevice.descriptor.bNumConfigurations);
for (int i = 0; i < usbConfigDescriptors.length; i++) {
usb_interface[] usbInterfaces = (usb_interface[]) usbConfigDescriptors[i].interf
.toArray(usbConfigDescriptors[i].bNumInterfaces);
for (int j = 0; j < usbInterfaces.length; j++) {
usb_interface_descriptor[] usbInterfaceDescriptors = (usb_interface_descriptor[]) usbInterfaces[j].altsetting
.toArray(usbInterfaces[j].num_altsetting);
for (int k = 0; k < usbInterfaceDescriptors.length; k++) {
if (usbInterfaceDescriptors[k].bInterfaceClass == 11) {
CCIDTerminal t = new CCIDTerminal(usbDevice, usbInterfaceDescriptors[k]);
t.setBusNumber(usbBus.location);
t.setDeviceNumber(usbDevice.devnum);
al.add(t);
}
}
}
usbDevice = usbDevice.next;
}
}
usbBus = usbBus.next;
}
return al;
}
@Test
public void testListReaders() throws Exception {
ArrayList<CCIDTerminal> ccidTerminals = listCCIDTerminals();
for (int i = 0; i < ccidTerminals.size(); i++) {
LOG.debug(String.format("Card terminal found. Vendor: 0x%x Product: 0x%x",
ccidTerminals.get(i).getUsbDevice().descriptor.idProduct,
ccidTerminals.get(i).getUsbDevice().descriptor.idVendor));
}
// usb_dev_handle usbDevHandle = LibUSB.libUSB.usb_open(usbDevice);
// int retval = LibUSB.libUSB.usb_set_configuration(usbDevHandle, i);
}
@Test
public void testPowerOn() throws Exception {
ArrayList<CCIDTerminal> ccidTerminals = listCCIDTerminals();
for (int i = 0; i < ccidTerminals.size(); i++) {
CCIDTerminal ct = ccidTerminals.get(i);
ct.open();
ct.powerOff();
byte[] answer = ct.powerOn();
LOG.debug(String.format("Card terminal powered on. ATR: %s", bytesToString(answer)));
ct.close();
}
}
@Test
public void testSelectIdentityFile() throws Exception {
ArrayList<CCIDTerminal> ccidTerminals = listCCIDTerminals();
byte[] apdu = { 0x00, (byte) 0xA4, 0x08, 0x0C, 0x06, 0x3F, 0x00, (byte) 0xDF, 0x01, 0x40, 0x31 }; // Identity
// File
// 00 A4 02 0C 02 3F 00 DF 01 40 31
for (int i = 0; i < ccidTerminals.size(); i++) {
CCIDTerminal ct = ccidTerminals.get(i);
ct.open();
ct.powerOff();
ct.powerOn();
ct.transmit(apdu);
byte[] answer = ct.receive();
LOG.debug(String.format("SELECT Identity file sent. Answer: %s", bytesToString(answer)));
ct.close();
}
}
@Test
public void testReadIdentity() throws Exception {
ArrayList<CCIDTerminal> ccidTerminals = listCCIDTerminals();
byte[] apduSelectIdentity = { 0x00, (byte) 0xA4, 0x08, 0x0C, 0x06, 0x3F, 0x00, (byte) 0xDF, 0x01, 0x40, 0x31 }; // Identity
// File
byte[] apduReadBinary = { 0x00, (byte) 0xB0, 0, 0, (byte) 0x80 };
for (int i = 0; i < ccidTerminals.size(); i++) {
byte[] answer;
apduReadBinary[4] = (byte) 0x80;
CCIDTerminal ct = ccidTerminals.get(i);
ct.open();
ct.getSlotStatus();
answer = ct.powerOn();
LOG.debug(String.format("PowerOn. Answer: %s", bytesToString(answer)));
do {
ct.transmit(apduSelectIdentity);
answer = ct.receive();
LOG.debug(String.format("SELECT Identity file sent. Answer: %s", bytesToString(answer)));
if (!(answer[0] == (byte) 0x90 && answer[1] == 0x00))
throw new RuntimeException("Bad response on select identity file");
ct.transmit(apduReadBinary);
answer = ct.receive();
LOG.debug(String.format("SELECT Read binary sent. Answer: %s", bytesToString(answer)));
if (answer[answer.length - 2] == 0x6C) {//
LOG.debug(String.format("SELECT Read binary: wrong expected length"));
}
apduReadBinary[4] = answer[answer.length - 1];
} while (answer[answer.length - 2] == 0x6C);
ct.close();
}
}
private String bytesToString(byte[] data) {
String dataString = "";
for (int j = 0; j < data.length; j++)
dataString += String.format("%2x ", data[j]);
return dataString;
}
// @Test
// public void waitForCardInsertion throws Exception {
// ArrayList<CCIDTerminal> ccidTerminals = listCCIDTerminals();
// }
}