diff options
5 files changed, 74 insertions, 93 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/BaseJavacardDevice.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/BaseJavacardDevice.java index 46f4c0443..f81d234b3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/BaseJavacardDevice.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/BaseJavacardDevice.java @@ -22,7 +22,7 @@ public class BaseJavacardDevice implements JavacardDevice {      private static final String FIDESMO_APPS_AID_PREFIX = "A000000617";      private static final byte[] BLANK_FINGERPRINT = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -    private final Transport mTransport; +    private Transport mTransport;      private Passphrase mPin;      private Passphrase mAdminPin; @@ -32,8 +32,7 @@ public class BaseJavacardDevice implements JavacardDevice {      private boolean mPw3Validated;      private boolean mTagHandlingEnabled; -    public BaseJavacardDevice(final Transport mTransport) { -        this.mTransport = mTransport; +    public BaseJavacardDevice() {      }      private static String getHex(byte[] raw) { @@ -528,6 +527,9 @@ public class BaseJavacardDevice implements JavacardDevice {          String response = nfcCommunicate(apdu); +        if (response.length() < 4) { +            throw new CardException("Bad response", (short) 0); +        }          // split up response into signature and status          String status = response.substring(response.length() - 4);          String signature = response.substring(0, response.length() - 4); @@ -722,4 +724,9 @@ public class BaseJavacardDevice implements JavacardDevice {          return fp;      } +    @Override +    public void setTransport(Transport mTransport) { +        this.mTransport = mTransport; + +    }  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/CachingBaseJavacardDevice.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/CachingBaseJavacardDevice.java deleted file mode 100644 index 5ad157de1..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/CachingBaseJavacardDevice.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.sufficientlysecure.keychain.javacard; - -import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey; -import org.sufficientlysecure.keychain.util.Passphrase; - -import java.io.IOException; - -public class CachingBaseJavacardDevice extends BaseJavacardDevice { -    private byte[] mFingerprintsCache; -    private String mUserIdCache; -    private byte[] mAidCache; - -    public CachingBaseJavacardDevice(final Transport mTransport) { -        super(mTransport); -    } - -    @Override -    public byte[] getFingerprints() throws IOException { -        if (mFingerprintsCache == null) { -            mFingerprintsCache = super.getFingerprints(); -        } -        return mFingerprintsCache; -    } - -    @Override -    public String getUserId() throws IOException { -        if (mUserIdCache == null) { -            mUserIdCache = super.getUserId(); -        } -        return mUserIdCache; -    } - -    @Override -    public byte[] getAid() throws IOException { -        if (mAidCache == null) { -            mAidCache = super.getAid(); -        } -        return mAidCache; -    } - -    @Override -    public void changeKey(final CanonicalizedSecretKey secretKey, final Passphrase passphrase) throws IOException { -        super.changeKey(secretKey, passphrase); -        mFingerprintsCache = null; -    } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/JavacardDevice.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/JavacardDevice.java index 04c2c0006..63d4d2ad7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/JavacardDevice.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/JavacardDevice.java @@ -100,4 +100,6 @@ public interface JavacardDevice {       * @param data       The data to store in the object       */      void putData(int dataObject, byte[] data) throws IOException; + +    void setTransport(Transport mTransport);  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbConnectionManager.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbConnectionManager.java index d140c771c..9dd3bc028 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbConnectionManager.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbConnectionManager.java @@ -8,6 +8,8 @@ import android.content.Intent;  import android.content.IntentFilter;  import android.hardware.usb.UsbDevice;  import android.hardware.usb.UsbManager; +import android.os.Handler; +import android.os.Looper;  import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.util.Log; @@ -17,50 +19,29 @@ import java.util.HashMap;  import java.util.Set;  import java.util.concurrent.ConcurrentHashMap;  import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicBoolean;  public class UsbConnectionManager {      private static final String LOG_TAG = UsbConnectionManager.class.getName();      private static final String ACTION_USB_PERMISSION = Constants.PACKAGE_NAME + ".USB_PERMITSSION"; - -    private Activity mActivity; -    private OnDiscoveredUsbDeviceListener mListener;      private final Semaphore mRunning = new Semaphore(1);      private final Set<UsbDevice> mProcessedDevices = Collections.newSetFromMap(new ConcurrentHashMap<UsbDevice, Boolean>()); - -    /** -     * Receives broadcast when a supported USB device is attached, detached or -     * when a permission to communicate to the device has been granted. -     */ -    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { -        @Override -        public void onReceive(Context context, Intent intent) { -            String action = intent.getAction(); -            UsbDevice usbDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); -            String deviceName = usbDevice.getDeviceName(); - -            if (ACTION_USB_PERMISSION.equals(action)) { -                boolean permission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, -                        false); -                Log.d(LOG_TAG, "ACTION_USB_PERMISSION: " + permission + " Device: " + deviceName); - -                interceptIntent(intent); - -                context.unregisterReceiver(mUsbReceiver); -            } -        } -    }; - +    private final AtomicBoolean mStopped = new AtomicBoolean(false); +    private Activity mActivity;      private final Thread mWatchThread = new Thread() {          @Override          public void run() {              final UsbManager usbManager = (UsbManager) mActivity.getSystemService(Context.USB_SERVICE); -            while (true) { -                mRunning.acquireUninterruptibly(); +            while (!mStopped.get()) { +                try { +                    mRunning.acquire(); +                } catch (InterruptedException e) { +                }                  mRunning.release(); +                if (mStopped.get()) return;                  // -                  final UsbDevice device = getDevice(usbManager);                  if (device != null && !mProcessedDevices.contains(device)) {                      mProcessedDevices.add(device); @@ -71,6 +52,7 @@ public class UsbConnectionManager {                      filter.addAction(ACTION_USB_PERMISSION);                      mActivity.registerReceiver(mUsbReceiver, filter); +                    Log.d(LOG_TAG, "Requesting permission for " + device.getDeviceName());                      usbManager.requestPermission(device, PendingIntent.getBroadcast(mActivity, 0, intent, 0));                  } @@ -81,6 +63,30 @@ public class UsbConnectionManager {              }          }      }; +    private OnDiscoveredUsbDeviceListener mListener; +    /** +     * Receives broadcast when a supported USB device is attached, detached or +     * when a permission to communicate to the device has been granted. +     */ +    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { +        @Override +        public void onReceive(Context context, Intent intent) { +            String action = intent.getAction(); +            UsbDevice usbDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); +            String deviceName = usbDevice.getDeviceName(); + +            if (ACTION_USB_PERMISSION.equals(action)) { +                boolean permission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, +                        false); +                Log.d(LOG_TAG, "ACTION_USB_PERMISSION: " + permission + " Device: " + deviceName); + +                interceptIntent(intent); + +                context.unregisterReceiver(mUsbReceiver); +            } +        } +    }; +    private Handler handler = new Handler(Looper.getMainLooper());      public UsbConnectionManager(final Activity activity, final OnDiscoveredUsbDeviceListener listener) {          this.mActivity = activity; @@ -89,6 +95,16 @@ public class UsbConnectionManager {          mWatchThread.start();      } +    private static UsbDevice getDevice(UsbManager manager) { +        HashMap<String, UsbDevice> deviceList = manager.getDeviceList(); +        for (UsbDevice device : deviceList.values()) { +            if (device.getVendorId() == 0x1050 && device.getProductId() == 0x0112) { +                return device; +            } +        } +        return null; +    } +      public void startListeningForDevices() {          mRunning.release();      } @@ -100,7 +116,7 @@ public class UsbConnectionManager {      public void interceptIntent(final Intent intent) {          if (intent == null || intent.getAction() == null) return;          switch (intent.getAction()) { -            case UsbManager.ACTION_USB_DEVICE_ATTACHED: { +            /*case UsbManager.ACTION_USB_DEVICE_ATTACHED: {                  final UsbManager usbManager = (UsbManager) mActivity.getSystemService(Context.USB_SERVICE);                  final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);                  Intent usbI = new Intent(mActivity, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); @@ -109,7 +125,7 @@ public class UsbConnectionManager {                  PendingIntent pi = PendingIntent.getActivity(mActivity, 0, usbI, PendingIntent.FLAG_CANCEL_CURRENT);                  usbManager.requestPermission(device, pi);                  break; -            } +            }*/              case ACTION_USB_PERMISSION: {                  UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);                  if (device != null) @@ -121,15 +137,11 @@ public class UsbConnectionManager {          }      } -    private static UsbDevice getDevice(UsbManager manager) { -        HashMap<String, UsbDevice> deviceList = manager.getDeviceList(); -        for (UsbDevice device : deviceList.values()) { -            Log.d(LOG_TAG, device.getDeviceName() + " " + device.getDeviceId()); -            if (device.getVendorId() == 0x1050 && device.getProductId() == 0x0112) { -                Log.d(LOG_TAG, device.getDeviceName() + " OK"); -                return device; -            } +    public void onDestroy() { +        mStopped.set(true); +        try { +            mActivity.unregisterReceiver(mUsbReceiver); +        } catch (IllegalArgumentException ignore) {          } -        return null;      }  } 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 573123daf..e3c331b0b 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 @@ -74,7 +74,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity      private static final String FIDESMO_APP_PACKAGE = "com.fidesmo.sec.android"; -    public JavacardDevice mJavacardDevice; +    public JavacardDevice mJavacardDevice = new BaseJavacardDevice();      protected TagDispatcher mTagDispatcher;      protected UsbConnectionManager mUsbDispatcher;      private boolean mTagHandlingEnabled; @@ -451,7 +451,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity              throw new IsoDepNotSupportedException("Tag does not support ISO-DEP (ISO 14443-4)");          } -        mJavacardDevice = new BaseJavacardDevice(new NfcTransport(isoCard)); +        mJavacardDevice.setTransport(new NfcTransport(isoCard));          mJavacardDevice.connectToDevice();          doNfcInBackground(); @@ -459,7 +459,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity      protected void handleUsbDevice(UsbDevice device) throws IOException {          UsbManager usbManager = (UsbManager) getSystemService(USB_SERVICE); -        mJavacardDevice = new BaseJavacardDevice(new UsbTransport(device, usbManager)); +        mJavacardDevice.setTransport(new UsbTransport(device, usbManager));          mJavacardDevice.connectToDevice();          doNfcInBackground(); @@ -567,4 +567,10 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity          }          return mAppInstalled;      } + +    @Override +    protected void onDestroy() { +        super.onDestroy(); +        mUsbDispatcher.onDestroy(); +    }  }  | 
