aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain
diff options
context:
space:
mode:
authorNikita Mikhailov <nikita.s.mikhailov@gmail.com>2016-04-08 00:41:53 +0600
committerNikita Mikhailov <nikita.s.mikhailov@gmail.com>2016-04-14 22:48:01 +0600
commitb5eb6468fecfc16ea041eb0f4bf48c37ec2e81f2 (patch)
treed9ee439e49649dfdbc81d61431bca22e48d85c34 /OpenKeychain/src/main/java/org/sufficientlysecure/keychain
parent3798249570e97861793f5d0ebc695d94e8d5ddcd (diff)
downloadopen-keychain-b5eb6468fecfc16ea041eb0f4bf48c37ec2e81f2.tar.gz
open-keychain-b5eb6468fecfc16ea041eb0f4bf48c37ec2e81f2.tar.bz2
open-keychain-b5eb6468fecfc16ea041eb0f4bf48c37ec2e81f2.zip
OTG: Add support for persistent usb connection
No need to reinsert token on each operation
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/NfcTransport.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/SmartcardDevice.java49
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/Transport.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbConnectionManager.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbTransport.java39
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateSecurityTokenImportResetFragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java67
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java67
8 files changed, 132 insertions, 111 deletions
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 557c6f37d..d56f5b5bf 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/NfcTransport.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/NfcTransport.java
@@ -28,4 +28,9 @@ public class NfcTransport implements Transport {
public boolean isConnected() {
return mIsoCard.isConnected();
}
+
+ @Override
+ public boolean allowPersistentConnection() {
+ return false;
+ }
}
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 b86c3cf4c..4420c0c88 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/SmartcardDevice.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/SmartcardDevice.java
@@ -32,7 +32,32 @@ public class SmartcardDevice {
private boolean mPw3Validated;
private boolean mTagHandlingEnabled;
- public SmartcardDevice() {
+ protected SmartcardDevice() {
+ }
+
+ public static SmartcardDevice getInstance() {
+ return LazyHolder.mSmartcardDevice;
+ }
+
+ // METHOD UPDATED [OK]
+ private String getHolderName(String name) {
+ try {
+ String slength;
+ int ilength;
+ name = name.substring(6);
+ slength = name.substring(0, 2);
+ ilength = Integer.parseInt(slength, 16) * 2;
+ name = name.substring(2, ilength + 2);
+ name = (new String(Hex.decode(name))).replace('<', ' ');
+ return name;
+ } catch (IndexOutOfBoundsException e) {
+ // try-catch for https://github.com/FluffyKaon/OpenPGP-Card
+ // Note: This should not happen, but happens with
+ // https://github.com/FluffyKaon/OpenPGP-Card, thus return an empty string for now!
+
+ Log.e(Constants.TAG, "Couldn't get holder name, returning empty string!", e);
+ return "";
+ }
}
private static String getHex(byte[] raw) {
@@ -541,15 +566,8 @@ public class SmartcardDevice {
return Hex.decode(signature);
}
- private String getHolderName(String name) {
- String slength;
- int ilength;
- name = name.substring(6);
- slength = name.substring(0, 2);
- ilength = Integer.parseInt(slength, 16) * 2;
- name = name.substring(2, ilength + 2);
- name = (new String(Hex.decode(name))).replace('<', ' ');
- return (name);
+ public boolean isConnected() {
+ return mTransport != null && mTransport.isConnected();
}
/**
@@ -560,8 +578,8 @@ public class SmartcardDevice {
return getHex(mTransport.sendAndReceive(Hex.decode(apdu)));
}
- public boolean isConnected() {
- return mTransport.isConnected();
+ public Transport getTransport() {
+ return mTransport;
}
// NEW METHOD [OK]
@@ -702,6 +720,13 @@ public class SmartcardDevice {
public void setTransport(Transport mTransport) {
this.mTransport = mTransport;
+ }
+
+ public boolean allowPersistentConnection() {
+ return mTransport != null && mTransport.allowPersistentConnection();
+ }
+ private static class LazyHolder {
+ private static final SmartcardDevice mSmartcardDevice = new SmartcardDevice();
}
}
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 e01d7da16..9b0ad2998 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/Transport.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/Transport.java
@@ -8,4 +8,6 @@ public interface Transport {
void release();
boolean isConnected();
+
+ boolean allowPersistentConnection();
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbConnectionManager.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbConnectionManager.java
index 8a6971fe6..e6fb5b04d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbConnectionManager.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbConnectionManager.java
@@ -51,4 +51,12 @@ public class UsbConnectionManager {
public void onStop() {
mActivity.unregisterReceiver(mUsbReceiver);
}
+
+ public void rescanDevices() {
+ final SmartcardDevice smartcardDevice = SmartcardDevice.getInstance();
+ if (smartcardDevice.isConnected()
+ && (smartcardDevice.getTransport() instanceof UsbTransport)) {
+ mListener.usbDeviceDiscovered(((UsbTransport) smartcardDevice.getTransport()).getUsbDevice());
+ }
+ }
}
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 08f296c25..2d435ccbe 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbTransport.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/smartcard/UsbTransport.java
@@ -12,6 +12,8 @@ import android.util.Pair;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Hex;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.util.Log;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -45,33 +47,7 @@ public class UsbTransport implements Transport {
// 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();
+ Log.d(Constants.TAG, "Usb transport connected");
}
private void powerOff() throws TransportIoException {
@@ -148,6 +124,11 @@ public class UsbTransport implements Transport {
}
@Override
+ public boolean allowPersistentConnection() {
+ return true;
+ }
+
+ @Override
public byte[] sendAndReceive(byte[] data) throws TransportIoException {
send(data);
byte[] bytes;
@@ -223,4 +204,8 @@ public class UsbTransport implements Transport {
private boolean isXfrBlockNotReady(byte[] bytes) {
return getStatus(bytes) == 2;
}
+
+ public UsbDevice getUsbDevice() {
+ return mUsbDevice;
+ }
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateSecurityTokenImportResetFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateSecurityTokenImportResetFragment.java
index a0e93ed85..aba06ac47 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateSecurityTokenImportResetFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateSecurityTokenImportResetFragment.java
@@ -249,9 +249,9 @@ public class CreateSecurityTokenImportResetFragment
@Override
public void doNfcInBackground() throws IOException {
- mTokenFingerprints = mCreateKeyActivity.mSmartcardDevice.getFingerprints();
- mTokenAid = mCreateKeyActivity.mSmartcardDevice.getAid();
- mTokenUserId = mCreateKeyActivity.mSmartcardDevice.getUserId();
+ mTokenFingerprints = mCreateKeyActivity.getSmartcardDevice().getFingerprints();
+ mTokenAid = mCreateKeyActivity.getSmartcardDevice().getAid();
+ mTokenUserId = mCreateKeyActivity.getSmartcardDevice().getUserId();
byte[] fp = new byte[20];
ByteBuffer.wrap(fp).put(mTokenFingerprints, 0, 20);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java
index c68936577..5f0093678 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java
@@ -140,6 +140,32 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenNfcActivity
if (mRequiredInput.mType != RequiredInputParcel.RequiredInputType.NFC_MOVE_KEY_TO_CARD
&& mRequiredInput.mType != RequiredInputParcel.RequiredInputType.NFC_RESET_CARD) {
obtainSecurityTokenPin(mRequiredInput);
+ checkPinAvailability();
+ } else {
+ // No need for pin, rescan USB devices
+ mUsbDispatcher.rescanDevices();
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (REQUEST_CODE_PIN == requestCode) {
+ checkPinAvailability();
+ }
+ }
+
+ private void checkPinAvailability() {
+ try {
+ Passphrase passphrase = PassphraseCacheService.getCachedPassphrase(this,
+ mRequiredInput.getMasterKeyId(), mRequiredInput.getSubKeyId());
+ if (passphrase != null) {
+ // Rescan USB devices
+ mUsbDispatcher.rescanDevices();
+ }
+ } catch (PassphraseCacheService.KeyNotFoundException e) {
+ throw new AssertionError(
+ "tried to find passphrase for non-existing key. this is a programming error!");
}
}
@@ -275,28 +301,33 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenNfcActivity
nfcGuideView.setCurrentStatus(NfcGuideView.NfcGuideViewStatus.DONE);
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- // check all 200ms if Security Token has been taken away
- while (true) {
- if (isNfcConnected()) {
- try {
- Thread.sleep(200);
- } catch (InterruptedException ignored) {
+ if (mSmartcardDevice.allowPersistentConnection()) {
+ // Just close
+ finish();
+ } else {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ // check all 200ms if Security Token has been taken away
+ while (true) {
+ if (isNfcConnected()) {
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException ignored) {
+ }
+ } else {
+ return null;
}
- } else {
- return null;
}
}
- }
- @Override
- protected void onPostExecute(Void result) {
- super.onPostExecute(result);
- finish();
- }
- }.execute();
+ @Override
+ protected void onPostExecute(Void result) {
+ super.onPostExecute(result);
+ finish();
+ }
+ }.execute();
+ }
}
/**
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 a6f8c0b0f..ecec98aaf 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
@@ -31,7 +31,6 @@ import android.nfc.TagLostException;
import android.os.AsyncTask;
import android.os.Bundle;
-import org.bouncycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
@@ -41,9 +40,9 @@ 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.SmartcardDevice;
import org.sufficientlysecure.keychain.smartcard.NfcTransport;
import org.sufficientlysecure.keychain.smartcard.OnDiscoveredUsbDeviceListener;
+import org.sufficientlysecure.keychain.smartcard.SmartcardDevice;
import org.sufficientlysecure.keychain.smartcard.UsbConnectionManager;
import org.sufficientlysecure.keychain.smartcard.UsbTransport;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity;
@@ -72,7 +71,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
private static final String FIDESMO_APP_PACKAGE = "com.fidesmo.sec.android";
- public SmartcardDevice mSmartcardDevice = new SmartcardDevice();
+ protected SmartcardDevice mSmartcardDevice = SmartcardDevice.getInstance();
protected TagDispatcher mTagDispatcher;
protected UsbConnectionManager mUsbDispatcher;
private boolean mTagHandlingEnabled;
@@ -175,7 +174,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
public void usbDeviceDiscovered(final UsbDevice device) {
- // Actual NFC operations are executed in doInBackground to not block the UI thread
+ // Actual USB operations are executed in doInBackground to not block the UI thread
if (!mTagHandlingEnabled)
return;
new AsyncTask<Void, Void, IOException>() {
@@ -372,7 +371,6 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
Log.d(Constants.TAG, "BaseNfcActivity.onPause");
mTagDispatcher.disableExclusiveNfc();
-// mUsbDispatcher.stopListeningForDevices();
}
/**
@@ -453,10 +451,15 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
}
protected void handleUsbDevice(UsbDevice device) throws IOException {
- UsbManager usbManager = (UsbManager) getSystemService(USB_SERVICE);
- mSmartcardDevice.setTransport(new UsbTransport(device, usbManager));
- mSmartcardDevice.connectToDevice();
-
+ // Don't reconnect if device was already connected
+ if (!mSmartcardDevice.isConnected()
+ || !(mSmartcardDevice.getTransport() instanceof UsbTransport)
+ || !((UsbTransport) mSmartcardDevice.getTransport()).getUsbDevice().equals(device)) {
+ UsbManager usbManager = (UsbManager) getSystemService(USB_SERVICE);
+
+ mSmartcardDevice.setTransport(new UsbTransport(device, usbManager));
+ mSmartcardDevice.connectToDevice();
+ }
doNfcInBackground();
}
@@ -464,48 +467,6 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
return mSmartcardDevice.isConnected();
}
- /**
- * Parses out the status word from a JavaCard response string.
- *
- * @param response A hex string with the response from the token
- * @return A short indicating the SW1/SW2, or 0 if a status could not be determined.
- */
- short parseCardStatus(String response) {
- if (response.length() < 4) {
- return 0; // invalid input
- }
-
- try {
- return Short.parseShort(response.substring(response.length() - 4), 16);
- } catch (NumberFormatException e) {
- return 0;
- }
- }
-
- public String getHolderName(String name) {
- try {
- String slength;
- int ilength;
- name = name.substring(6);
- slength = name.substring(0, 2);
- ilength = Integer.parseInt(slength, 16) * 2;
- name = name.substring(2, ilength + 2);
- name = (new String(Hex.decode(name))).replace('<', ' ');
- return name;
- } catch (IndexOutOfBoundsException e) {
- // try-catch for https://github.com/FluffyKaon/OpenPGP-Card
- // Note: This should not happen, but happens with
- // https://github.com/FluffyKaon/OpenPGP-Card, thus return an empty string for now!
-
- Log.e(Constants.TAG, "Couldn't get holder name, returning empty string!", e);
- return "";
- }
- }
-
- public static String getHex(byte[] raw) {
- return new String(Hex.encode(raw));
- }
-
public class IsoDepNotSupportedException extends IOException {
public IsoDepNotSupportedException(String detailMessage) {
@@ -575,4 +536,8 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
super.onStart();
mUsbDispatcher.onStart();
}
+
+ public SmartcardDevice getSmartcardDevice() {
+ return mSmartcardDevice;
+ }
}