From 6ad2676e8c2659470572ddddc88a9d37e30ec5fa Mon Sep 17 00:00:00 2001 From: Nikita Mikhailov Date: Sat, 9 Apr 2016 16:03:31 +0600 Subject: OTG: Add/update javadoc; rename methods, exceptions --- .../keychain/smartcard/NfcTransport.java | 21 +++- .../keychain/smartcard/SmartcardDevice.java | 49 ++++---- .../keychain/smartcard/Transport.java | 30 ++++- .../keychain/smartcard/TransportIoException.java | 20 ---- .../smartcard/UsbConnectionDispatcher.java | 54 +++++++++ .../keychain/smartcard/UsbConnectionManager.java | 54 --------- .../keychain/smartcard/UsbTransport.java | 123 ++++++++++++++------- .../keychain/smartcard/UsbTransportException.java | 20 ++++ .../ui/base/BaseSecurityTokenNfcActivity.java | 21 +--- 9 files changed, 225 insertions(+), 167 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/TransportIoException.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbConnectionDispatcher.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbConnectionManager.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbTransportException.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/NfcTransport.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/NfcTransport.java index e47ba5360..e3c6d12da 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/NfcTransport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/NfcTransport.java @@ -19,13 +19,23 @@ public class NfcTransport implements Transport { this.mTag = tag; } + /** + * Transmit and receive data + * @param data data to transmit + * @return received data + * @throws IOException + */ @Override - public byte[] sendAndReceive(final byte[] data) throws TransportIoException, IOException { + public byte[] transceive(final byte[] data) throws IOException { return mIsoCard.transceive(data); } + /** + * Disconnect and release connection + */ @Override public void release() { + // Not supported } @Override @@ -33,13 +43,18 @@ public class NfcTransport implements Transport { return mIsoCard != null && mIsoCard.isConnected(); } + /** + * Check if Transport supports persistent connections e.g connections which can + * handle multiple operations in one session + * @return true if transport supports persistent connections + */ @Override - public boolean allowPersistentConnection() { + public boolean isPersistentConnectionAllowed() { return false; } /** - * Handle NFC communication and return a result. + * Connect to NFC device. *

* On general communication, see also * http://www.cardwerk.com/smartcards/smartcard_standard_ISO7816-4_annex-a.aspx diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/SmartcardDevice.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/SmartcardDevice.java index 286a38d1f..7bc53a10a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/SmartcardDevice.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/SmartcardDevice.java @@ -39,7 +39,6 @@ public class SmartcardDevice { return LazyHolder.mSmartcardDevice; } - // METHOD UPDATED [OK] private String getHolderName(String name) { try { String slength; @@ -80,6 +79,7 @@ public class SmartcardDevice { this.mAdminPin = adminPin; } + // NEW MY METHOD public void changeKey(CanonicalizedSecretKey secretKey, Passphrase passphrase) throws IOException { long keyGenerationTimestamp = secretKey.getCreationTime().getTime() / 1000; byte[] timestampBytes = ByteBuffer.allocate(4).putInt((int) keyGenerationTimestamp).array(); @@ -102,7 +102,7 @@ public class SmartcardDevice { putData(keyType.getTimestampObjectId(), timestampBytes); } - public boolean containsKey(KeyType keyType) throws IOException { + private boolean containsKey(KeyType keyType) throws IOException { return !keyMatchesFingerPrint(keyType, BLANK_FINGERPRINT); } @@ -110,10 +110,17 @@ public class SmartcardDevice { return java.util.Arrays.equals(getMasterKeyFingerprint(keyType.getIdx()), fingerprint); } - // METHOD UPDATED OK + /** + * Connect to device and select pgp applet + * + * @throws IOException + */ public void connectToDevice() throws IOException { + // Connect on transport layer mTransport.connect(); + // Connect on smartcard layer + // SW1/2 0x9000 is the generic "ok" response, which we expect most of the time. // See specification, page 51 String accepted = "9000"; @@ -164,7 +171,6 @@ public class SmartcardDevice { * @param pw For PW1, this is 0x81. For PW3 (Admin PIN), mode is 0x83. * @param newPin The new PW1 or PW3. */ - // METHOD UPDATED[OK] public void modifyPin(int pw, byte[] newPin) throws IOException { final int MAX_PW1_LENGTH_INDEX = 1; final int MAX_PW3_LENGTH_INDEX = 3; @@ -210,7 +216,6 @@ public class SmartcardDevice { * @param encryptedSessionKey the encoded session key * @return the decoded session key */ - // METHOD UPDATED [OK] public byte[] decryptSessionKey(byte[] encryptedSessionKey) throws IOException { if (!mPw1ValidatedForDecrypt) { verifyPin(0x82); // (Verify PW1 with mode 82 for decryption) @@ -280,7 +285,6 @@ public class SmartcardDevice { * @param dataObject The data object to be stored. * @param data The data to store in the object */ - // METHOD UPDATED [OK] public void putData(int dataObject, byte[] data) throws IOException { if (data.length > 254) { throw new IOException("Cannot PUT DATA with length > 254"); @@ -315,7 +319,6 @@ public class SmartcardDevice { * 0xB8: Decipherment Key * 0xA4: Authentication Key */ - // METHOD UPDATED [OK] public void putKey(int slot, CanonicalizedSecretKey secretKey, Passphrase passphrase) throws IOException { if (slot != 0xB6 && slot != 0xB8 && slot != 0xA4) { @@ -426,10 +429,9 @@ public class SmartcardDevice { * * @return The fingerprints of all subkeys in a contiguous byte array. */ - // METHOD UPDATED [OK] public byte[] getFingerprints() throws IOException { String data = "00CA006E00"; - byte[] buf = mTransport.sendAndReceive(Hex.decode(data)); + byte[] buf = mTransport.transceive(Hex.decode(data)); Iso7816TLV tlv = Iso7816TLV.readSingle(buf, true); Log.d(Constants.TAG, "nfcGetFingerprints() Iso7816TLV tlv data:\n" + tlv.prettyPrint()); @@ -446,19 +448,16 @@ public class SmartcardDevice { * * @return Seven bytes in fixed format, plus 0x9000 status word at the end. */ - // METHOD UPDATED [OK] private byte[] getPwStatusBytes() throws IOException { String data = "00CA00C400"; - return mTransport.sendAndReceive(Hex.decode(data)); + return mTransport.transceive(Hex.decode(data)); } - // METHOD UPDATED [OK] public byte[] getAid() throws IOException { String info = "00CA004F00"; - return mTransport.sendAndReceive(Hex.decode(info)); + return mTransport.transceive(Hex.decode(info)); } - // METHOD UPDATED [OK] public String getUserId() throws IOException { String info = "00CA006500"; return getHolderName(communicate(info)); @@ -470,7 +469,6 @@ public class SmartcardDevice { * @param hash the hash for signing * @return a big integer representing the MPI for the given hash */ - // METHOD UPDATED [OK] public byte[] calculateSignature(byte[] hash, int hashAlgo) throws IOException { if (!mPw1ValidatedForSignature) { verifyPin(0x81); // (Verify PW1 with mode 81 for signing) @@ -568,29 +566,23 @@ public class SmartcardDevice { return Hex.decode(signature); } - public boolean isConnected() { - return mTransport != null && mTransport.isConnected(); - } - /** * Transceive data via NFC encoded as Hex */ - // METHOD UPDATED [OK] - private String communicate(String apdu) throws IOException, TransportIoException { - return getHex(mTransport.sendAndReceive(Hex.decode(apdu))); + private String communicate(String apdu) throws IOException { + return getHex(mTransport.transceive(Hex.decode(apdu))); } public Transport getTransport() { return mTransport; } - // NEW METHOD [OK] public boolean isFidesmoToken() { if (isConnected()) { // Check if we can still talk to the card try { // By trying to select any apps that have the Fidesmo AID prefix we can // see if it is a Fidesmo device or not - byte[] mSelectResponse = mTransport.sendAndReceive(Apdu.select(FIDESMO_APPS_AID_PREFIX)); + byte[] mSelectResponse = mTransport.transceive(Apdu.select(FIDESMO_APPS_AID_PREFIX)); // Compare the status returned by our select with the OK status code return Apdu.hasStatus(mSelectResponse, Apdu.OK_APDU); } catch (IOException e) { @@ -614,7 +606,6 @@ public class SmartcardDevice { * @return the public key data objects, in TLV format. For RSA this will be the public modulus * (0x81) and exponent (0x82). These may come out of order; proper TLV parsing is required. */ - // NEW METHOD [OK] public byte[] generateKey(int slot) throws IOException { if (slot != 0xB6 && slot != 0xB8 && slot != 0xA4) { throw new IOException("Invalid key slot"); @@ -641,7 +632,6 @@ public class SmartcardDevice { return Hex.decode(publicKeyData); } - // NEW METHOD [OK][OK] private String getDataField(String output) { return output.substring(0, output.length() - 4); } @@ -665,7 +655,6 @@ public class SmartcardDevice { * This works by entering a wrong PIN and then Admin PIN 4 times respectively. * Afterwards, the token is reactivated. */ - // NEW METHOD [OK] public void resetAndWipeToken() throws IOException { String accepted = "9000"; @@ -725,7 +714,11 @@ public class SmartcardDevice { } public boolean isPersistentConnectionAllowed() { - return mTransport != null && mTransport.allowPersistentConnection(); + return mTransport != null && mTransport.isPersistentConnectionAllowed(); + } + + public boolean isConnected() { + return mTransport != null && mTransport.isConnected(); } private static class LazyHolder { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/Transport.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/Transport.java index 5252a95d0..fa8b0695a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/Transport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/Transport.java @@ -2,14 +2,40 @@ package org.sufficientlysecure.keychain.smartcard; import java.io.IOException; +/** + * Abstraction for transmitting APDU commands + */ public interface Transport { - byte[] sendAndReceive(byte[] data) throws IOException; + /** + * Transmit and receive data + * @param data data to transmit + * @return received data + * @throws IOException + */ + byte[] transceive(byte[] data) throws IOException; + /** + * Disconnect and release connection + */ void release(); + /** + * Check if device is was connected to and still is connected + * @return connection status + */ boolean isConnected(); - boolean allowPersistentConnection(); + /** + * Check if Transport supports persistent connections e.g connections which can + * handle multiple operations in one session + * @return true if transport supports persistent connections + */ + boolean isPersistentConnectionAllowed(); + + /** + * Connect to device + * @throws IOException + */ void connect() throws IOException; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/TransportIoException.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/TransportIoException.java deleted file mode 100644 index 544dd4045..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/TransportIoException.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.sufficientlysecure.keychain.smartcard; - -import java.io.IOException; - -public class TransportIoException extends IOException { - public TransportIoException() { - } - - public TransportIoException(final String detailMessage) { - super(detailMessage); - } - - public TransportIoException(final String message, final Throwable cause) { - super(message, cause); - } - - public TransportIoException(final Throwable cause) { - super(cause); - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbConnectionDispatcher.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbConnectionDispatcher.java new file mode 100644 index 000000000..c3068916e --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbConnectionDispatcher.java @@ -0,0 +1,54 @@ +package org.sufficientlysecure.keychain.smartcard; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbManager; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.ui.UsbEventReceiverActivity; +import org.sufficientlysecure.keychain.util.Log; + +public class UsbConnectionDispatcher { + private Activity mActivity; + + private OnDiscoveredUsbDeviceListener mListener; + /** + * Receives broadcast when a supported USB device get permission. + */ + private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + + if (UsbEventReceiverActivity.ACTION_USB_PERMISSION.equals(action)) { + UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + boolean permission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, + false); + if (permission) { + Log.d(Constants.TAG, "Got permission for " + usbDevice.getDeviceName()); + mListener.usbDeviceDiscovered(usbDevice); + } + } + } + }; + + public UsbConnectionDispatcher(final Activity activity, final OnDiscoveredUsbDeviceListener listener) { + this.mActivity = activity; + this.mListener = listener; + } + + public void onStart() { + final IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(UsbEventReceiverActivity.ACTION_USB_PERMISSION); + + mActivity.registerReceiver(mUsbReceiver, intentFilter); + } + + public void onStop() { + mActivity.unregisterReceiver(mUsbReceiver); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbConnectionManager.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbConnectionManager.java deleted file mode 100644 index 8a6971fe6..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbConnectionManager.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.sufficientlysecure.keychain.smartcard; - -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbManager; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.ui.UsbEventReceiverActivity; -import org.sufficientlysecure.keychain.util.Log; - -public class UsbConnectionManager { - private Activity mActivity; - - private OnDiscoveredUsbDeviceListener mListener; - /** - * Receives broadcast when a supported USB device get permission. - */ - private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - - if (UsbEventReceiverActivity.ACTION_USB_PERMISSION.equals(action)) { - UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - boolean permission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, - false); - if (permission) { - Log.d(Constants.TAG, "Got permission for " + usbDevice.getDeviceName()); - mListener.usbDeviceDiscovered(usbDevice); - } - } - } - }; - - public UsbConnectionManager(final Activity activity, final OnDiscoveredUsbDeviceListener listener) { - this.mActivity = activity; - this.mListener = listener; - } - - public void onStart() { - final IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(UsbEventReceiverActivity.ACTION_USB_PERMISSION); - - mActivity.registerReceiver(mUsbReceiver, intentFilter); - } - - public void onStop() { - mActivity.unregisterReceiver(mUsbReceiver); - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbTransport.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbTransport.java index 2a21c10dd..86f4a687d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbTransport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbTransport.java @@ -19,9 +19,14 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; +/** + * Based on USB CCID Specification rev. 1.1 + * http://www.usb.org/developers/docs/devclass_docs/DWG_Smart-Card_CCID_Rev110.pdf + * Implements small subset of these features + */ public class UsbTransport implements Transport { - private static final int CLASS_SMARTCARD = 11; - private static final int TIMEOUT = 20 * 1000; // 2 s + private static final int USB_CLASS_SMARTCARD = 11; + private static final int TIMEOUT = 20 * 1000; // 20s private final UsbManager mUsbManager; private final UsbDevice mUsbDevice; @@ -29,29 +34,24 @@ public class UsbTransport implements Transport { private UsbEndpoint mBulkIn; private UsbEndpoint mBulkOut; private UsbDeviceConnection mConnection; - private byte mCounter = 0; + private byte mCounter; - public UsbTransport(final UsbDevice usbDevice, final UsbManager usbManager) { + public UsbTransport(UsbDevice usbDevice, UsbManager usbManager) { mUsbDevice = usbDevice; mUsbManager = usbManager; } - 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 { + /** + * Manage ICC power, Yubikey requires to power on ICC + * Spec: 6.1.1 PC_to_RDR_IccPowerOn; 6.1.2 PC_to_RDR_IccPowerOff + * + * @param on true to turn ICC on, false to turn it off + * @throws UsbTransportException + */ + private void iccPowerSet(boolean on) throws UsbTransportException { final byte[] iccPowerOn = { - 0x62, + (byte) (on ? 0x62 : 0x63), 0x00, 0x00, 0x00, 0x00, 0x00, mCounter++, @@ -63,22 +63,28 @@ public class UsbTransport implements Transport { } /** - * Get first class 11 (Chip/Smartcard) interface for the device + * Get first class 11 (Chip/Smartcard) interface of 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) { + private static UsbInterface getSmartCardInterface(UsbDevice device) { for (int i = 0; i < device.getInterfaceCount(); i++) { - final UsbInterface anInterface = device.getInterface(i); - if (anInterface.getInterfaceClass() == CLASS_SMARTCARD) { + UsbInterface anInterface = device.getInterface(i); + if (anInterface.getInterfaceClass() == USB_CLASS_SMARTCARD) { return anInterface; } } return null; } + /** + * Get device's bulk-in and bulk-out endpoints + * + * @param usbInterface usb device interface + * @return pair of builk-in and bulk-out endpoints respectively + */ @NonNull private static Pair getIoEndpoints(final UsbInterface usbInterface) { UsbEndpoint bulkIn = null, bulkOut = null; @@ -97,43 +103,77 @@ public class UsbTransport implements Transport { return new Pair<>(bulkIn, bulkOut); } + /** + * Release interface and disconnect + */ @Override public void release() { mConnection.releaseInterface(mUsbInterface); mConnection.close(); + mConnection = null; } + /** + * Check if device is was connected to and still is connected + * @return true if device is connected + */ @Override public boolean isConnected() { - // TODO: redo return mConnection != null && mUsbManager.getDeviceList().containsValue(mUsbDevice); } + /** + * Check if Transport supports persistent connections e.g connections which can + * handle multiple operations in one session + * @return true if transport supports persistent connections + */ @Override - public boolean allowPersistentConnection() { + public boolean isPersistentConnectionAllowed() { return true; } + /** + * Connect to OTG device + * @throws IOException + */ @Override public void connect() throws IOException { + mCounter = 0; mUsbInterface = getSmartCardInterface(mUsbDevice); - // throw if mUsbInterface == null + if (mUsbInterface == null) { + // Shouldn't happen as we whitelist only class 11 devices + throw new UsbTransportException("USB error: device doesn't have class 11 interface"); + } + final Pair ioEndpoints = getIoEndpoints(mUsbInterface); mBulkIn = ioEndpoints.first; mBulkOut = ioEndpoints.second; - // throw if any endpoint is null + + if (mBulkIn == null || mBulkOut == null) { + throw new UsbTransportException("USB error: invalid class 11 interface"); + } mConnection = mUsbManager.openDevice(mUsbDevice); - // throw if connection is null - mConnection.claimInterface(mUsbInterface, true); - // check result + if (mConnection == null) { + throw new UsbTransportException("USB error: failed to connect to device"); + } + + if (!mConnection.claimInterface(mUsbInterface, true)) { + throw new UsbTransportException("USB error: failed to claim interface"); + } - powerOn(); + iccPowerSet(true); Log.d(Constants.TAG, "Usb transport connected"); } + /** + * Transmit and receive data + * @param data data to transmit + * @return received data + * @throws UsbTransportException + */ @Override - public byte[] sendAndReceive(byte[] data) throws TransportIoException { + public byte[] transceive(byte[] data) throws UsbTransportException { send(data); byte[] bytes; do { @@ -141,10 +181,11 @@ public class UsbTransport implements Transport { } while (isXfrBlockNotReady(bytes)); checkXfrBlockResult(bytes); + // Discard header return Arrays.copyOfRange(bytes, 10, bytes.length); } - public void send(byte[] d) throws TransportIoException { + private void send(byte[] d) throws UsbTransportException { int l = d.length; byte[] data = Arrays.concatenate(new byte[]{ 0x6f, @@ -163,7 +204,7 @@ public class UsbTransport implements Transport { } } - public byte[] receive() throws TransportIoException { + private byte[] receive() throws UsbTransportException { byte[] buffer = new byte[mBulkIn.getMaxPacketSize()]; byte[] result = null; int readBytes = 0, totalBytes = 0; @@ -171,11 +212,11 @@ public class UsbTransport implements Transport { do { int res = mConnection.bulkTransfer(mBulkIn, buffer, buffer.length, TIMEOUT); if (res < 0) { - throw new TransportIoException("USB error, failed to receive response " + res); + throw new UsbTransportException("USB error: failed to receive response " + res); } if (result == null) { if (res < 10) { - throw new TransportIoException("USB error, failed to receive ccid header"); + throw new UsbTransportException("USB-CCID error: failed to receive CCID header"); } totalBytes = ByteBuffer.wrap(buffer, 1, 4).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer().get() + 10; result = new byte[totalBytes]; @@ -187,10 +228,10 @@ public class UsbTransport implements Transport { return result; } - private void sendRaw(final byte[] data) throws TransportIoException { + private void sendRaw(final byte[] data) throws UsbTransportException { final int tr1 = mConnection.bulkTransfer(mBulkOut, data, data.length, TIMEOUT); if (tr1 != data.length) { - throw new TransportIoException("USB error, failed to send data " + tr1); + throw new UsbTransportException("USB error: failed to transmit data " + tr1); } } @@ -198,10 +239,10 @@ public class UsbTransport implements Transport { return (byte) ((bytes[7] >> 6) & 0x03); } - private void checkXfrBlockResult(byte[] bytes) throws TransportIoException { + private void checkXfrBlockResult(byte[] bytes) throws UsbTransportException { final byte status = getStatus(bytes); if (status != 0) { - throw new TransportIoException("CCID error, status " + status + " error code: " + Hex.toHexString(bytes, 8, 1)); + throw new UsbTransportException("USB-CCID error: status " + status + " error code: " + Hex.toHexString(bytes, 8, 1)); } } @@ -209,10 +250,6 @@ public class UsbTransport implements Transport { return getStatus(bytes) == 2; } - public UsbDevice getUsbDevice() { - return mUsbDevice; - } - @Override public boolean equals(final Object o) { if (this == o) return true; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbTransportException.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbTransportException.java new file mode 100644 index 000000000..27635137f --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbTransportException.java @@ -0,0 +1,20 @@ +package org.sufficientlysecure.keychain.smartcard; + +import java.io.IOException; + +public class UsbTransportException extends IOException { + public UsbTransportException() { + } + + public UsbTransportException(final String detailMessage) { + super(detailMessage); + } + + public UsbTransportException(final String message, final Throwable cause) { + super(message, cause); + } + + public UsbTransportException(final Throwable cause) { + super(cause); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java index e138af895..f3c3cbe75 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java @@ -40,11 +40,12 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; +import org.sufficientlysecure.keychain.smartcard.CardException; import org.sufficientlysecure.keychain.smartcard.NfcTransport; import org.sufficientlysecure.keychain.smartcard.OnDiscoveredUsbDeviceListener; import org.sufficientlysecure.keychain.smartcard.SmartcardDevice; import org.sufficientlysecure.keychain.smartcard.Transport; -import org.sufficientlysecure.keychain.smartcard.UsbConnectionManager; +import org.sufficientlysecure.keychain.smartcard.UsbConnectionDispatcher; import org.sufficientlysecure.keychain.smartcard.UsbTransport; import org.sufficientlysecure.keychain.ui.CreateKeyActivity; import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity; @@ -72,7 +73,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity protected SmartcardDevice mSmartcardDevice = SmartcardDevice.getInstance(); protected TagDispatcher mTagDispatcher; - protected UsbConnectionManager mUsbDispatcher; + protected UsbConnectionDispatcher mUsbDispatcher; private boolean mTagHandlingEnabled; private byte[] mSmartcardFingerprints; @@ -201,7 +202,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity super.onCreate(savedInstanceState); mTagDispatcher = TagDispatcher.get(this, this, false, false, true, false); - mUsbDispatcher = new UsbConnectionManager(this, this); + mUsbDispatcher = new UsbConnectionDispatcher(this, this); // Check whether we're recreating a previously destroyed instance if (savedInstanceState != null) { @@ -423,20 +424,6 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity } - public class CardException extends IOException { - private short mResponseCode; - - public CardException(String detailMessage, short responseCode) { - super(detailMessage); - mResponseCode = responseCode; - } - - public short getResponseCode() { - return mResponseCode; - } - - } - /** * Ask user if she wants to install PGP onto her Fidesmo token */ -- cgit v1.2.3