OTG: Usb device manager fixes
This commit is contained in:
@@ -22,7 +22,7 @@ public class BaseJavacardDevice implements JavacardDevice {
|
|||||||
private static final String FIDESMO_APPS_AID_PREFIX = "A000000617";
|
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 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 mPin;
|
||||||
private Passphrase mAdminPin;
|
private Passphrase mAdminPin;
|
||||||
@@ -32,8 +32,7 @@ public class BaseJavacardDevice implements JavacardDevice {
|
|||||||
private boolean mPw3Validated;
|
private boolean mPw3Validated;
|
||||||
private boolean mTagHandlingEnabled;
|
private boolean mTagHandlingEnabled;
|
||||||
|
|
||||||
public BaseJavacardDevice(final Transport mTransport) {
|
public BaseJavacardDevice() {
|
||||||
this.mTransport = mTransport;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getHex(byte[] raw) {
|
private static String getHex(byte[] raw) {
|
||||||
@@ -528,6 +527,9 @@ public class BaseJavacardDevice implements JavacardDevice {
|
|||||||
|
|
||||||
String response = nfcCommunicate(apdu);
|
String response = nfcCommunicate(apdu);
|
||||||
|
|
||||||
|
if (response.length() < 4) {
|
||||||
|
throw new CardException("Bad response", (short) 0);
|
||||||
|
}
|
||||||
// split up response into signature and status
|
// split up response into signature and status
|
||||||
String status = response.substring(response.length() - 4);
|
String status = response.substring(response.length() - 4);
|
||||||
String signature = response.substring(0, response.length() - 4);
|
String signature = response.substring(0, response.length() - 4);
|
||||||
@@ -722,4 +724,9 @@ public class BaseJavacardDevice implements JavacardDevice {
|
|||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTransport(Transport mTransport) {
|
||||||
|
this.mTransport = mTransport;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -100,4 +100,6 @@ public interface JavacardDevice {
|
|||||||
* @param data The data to store in the object
|
* @param data The data to store in the object
|
||||||
*/
|
*/
|
||||||
void putData(int dataObject, byte[] data) throws IOException;
|
void putData(int dataObject, byte[] data) throws IOException;
|
||||||
|
|
||||||
|
void setTransport(Transport mTransport);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import android.content.Intent;
|
|||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.hardware.usb.UsbDevice;
|
import android.hardware.usb.UsbDevice;
|
||||||
import android.hardware.usb.UsbManager;
|
import android.hardware.usb.UsbManager;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
@@ -17,16 +19,51 @@ import java.util.HashMap;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public class UsbConnectionManager {
|
public class UsbConnectionManager {
|
||||||
private static final String LOG_TAG = UsbConnectionManager.class.getName();
|
private static final String LOG_TAG = UsbConnectionManager.class.getName();
|
||||||
private static final String ACTION_USB_PERMISSION = Constants.PACKAGE_NAME + ".USB_PERMITSSION";
|
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 Semaphore mRunning = new Semaphore(1);
|
||||||
private final Set<UsbDevice> mProcessedDevices = Collections.newSetFromMap(new ConcurrentHashMap<UsbDevice, Boolean>());
|
private final Set<UsbDevice> mProcessedDevices = Collections.newSetFromMap(new ConcurrentHashMap<UsbDevice, Boolean>());
|
||||||
|
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 (!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);
|
||||||
|
|
||||||
|
final Intent intent = new Intent(ACTION_USB_PERMISSION);
|
||||||
|
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
sleep(1000);
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private OnDiscoveredUsbDeviceListener mListener;
|
||||||
/**
|
/**
|
||||||
* Receives broadcast when a supported USB device is attached, detached or
|
* Receives broadcast when a supported USB device is attached, detached or
|
||||||
* when a permission to communicate to the device has been granted.
|
* when a permission to communicate to the device has been granted.
|
||||||
@@ -49,38 +86,7 @@ public class UsbConnectionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
private Handler handler = new Handler(Looper.getMainLooper());
|
||||||
private final Thread mWatchThread = new Thread() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
final UsbManager usbManager = (UsbManager) mActivity.getSystemService(Context.USB_SERVICE);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
mRunning.acquireUninterruptibly();
|
|
||||||
mRunning.release();
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
final UsbDevice device = getDevice(usbManager);
|
|
||||||
if (device != null && !mProcessedDevices.contains(device)) {
|
|
||||||
mProcessedDevices.add(device);
|
|
||||||
|
|
||||||
final Intent intent = new Intent(ACTION_USB_PERMISSION);
|
|
||||||
|
|
||||||
IntentFilter filter = new IntentFilter();
|
|
||||||
filter.addAction(ACTION_USB_PERMISSION);
|
|
||||||
mActivity.registerReceiver(mUsbReceiver, filter);
|
|
||||||
|
|
||||||
usbManager.requestPermission(device, PendingIntent.getBroadcast(mActivity, 0, intent, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
sleep(1000);
|
|
||||||
} catch (InterruptedException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public UsbConnectionManager(final Activity activity, final OnDiscoveredUsbDeviceListener listener) {
|
public UsbConnectionManager(final Activity activity, final OnDiscoveredUsbDeviceListener listener) {
|
||||||
this.mActivity = activity;
|
this.mActivity = activity;
|
||||||
@@ -89,6 +95,16 @@ public class UsbConnectionManager {
|
|||||||
mWatchThread.start();
|
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() {
|
public void startListeningForDevices() {
|
||||||
mRunning.release();
|
mRunning.release();
|
||||||
}
|
}
|
||||||
@@ -100,7 +116,7 @@ public class UsbConnectionManager {
|
|||||||
public void interceptIntent(final Intent intent) {
|
public void interceptIntent(final Intent intent) {
|
||||||
if (intent == null || intent.getAction() == null) return;
|
if (intent == null || intent.getAction() == null) return;
|
||||||
switch (intent.getAction()) {
|
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 UsbManager usbManager = (UsbManager) mActivity.getSystemService(Context.USB_SERVICE);
|
||||||
final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
|
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);
|
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);
|
PendingIntent pi = PendingIntent.getActivity(mActivity, 0, usbI, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
usbManager.requestPermission(device, pi);
|
usbManager.requestPermission(device, pi);
|
||||||
break;
|
break;
|
||||||
}
|
}*/
|
||||||
case ACTION_USB_PERMISSION: {
|
case ACTION_USB_PERMISSION: {
|
||||||
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
|
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
|
||||||
if (device != null)
|
if (device != null)
|
||||||
@@ -121,15 +137,11 @@ public class UsbConnectionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UsbDevice getDevice(UsbManager manager) {
|
public void onDestroy() {
|
||||||
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
|
mStopped.set(true);
|
||||||
for (UsbDevice device : deviceList.values()) {
|
try {
|
||||||
Log.d(LOG_TAG, device.getDeviceName() + " " + device.getDeviceId());
|
mActivity.unregisterReceiver(mUsbReceiver);
|
||||||
if (device.getVendorId() == 0x1050 && device.getProductId() == 0x0112) {
|
} catch (IllegalArgumentException ignore) {
|
||||||
Log.d(LOG_TAG, device.getDeviceName() + " OK");
|
|
||||||
return device;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
|
|||||||
|
|
||||||
private static final String FIDESMO_APP_PACKAGE = "com.fidesmo.sec.android";
|
private static final String FIDESMO_APP_PACKAGE = "com.fidesmo.sec.android";
|
||||||
|
|
||||||
public JavacardDevice mJavacardDevice;
|
public JavacardDevice mJavacardDevice = new BaseJavacardDevice();
|
||||||
protected TagDispatcher mTagDispatcher;
|
protected TagDispatcher mTagDispatcher;
|
||||||
protected UsbConnectionManager mUsbDispatcher;
|
protected UsbConnectionManager mUsbDispatcher;
|
||||||
private boolean mTagHandlingEnabled;
|
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)");
|
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();
|
mJavacardDevice.connectToDevice();
|
||||||
|
|
||||||
doNfcInBackground();
|
doNfcInBackground();
|
||||||
@@ -459,7 +459,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
|
|||||||
|
|
||||||
protected void handleUsbDevice(UsbDevice device) throws IOException {
|
protected void handleUsbDevice(UsbDevice device) throws IOException {
|
||||||
UsbManager usbManager = (UsbManager) getSystemService(USB_SERVICE);
|
UsbManager usbManager = (UsbManager) getSystemService(USB_SERVICE);
|
||||||
mJavacardDevice = new BaseJavacardDevice(new UsbTransport(device, usbManager));
|
mJavacardDevice.setTransport(new UsbTransport(device, usbManager));
|
||||||
mJavacardDevice.connectToDevice();
|
mJavacardDevice.connectToDevice();
|
||||||
|
|
||||||
doNfcInBackground();
|
doNfcInBackground();
|
||||||
@@ -567,4 +567,10 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
|
|||||||
}
|
}
|
||||||
return mAppInstalled;
|
return mAppInstalled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
mUsbDispatcher.onDestroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user