aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbTransport.java
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbTransport.java')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbTransport.java226
1 files changed, 0 insertions, 226 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbTransport.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbTransport.java
deleted file mode 100644
index 07697f11e..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbTransport.java
+++ /dev/null
@@ -1,226 +0,0 @@
-package org.sufficientlysecure.keychain.javacard;
-
-import android.hardware.usb.UsbConstants;
-import android.hardware.usb.UsbDevice;
-import android.hardware.usb.UsbDeviceConnection;
-import android.hardware.usb.UsbEndpoint;
-import android.hardware.usb.UsbInterface;
-import android.hardware.usb.UsbManager;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.Pair;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-public class UsbTransport implements Transport {
- private static final int CLASS_SMARTCARD = 11;
- private static final int TIMEOUT = 20 * 1000; // 2 s
-
- private final UsbManager mUsbManager;
- private final UsbDevice mUsbDevice;
- private final UsbInterface mUsbInterface;
- private final UsbEndpoint mBulkIn;
- private final UsbEndpoint mBulkOut;
- private final UsbDeviceConnection mConnection;
- private byte mCounter = 0;
-
- public UsbTransport(final UsbDevice usbDevice, final UsbManager usbManager) throws TransportIoException {
- mUsbDevice = usbDevice;
- mUsbManager = usbManager;
-
- mUsbInterface = getSmartCardInterface(mUsbDevice);
- // throw if mUsbInterface == null
- final Pair<UsbEndpoint, UsbEndpoint> ioEndpoints = getIoEndpoints(mUsbInterface);
- mBulkIn = ioEndpoints.first;
- mBulkOut = ioEndpoints.second;
- // throw if any endpoint is null
-
- mConnection = mUsbManager.openDevice(mUsbDevice);
- // throw if connection is null
- mConnection.claimInterface(mUsbInterface, true);
- // check result
-
- powerOn();
-
- setTimings();
- }
-
- private void setTimings() throws TransportIoException {
- byte[] data = {
- 0x6C,
- 0x00, 0x00, 0x00, 0x00,
- 0x00,
- mCounter++,
- 0x00, 0x00, 0x00
- };
- sendRaw(data);
- data = receive();
-
- data[0] = 0x61;
- data[1] = 0x04;
- data[2] = data[3] = data[4] = 0x00;
- data[5] = 0x00;
- data[6] = mCounter++;
- data[7] = 0x00;
- data[8] = data[9] = 0x00;
-
- data[13] = 1;
-
- sendRaw(data);
- receive();
- }
-
- private void powerOff() throws TransportIoException {
- final byte[] iccPowerOff = {
- 0x63,
- 0x00, 0x00, 0x00, 0x00,
- 0x00,
- mCounter++,
- 0x00,
- 0x00, 0x00
- };
- sendRaw(iccPowerOff);
- receive();
- }
-
- void powerOn() throws TransportIoException {
- final byte[] iccPowerOn = {
- 0x62,
- 0x00, 0x00, 0x00, 0x00,
- 0x00,
- mCounter++,
- 0x00,
- 0x00, 0x00
- };
- sendRaw(iccPowerOn);
- receive();
- }
-
- /**
- * Get first class 11 (Chip/Smartcard) interface for the device
- *
- * @param device {@link UsbDevice} which will be searched
- * @return {@link UsbInterface} of smartcard or null if it doesn't exist
- */
- @Nullable
- private static UsbInterface getSmartCardInterface(final UsbDevice device) {
- for (int i = 0; i < device.getInterfaceCount(); i++) {
- final UsbInterface anInterface = device.getInterface(i);
- if (anInterface.getInterfaceClass() == CLASS_SMARTCARD) {
- return anInterface;
- }
- }
- return null;
- }
-
- @NonNull
- private static Pair<UsbEndpoint, UsbEndpoint> getIoEndpoints(final UsbInterface usbInterface) {
- UsbEndpoint bulkIn = null, bulkOut = null;
- for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
- final UsbEndpoint endpoint = usbInterface.getEndpoint(i);
- if (endpoint.getType() != UsbConstants.USB_ENDPOINT_XFER_BULK) {
- continue;
- }
-
- if (endpoint.getDirection() == UsbConstants.USB_DIR_IN) {
- bulkIn = endpoint;
- } else if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
- bulkOut = endpoint;
- }
- }
- return new Pair<>(bulkIn, bulkOut);
- }
-
- @Override
- public void release() {
- mConnection.releaseInterface(mUsbInterface);
- mConnection.close();
- }
-
- @Override
- public boolean isConnected() {
- // TODO: redo
- return mUsbManager.getDeviceList().containsValue(mUsbDevice);
- }
-
- @Override
- public byte[] sendAndReceive(byte[] data) throws TransportIoException {
- send(data);
- byte[] bytes;
- do {
- bytes = receive();
- } while (isXfrBlockNotReady(bytes));
-
- checkXfrBlockResult(bytes);
- return Arrays.copyOfRange(bytes, 10, bytes.length);
- }
-
- public void send(byte[] d) throws TransportIoException {
- int l = d.length;
- byte[] data = Arrays.concatenate(new byte[]{
- 0x6f,
- (byte) l, (byte) (l >> 8), (byte) (l >> 16), (byte) (l >> 24),
- 0x00,
- mCounter++,
- 0x00,
- 0x00, 0x00},
- d);
-
- int send = 0;
- while (send < data.length) {
- final int len = Math.min(mBulkIn.getMaxPacketSize(), data.length - send);
- sendRaw(Arrays.copyOfRange(data, send, send + len));
- send += len;
- }
- }
-
- public byte[] receive() throws TransportIoException {
- byte[] buffer = new byte[mBulkIn.getMaxPacketSize()];
- byte[] result = null;
- int readBytes = 0, totalBytes = 0;
-
- do {
- int res = mConnection.bulkTransfer(mBulkIn, buffer, buffer.length, TIMEOUT);
- if (res < 0) {
- throw new TransportIoException("USB error, failed to receive response " + res);
- }
- if (result == null) {
- if (res < 10) {
- throw new TransportIoException("USB error, failed to receive ccid header");
- }
- totalBytes = ByteBuffer.wrap(buffer, 1, 4).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer().get() + 10;
- result = new byte[totalBytes];
- }
- System.arraycopy(buffer, 0, result, readBytes, res);
- readBytes += res;
- } while (readBytes < totalBytes);
-
- return result;
- }
-
- private void sendRaw(final byte[] data) throws TransportIoException {
- final int tr1 = mConnection.bulkTransfer(mBulkOut, data, data.length, TIMEOUT);
- if (tr1 != data.length) {
- throw new TransportIoException("USB error, failed to send data " + tr1);
- }
- }
-
- private byte getStatus(byte[] bytes) {
- return (byte) ((bytes[7] >> 6) & 0x03);
- }
-
- private void checkXfrBlockResult(byte[] bytes) throws TransportIoException {
- final byte status = getStatus(bytes);
- if (status != 0) {
- throw new TransportIoException("CCID error, status " + status + " error code: " + Hex.toHexString(bytes, 8, 1));
- }
- }
-
- private boolean isXfrBlockNotReady(byte[] bytes) {
- return getStatus(bytes) == 2;
- }
-}