OTG: rename Smartcard -> SecurityToken

This commit is contained in:
Nikita Mikhailov
2016-04-12 00:02:59 +06:00
parent 4e543e5368
commit df57ecde47
13 changed files with 127 additions and 129 deletions

View File

@@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.sufficientlysecure.keychain.smartcard; package org.sufficientlysecure.keychain.securitytoken;
import java.io.IOException; import java.io.IOException;

View File

@@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.sufficientlysecure.keychain.smartcard; package org.sufficientlysecure.keychain.securitytoken;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;

View File

@@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.sufficientlysecure.keychain.smartcard; package org.sufficientlysecure.keychain.securitytoken;
import android.nfc.Tag; import android.nfc.Tag;

View File

@@ -20,7 +20,7 @@
*/ */
package org.sufficientlysecure.keychain.smartcard; package org.sufficientlysecure.keychain.securitytoken;
import org.bouncycastle.bcpg.HashAlgorithmTags; import org.bouncycastle.bcpg.HashAlgorithmTags;
import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Arrays;
@@ -41,10 +41,10 @@ import nordpol.Apdu;
/** /**
* This class provides a communication interface to OpenPGP applications on ISO SmartCard compliant * This class provides a communication interface to OpenPGP applications on ISO SmartCard compliant
* NFC devices. * devices.
* For the full specs, see http://g10code.com/docs/openpgp-card-2.0.pdf * For the full specs, see http://g10code.com/docs/openpgp-card-2.0.pdf
*/ */
public class SmartcardDevice { public class SecurityTokenHelper {
// Fidesmo constants // Fidesmo constants
private static final String FIDESMO_APPS_AID_PREFIX = "A000000617"; private static final String FIDESMO_APPS_AID_PREFIX = "A000000617";
@@ -58,11 +58,11 @@ public class SmartcardDevice {
private boolean mPw1ValidatedForDecrypt; // Mode 82 does other things; consider renaming? private boolean mPw1ValidatedForDecrypt; // Mode 82 does other things; consider renaming?
private boolean mPw3Validated; private boolean mPw3Validated;
protected SmartcardDevice() { protected SecurityTokenHelper() {
} }
public static SmartcardDevice getInstance() { public static SecurityTokenHelper getInstance() {
return LazyHolder.mSmartcardDevice; return LazyHolder.SECURITY_TOKEN_HELPER;
} }
private static String getHex(byte[] raw) { private static String getHex(byte[] raw) {
@@ -750,6 +750,6 @@ public class SmartcardDevice {
} }
private static class LazyHolder { private static class LazyHolder {
private static final SmartcardDevice mSmartcardDevice = new SmartcardDevice(); private static final SecurityTokenHelper SECURITY_TOKEN_HELPER = new SecurityTokenHelper();
} }
} }

View File

@@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.sufficientlysecure.keychain.smartcard; package org.sufficientlysecure.keychain.securitytoken;
import java.io.IOException; import java.io.IOException;

View File

@@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.sufficientlysecure.keychain.smartcard; package org.sufficientlysecure.keychain.securitytoken;
import android.hardware.usb.UsbConstants; import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbDevice;

View File

@@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.sufficientlysecure.keychain.smartcard; package org.sufficientlysecure.keychain.securitytoken;
import java.io.IOException; import java.io.IOException;

View File

@@ -47,9 +47,9 @@ public class CreateKeyActivity extends BaseSecurityTokenNfcActivity {
public static final String EXTRA_SECURITY_TOKEN_PIN = "yubi_key_pin"; public static final String EXTRA_SECURITY_TOKEN_PIN = "yubi_key_pin";
public static final String EXTRA_SECURITY_TOKEN_ADMIN_PIN = "yubi_key_admin_pin"; public static final String EXTRA_SECURITY_TOKEN_ADMIN_PIN = "yubi_key_admin_pin";
public static final String EXTRA_NFC_USER_ID = "nfc_user_id"; public static final String EXTRA_SECURITY_TOKEN_USER_ID = "nfc_user_id";
public static final String EXTRA_NFC_AID = "nfc_aid"; public static final String EXTRA_SECURITY_TOKEN_AID = "nfc_aid";
public static final String EXTRA_NFC_FINGERPRINTS = "nfc_fingerprints"; public static final String EXTRA_SECURITY_FINGERPRINTS = "nfc_fingerprints";
public static final String FRAGMENT_TAG = "currentFragment"; public static final String FRAGMENT_TAG = "currentFragment";
@@ -66,8 +66,8 @@ public class CreateKeyActivity extends BaseSecurityTokenNfcActivity {
byte[] mScannedFingerprints; byte[] mScannedFingerprints;
byte[] mNfcAid; byte[] mSecurityTokenAid;
String mNfcUserId; String mSecurityTokenUserId;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@@ -107,10 +107,10 @@ public class CreateKeyActivity extends BaseSecurityTokenNfcActivity {
mFirstTime = intent.getBooleanExtra(EXTRA_FIRST_TIME, false); mFirstTime = intent.getBooleanExtra(EXTRA_FIRST_TIME, false);
mCreateSecurityToken = intent.getBooleanExtra(EXTRA_CREATE_SECURITY_TOKEN, false); mCreateSecurityToken = intent.getBooleanExtra(EXTRA_CREATE_SECURITY_TOKEN, false);
if (intent.hasExtra(EXTRA_NFC_FINGERPRINTS)) { if (intent.hasExtra(EXTRA_SECURITY_FINGERPRINTS)) {
byte[] nfcFingerprints = intent.getByteArrayExtra(EXTRA_NFC_FINGERPRINTS); byte[] nfcFingerprints = intent.getByteArrayExtra(EXTRA_SECURITY_FINGERPRINTS);
String nfcUserId = intent.getStringExtra(EXTRA_NFC_USER_ID); String nfcUserId = intent.getStringExtra(EXTRA_SECURITY_TOKEN_USER_ID);
byte[] nfcAid = intent.getByteArrayExtra(EXTRA_NFC_AID); byte[] nfcAid = intent.getByteArrayExtra(EXTRA_SECURITY_TOKEN_AID);
if (containsKeys(nfcFingerprints)) { if (containsKeys(nfcFingerprints)) {
Fragment frag = CreateSecurityTokenImportResetFragment.newInstance( Fragment frag = CreateSecurityTokenImportResetFragment.newInstance(
@@ -143,19 +143,19 @@ public class CreateKeyActivity extends BaseSecurityTokenNfcActivity {
} }
@Override @Override
protected void doSmartcardInBackground() throws IOException { protected void doSecurityTokenInBackground() throws IOException {
if (mCurrentFragment instanceof NfcListenerFragment) { if (mCurrentFragment instanceof NfcListenerFragment) {
((NfcListenerFragment) mCurrentFragment).doNfcInBackground(); ((NfcListenerFragment) mCurrentFragment).doNfcInBackground();
return; return;
} }
mScannedFingerprints = mSmartcardDevice.getFingerprints(); mScannedFingerprints = mSecurityTokenHelper.getFingerprints();
mNfcAid = mSmartcardDevice.getAid(); mSecurityTokenAid = mSecurityTokenHelper.getAid();
mNfcUserId = mSmartcardDevice.getUserId(); mSecurityTokenUserId = mSecurityTokenHelper.getUserId();
} }
@Override @Override
protected void onSmartcardPostExecute() { protected void onSecurityTokenPostExecute() {
if (mCurrentFragment instanceof NfcListenerFragment) { if (mCurrentFragment instanceof NfcListenerFragment) {
((NfcListenerFragment) mCurrentFragment).onNfcPostExecute(); ((NfcListenerFragment) mCurrentFragment).onNfcPostExecute();
return; return;
@@ -169,15 +169,15 @@ public class CreateKeyActivity extends BaseSecurityTokenNfcActivity {
Intent intent = new Intent(this, ViewKeyActivity.class); Intent intent = new Intent(this, ViewKeyActivity.class);
intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId)); intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId));
intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_AID, mNfcAid); intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_AID, mSecurityTokenAid);
intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_USER_ID, mNfcUserId); intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_USER_ID, mSecurityTokenUserId);
intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_FINGERPRINTS, mScannedFingerprints); intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_FINGERPRINTS, mScannedFingerprints);
startActivity(intent); startActivity(intent);
finish(); finish();
} catch (PgpKeyNotFoundException e) { } catch (PgpKeyNotFoundException e) {
Fragment frag = CreateSecurityTokenImportResetFragment.newInstance( Fragment frag = CreateSecurityTokenImportResetFragment.newInstance(
mScannedFingerprints, mNfcAid, mNfcUserId); mScannedFingerprints, mSecurityTokenAid, mSecurityTokenUserId);
loadFragment(frag, FragAction.TO_RIGHT); loadFragment(frag, FragAction.TO_RIGHT);
} }
} else { } else {

View File

@@ -249,9 +249,9 @@ public class CreateSecurityTokenImportResetFragment
@Override @Override
public void doNfcInBackground() throws IOException { public void doNfcInBackground() throws IOException {
mTokenFingerprints = mCreateKeyActivity.getSmartcardDevice().getFingerprints(); mTokenFingerprints = mCreateKeyActivity.getSecurityTokenHelper().getFingerprints();
mTokenAid = mCreateKeyActivity.getSmartcardDevice().getAid(); mTokenAid = mCreateKeyActivity.getSecurityTokenHelper().getAid();
mTokenUserId = mCreateKeyActivity.getSmartcardDevice().getUserId(); mTokenUserId = mCreateKeyActivity.getSecurityTokenHelper().getUserId();
byte[] fp = new byte[20]; byte[] fp = new byte[20];
ByteBuffer.wrap(fp).put(mTokenFingerprints, 0, 20); ByteBuffer.wrap(fp).put(mTokenFingerprints, 0, 20);

View File

@@ -172,20 +172,20 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenNfcActivity
} }
@Override @Override
public void onSmartcardPreExecute() { public void onSecurityTokenPreExecute() {
// start with indeterminate progress // start with indeterminate progress
vAnimator.setDisplayedChild(1); vAnimator.setDisplayedChild(1);
nfcGuideView.setCurrentStatus(NfcGuideView.NfcGuideViewStatus.TRANSFERRING); nfcGuideView.setCurrentStatus(NfcGuideView.NfcGuideViewStatus.TRANSFERRING);
} }
@Override @Override
protected void doSmartcardInBackground() throws IOException { protected void doSecurityTokenInBackground() throws IOException {
switch (mRequiredInput.mType) { switch (mRequiredInput.mType) {
case SMARTCARD_DECRYPT: { case SMARTCARD_DECRYPT: {
for (int i = 0; i < mRequiredInput.mInputData.length; i++) { for (int i = 0; i < mRequiredInput.mInputData.length; i++) {
byte[] encryptedSessionKey = mRequiredInput.mInputData[i]; byte[] encryptedSessionKey = mRequiredInput.mInputData[i];
byte[] decryptedSessionKey = mSmartcardDevice.decryptSessionKey(encryptedSessionKey); byte[] decryptedSessionKey = mSecurityTokenHelper.decryptSessionKey(encryptedSessionKey);
mInputParcel.addCryptoData(encryptedSessionKey, decryptedSessionKey); mInputParcel.addCryptoData(encryptedSessionKey, decryptedSessionKey);
} }
break; break;
@@ -196,15 +196,15 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenNfcActivity
for (int i = 0; i < mRequiredInput.mInputData.length; i++) { for (int i = 0; i < mRequiredInput.mInputData.length; i++) {
byte[] hash = mRequiredInput.mInputData[i]; byte[] hash = mRequiredInput.mInputData[i];
int algo = mRequiredInput.mSignAlgos[i]; int algo = mRequiredInput.mSignAlgos[i];
byte[] signedHash = mSmartcardDevice.calculateSignature(hash, algo); byte[] signedHash = mSecurityTokenHelper.calculateSignature(hash, algo);
mInputParcel.addCryptoData(hash, signedHash); mInputParcel.addCryptoData(hash, signedHash);
} }
break; break;
} }
case SMARTCARD_MOVE_KEY_TO_CARD: { case SMARTCARD_MOVE_KEY_TO_CARD: {
// TODO: assume PIN and Admin PIN to be default for this operation // TODO: assume PIN and Admin PIN to be default for this operation
mSmartcardDevice.setPin(new Passphrase("123456")); mSecurityTokenHelper.setPin(new Passphrase("123456"));
mSmartcardDevice.setAdminPin(new Passphrase("12345678")); mSecurityTokenHelper.setAdminPin(new Passphrase("12345678"));
ProviderHelper providerHelper = new ProviderHelper(this); ProviderHelper providerHelper = new ProviderHelper(this);
CanonicalizedSecretKeyRing secretKeyRing; CanonicalizedSecretKeyRing secretKeyRing;
@@ -225,7 +225,7 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenNfcActivity
long subkeyId = buf.getLong(); long subkeyId = buf.getLong();
CanonicalizedSecretKey key = secretKeyRing.getSecretKey(subkeyId); CanonicalizedSecretKey key = secretKeyRing.getSecretKey(subkeyId);
byte[] tokenSerialNumber = Arrays.copyOf(mSmartcardDevice.getAid(), 16); byte[] tokenSerialNumber = Arrays.copyOf(mSecurityTokenHelper.getAid(), 16);
Passphrase passphrase; Passphrase passphrase;
try { try {
@@ -235,20 +235,20 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenNfcActivity
throw new IOException("Unable to get cached passphrase!"); throw new IOException("Unable to get cached passphrase!");
} }
mSmartcardDevice.changeKey(key, passphrase); mSecurityTokenHelper.changeKey(key, passphrase);
// TODO: Is this really used anywhere? // TODO: Is this really used anywhere?
mInputParcel.addCryptoData(subkeyBytes, tokenSerialNumber); mInputParcel.addCryptoData(subkeyBytes, tokenSerialNumber);
} }
// change PINs afterwards // change PINs afterwards
mSmartcardDevice.modifyPin(0x81, newPin); mSecurityTokenHelper.modifyPin(0x81, newPin);
mSmartcardDevice.modifyPin(0x83, newAdminPin); mSecurityTokenHelper.modifyPin(0x83, newAdminPin);
break; break;
} }
case SMARTCARD_RESET_CARD: { case SMARTCARD_RESET_CARD: {
mSmartcardDevice.resetAndWipeToken(); mSecurityTokenHelper.resetAndWipeToken();
break; break;
} }
@@ -260,7 +260,7 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenNfcActivity
} }
@Override @Override
protected final void onSmartcardPostExecute() { protected final void onSecurityTokenPostExecute() {
handleResult(mInputParcel); handleResult(mInputParcel);
// show finish // show finish
@@ -268,7 +268,7 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenNfcActivity
nfcGuideView.setCurrentStatus(NfcGuideView.NfcGuideViewStatus.DONE); nfcGuideView.setCurrentStatus(NfcGuideView.NfcGuideViewStatus.DONE);
if (mSmartcardDevice.isPersistentConnectionAllowed()) { if (mSecurityTokenHelper.isPersistentConnectionAllowed()) {
// Just close // Just close
finish(); finish();
} else { } else {
@@ -309,7 +309,7 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenNfcActivity
} }
@Override @Override
protected void onSmartcardError(String error) { protected void onSecurityTokenError(String error) {
pauseTagHandling(); pauseTagHandling();
vErrorText.setText(error + "\n\n" + getString(R.string.security_token_nfc_try_again_text)); vErrorText.setText(error + "\n\n" + getString(R.string.security_token_nfc_try_again_text));
@@ -319,8 +319,8 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenNfcActivity
} }
@Override @Override
public void onSmartcardPinError(String error) { public void onSecurityTokenPinError(String error) {
onSmartcardError(error); onSecurityTokenError(error);
// clear (invalid) passphrase // clear (invalid) passphrase
PassphraseCacheService.clearCachedPassphrase( PassphraseCacheService.clearCachedPassphrase(

View File

@@ -32,7 +32,6 @@ import android.app.ActivityOptions;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.net.Uri; import android.net.Uri;
import android.nfc.NfcAdapter; import android.nfc.NfcAdapter;
@@ -172,9 +171,9 @@ public class ViewKeyActivity extends BaseSecurityTokenNfcActivity implements
private byte[] mFingerprint; private byte[] mFingerprint;
private String mFingerprintString; private String mFingerprintString;
private byte[] mNfcFingerprints; private byte[] mSecurityTokenFingerprints;
private String mNfcUserId; private String mSecurityTokenUserId;
private byte[] mNfcAid; private byte[] mSecurityTokenAid;
@SuppressLint("InflateParams") @SuppressLint("InflateParams")
@Override @Override
@@ -647,17 +646,17 @@ public class ViewKeyActivity extends BaseSecurityTokenNfcActivity implements
} }
@Override @Override
protected void doSmartcardInBackground() throws IOException { protected void doSecurityTokenInBackground() throws IOException {
mNfcFingerprints = mSmartcardDevice.getFingerprints(); mSecurityTokenFingerprints = mSecurityTokenHelper.getFingerprints();
mNfcUserId = mSmartcardDevice.getUserId(); mSecurityTokenUserId = mSecurityTokenHelper.getUserId();
mNfcAid = mSmartcardDevice.getAid(); mSecurityTokenAid = mSecurityTokenHelper.getAid();
} }
@Override @Override
protected void onSmartcardPostExecute() { protected void onSecurityTokenPostExecute() {
long tokenId = KeyFormattingUtils.getKeyIdFromFingerprint(mNfcFingerprints); long tokenId = KeyFormattingUtils.getKeyIdFromFingerprint(mSecurityTokenFingerprints);
try { try {
@@ -668,7 +667,7 @@ public class ViewKeyActivity extends BaseSecurityTokenNfcActivity implements
// if the master key of that key matches this one, just show the token dialog // if the master key of that key matches this one, just show the token dialog
if (KeyFormattingUtils.convertFingerprintToHex(candidateFp).equals(mFingerprintString)) { if (KeyFormattingUtils.convertFingerprintToHex(candidateFp).equals(mFingerprintString)) {
showSecurityTokenFragment(mNfcFingerprints, mNfcUserId, mNfcAid); showSecurityTokenFragment(mSecurityTokenFingerprints, mSecurityTokenUserId, mSecurityTokenAid);
return; return;
} }
@@ -681,9 +680,9 @@ public class ViewKeyActivity extends BaseSecurityTokenNfcActivity implements
Intent intent = new Intent( Intent intent = new Intent(
ViewKeyActivity.this, ViewKeyActivity.class); ViewKeyActivity.this, ViewKeyActivity.class);
intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId)); intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId));
intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_AID, mNfcAid); intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_AID, mSecurityTokenAid);
intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_USER_ID, mNfcUserId); intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_USER_ID, mSecurityTokenUserId);
intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_FINGERPRINTS, mNfcFingerprints); intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_FINGERPRINTS, mSecurityTokenFingerprints);
startActivity(intent); startActivity(intent);
finish(); finish();
} }
@@ -696,9 +695,9 @@ public class ViewKeyActivity extends BaseSecurityTokenNfcActivity implements
public void onAction() { public void onAction() {
Intent intent = new Intent( Intent intent = new Intent(
ViewKeyActivity.this, CreateKeyActivity.class); ViewKeyActivity.this, CreateKeyActivity.class);
intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_AID, mNfcAid); intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_AID, mSecurityTokenAid);
intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_USER_ID, mNfcUserId); intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_USER_ID, mSecurityTokenUserId);
intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_FINGERPRINTS, mNfcFingerprints); intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_FINGERPRINTS, mSecurityTokenFingerprints);
startActivity(intent); startActivity(intent);
finish(); finish();
} }

View File

@@ -24,7 +24,6 @@ package org.sufficientlysecure.keychain.ui.base;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.hardware.usb.UsbManager;
import android.nfc.NfcAdapter; import android.nfc.NfcAdapter;
import android.nfc.Tag; import android.nfc.Tag;
import android.nfc.TagLostException; import android.nfc.TagLostException;
@@ -40,12 +39,12 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.smartcard.CardException; import org.sufficientlysecure.keychain.securitytoken.CardException;
import org.sufficientlysecure.keychain.smartcard.NfcTransport; import org.sufficientlysecure.keychain.securitytoken.NfcTransport;
import org.sufficientlysecure.keychain.smartcard.SmartcardDevice; import org.sufficientlysecure.keychain.securitytoken.SecurityTokenHelper;
import org.sufficientlysecure.keychain.smartcard.Transport; import org.sufficientlysecure.keychain.securitytoken.Transport;
import org.sufficientlysecure.keychain.util.UsbConnectionDispatcher; import org.sufficientlysecure.keychain.util.UsbConnectionDispatcher;
import org.sufficientlysecure.keychain.smartcard.UsbTransport; import org.sufficientlysecure.keychain.securitytoken.UsbTransport;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity; import org.sufficientlysecure.keychain.ui.CreateKeyActivity;
import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity; import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
import org.sufficientlysecure.keychain.ui.ViewKeyActivity; import org.sufficientlysecure.keychain.ui.ViewKeyActivity;
@@ -70,36 +69,36 @@ 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";
protected SmartcardDevice mSmartcardDevice = SmartcardDevice.getInstance(); protected SecurityTokenHelper mSecurityTokenHelper = SecurityTokenHelper.getInstance();
protected TagDispatcher mTagDispatcher; protected TagDispatcher mTagDispatcher;
protected UsbConnectionDispatcher mUsbDispatcher; protected UsbConnectionDispatcher mUsbDispatcher;
private boolean mTagHandlingEnabled; private boolean mTagHandlingEnabled;
private byte[] mSmartcardFingerprints; private byte[] mSecurityTokenFingerprints;
private String mSmartcardUserId; private String mSecurityTokenUserId;
private byte[] mSmartcardAid; private byte[] mSecurityTokenAid;
/** /**
* Override to change UI before NFC handling (UI thread) * Override to change UI before SecurityToken handling (UI thread)
*/ */
protected void onSmartcardPreExecute() { protected void onSecurityTokenPreExecute() {
} }
/** /**
* Override to implement NFC operations (background thread) * Override to implement SecurityToken operations (background thread)
*/ */
protected void doSmartcardInBackground() throws IOException { protected void doSecurityTokenInBackground() throws IOException {
mSmartcardFingerprints = mSmartcardDevice.getFingerprints(); mSecurityTokenFingerprints = mSecurityTokenHelper.getFingerprints();
mSmartcardUserId = mSmartcardDevice.getUserId(); mSecurityTokenUserId = mSecurityTokenHelper.getUserId();
mSmartcardAid = mSmartcardDevice.getAid(); mSecurityTokenAid = mSecurityTokenHelper.getAid();
} }
/** /**
* Override to handle result of NFC operations (UI thread) * Override to handle result of SecurityToken operations (UI thread)
*/ */
protected void onSmartcardPostExecute() { protected void onSecurityTokenPostExecute() {
final long subKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mSmartcardFingerprints); final long subKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mSecurityTokenFingerprints);
try { try {
CachedPublicKeyRing ring = new ProviderHelper(this).getCachedPublicKeyRing( CachedPublicKeyRing ring = new ProviderHelper(this).getCachedPublicKeyRing(
@@ -108,15 +107,15 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
Intent intent = new Intent(this, ViewKeyActivity.class); Intent intent = new Intent(this, ViewKeyActivity.class);
intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId)); intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId));
intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_AID, mSmartcardAid); intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_AID, mSecurityTokenAid);
intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_USER_ID, mSmartcardUserId); intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_USER_ID, mSecurityTokenUserId);
intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_FINGERPRINTS, mSmartcardFingerprints); intent.putExtra(ViewKeyActivity.EXTRA_SECURITY_TOKEN_FINGERPRINTS, mSecurityTokenFingerprints);
startActivity(intent); startActivity(intent);
} catch (PgpKeyNotFoundException e) { } catch (PgpKeyNotFoundException e) {
Intent intent = new Intent(this, CreateKeyActivity.class); Intent intent = new Intent(this, CreateKeyActivity.class);
intent.putExtra(CreateKeyActivity.EXTRA_NFC_AID, mSmartcardAid); intent.putExtra(CreateKeyActivity.EXTRA_SECURITY_TOKEN_AID, mSecurityTokenAid);
intent.putExtra(CreateKeyActivity.EXTRA_NFC_USER_ID, mSmartcardUserId); intent.putExtra(CreateKeyActivity.EXTRA_SECURITY_TOKEN_USER_ID, mSecurityTokenUserId);
intent.putExtra(CreateKeyActivity.EXTRA_NFC_FINGERPRINTS, mSmartcardFingerprints); intent.putExtra(CreateKeyActivity.EXTRA_SECURITY_FINGERPRINTS, mSecurityTokenFingerprints);
startActivity(intent); startActivity(intent);
} }
} }
@@ -124,15 +123,15 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
/** /**
* Override to use something different than Notify (UI thread) * Override to use something different than Notify (UI thread)
*/ */
protected void onSmartcardError(String error) { protected void onSecurityTokenError(String error) {
Notify.create(this, error, Style.WARN).show(); Notify.create(this, error, Style.WARN).show();
} }
/** /**
* Override to do something when PIN is wrong, e.g., clear passphrases (UI thread) * Override to do something when PIN is wrong, e.g., clear passphrases (UI thread)
*/ */
protected void onSmartcardPinError(String error) { protected void onSecurityTokenPinError(String error) {
onSmartcardError(error); onSecurityTokenError(error);
} }
public void tagDiscovered(final Tag tag) { public void tagDiscovered(final Tag tag) {
@@ -140,7 +139,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
if (!mTagHandlingEnabled) if (!mTagHandlingEnabled)
return; return;
smartcardDiscovered(new NfcTransport(tag)); securityTokenDiscovered(new NfcTransport(tag));
} }
public void usbDeviceDiscovered(final UsbTransport transport) { public void usbDeviceDiscovered(final UsbTransport transport) {
@@ -148,10 +147,10 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
if (!mTagHandlingEnabled) if (!mTagHandlingEnabled)
return; return;
smartcardDiscovered(transport); securityTokenDiscovered(transport);
} }
public void smartcardDiscovered(final Transport transport) { public void securityTokenDiscovered(final Transport transport) {
// Actual Smartcard operations are executed in doInBackground to not block the UI thread // Actual Smartcard operations are executed in doInBackground to not block the UI thread
if (!mTagHandlingEnabled) if (!mTagHandlingEnabled)
return; return;
@@ -159,7 +158,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
@Override @Override
protected void onPreExecute() { protected void onPreExecute() {
super.onPreExecute(); super.onPreExecute();
onSmartcardPreExecute(); onSecurityTokenPreExecute();
} }
@Override @Override
@@ -182,7 +181,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
return; return;
} }
onSmartcardPostExecute(); onSecurityTokenPostExecute();
} }
}.execute(); }.execute();
} }
@@ -237,12 +236,12 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
private void handleSmartcardError(IOException e) { private void handleSmartcardError(IOException e) {
if (e instanceof TagLostException) { if (e instanceof TagLostException) {
onSmartcardError(getString(R.string.security_token_error_tag_lost)); onSecurityTokenError(getString(R.string.security_token_error_tag_lost));
return; return;
} }
if (e instanceof IsoDepNotSupportedException) { if (e instanceof IsoDepNotSupportedException) {
onSmartcardError(getString(R.string.security_token_error_iso_dep_not_supported)); onSecurityTokenError(getString(R.string.security_token_error_iso_dep_not_supported));
return; return;
} }
@@ -257,7 +256,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
if ((status & (short) 0xFFF0) == 0x63C0) { if ((status & (short) 0xFFF0) == 0x63C0) {
int tries = status & 0x000F; int tries = status & 0x000F;
// hook to do something different when PIN is wrong // hook to do something different when PIN is wrong
onSmartcardPinError(getResources().getQuantityString(R.plurals.security_token_error_pin, tries, tries)); onSecurityTokenPinError(getResources().getQuantityString(R.plurals.security_token_error_pin, tries, tries));
return; return;
} }
@@ -266,61 +265,61 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
// These errors should not occur in everyday use; if they are returned, it means we // These errors should not occur in everyday use; if they are returned, it means we
// made a mistake sending data to the token, or the token is misbehaving. // made a mistake sending data to the token, or the token is misbehaving.
case 0x6A80: { case 0x6A80: {
onSmartcardError(getString(R.string.security_token_error_bad_data)); onSecurityTokenError(getString(R.string.security_token_error_bad_data));
break; break;
} }
case 0x6883: { case 0x6883: {
onSmartcardError(getString(R.string.security_token_error_chaining_error)); onSecurityTokenError(getString(R.string.security_token_error_chaining_error));
break; break;
} }
case 0x6B00: { case 0x6B00: {
onSmartcardError(getString(R.string.security_token_error_header, "P1/P2")); onSecurityTokenError(getString(R.string.security_token_error_header, "P1/P2"));
break; break;
} }
case 0x6D00: { case 0x6D00: {
onSmartcardError(getString(R.string.security_token_error_header, "INS")); onSecurityTokenError(getString(R.string.security_token_error_header, "INS"));
break; break;
} }
case 0x6E00: { case 0x6E00: {
onSmartcardError(getString(R.string.security_token_error_header, "CLA")); onSecurityTokenError(getString(R.string.security_token_error_header, "CLA"));
break; break;
} }
// These error conditions are more likely to be experienced by an end user. // These error conditions are more likely to be experienced by an end user.
case 0x6285: { case 0x6285: {
onSmartcardError(getString(R.string.security_token_error_terminated)); onSecurityTokenError(getString(R.string.security_token_error_terminated));
break; break;
} }
case 0x6700: { case 0x6700: {
onSmartcardPinError(getString(R.string.security_token_error_wrong_length)); onSecurityTokenPinError(getString(R.string.security_token_error_wrong_length));
break; break;
} }
case 0x6982: { case 0x6982: {
onSmartcardError(getString(R.string.security_token_error_security_not_satisfied)); onSecurityTokenError(getString(R.string.security_token_error_security_not_satisfied));
break; break;
} }
case 0x6983: { case 0x6983: {
onSmartcardError(getString(R.string.security_token_error_authentication_blocked)); onSecurityTokenError(getString(R.string.security_token_error_authentication_blocked));
break; break;
} }
case 0x6985: { case 0x6985: {
onSmartcardError(getString(R.string.security_token_error_conditions_not_satisfied)); onSecurityTokenError(getString(R.string.security_token_error_conditions_not_satisfied));
break; break;
} }
// 6A88 is "Not Found" in the spec, but Yubikey also returns 6A83 for this in some cases. // 6A88 is "Not Found" in the spec, but Yubikey also returns 6A83 for this in some cases.
case 0x6A88: case 0x6A88:
case 0x6A83: { case 0x6A83: {
onSmartcardError(getString(R.string.security_token_error_data_not_found)); onSecurityTokenError(getString(R.string.security_token_error_data_not_found));
break; break;
} }
// 6F00 is a JavaCard proprietary status code, SW_UNKNOWN, and usually represents an // 6F00 is a JavaCard proprietary status code, SW_UNKNOWN, and usually represents an
// unhandled exception on the security token. // unhandled exception on the security token.
case 0x6F00: { case 0x6F00: {
onSmartcardError(getString(R.string.security_token_error_unknown)); onSecurityTokenError(getString(R.string.security_token_error_unknown));
break; break;
} }
// 6A82 app not installed on security token! // 6A82 app not installed on security token!
case 0x6A82: { case 0x6A82: {
if (mSmartcardDevice.isFidesmoToken()) { if (mSecurityTokenHelper.isFidesmoToken()) {
// Check if the Fidesmo app is installed // Check if the Fidesmo app is installed
if (isAndroidAppInstalled(FIDESMO_APP_PACKAGE)) { if (isAndroidAppInstalled(FIDESMO_APP_PACKAGE)) {
promptFidesmoPgpInstall(); promptFidesmoPgpInstall();
@@ -328,12 +327,12 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
promptFidesmoAppInstall(); promptFidesmoAppInstall();
} }
} else { // Other (possibly) compatible hardware } else { // Other (possibly) compatible hardware
onSmartcardError(getString(R.string.security_token_error_pgp_app_not_installed)); onSecurityTokenError(getString(R.string.security_token_error_pgp_app_not_installed));
} }
break; break;
} }
default: { default: {
onSmartcardError(getString(R.string.security_token_error, e.getMessage())); onSecurityTokenError(getString(R.string.security_token_error, e.getMessage()));
break; break;
} }
} }
@@ -367,7 +366,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
Passphrase passphrase = PassphraseCacheService.getCachedPassphrase(this, Passphrase passphrase = PassphraseCacheService.getCachedPassphrase(this,
requiredInput.getMasterKeyId(), requiredInput.getSubKeyId()); requiredInput.getMasterKeyId(), requiredInput.getSubKeyId());
if (passphrase != null) { if (passphrase != null) {
mSmartcardDevice.setPin(passphrase); mSecurityTokenHelper.setPin(passphrase);
return; return;
} }
@@ -392,7 +391,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
return; return;
} }
CryptoInputParcel input = data.getParcelableExtra(PassphraseDialogActivity.RESULT_CRYPTO_INPUT); CryptoInputParcel input = data.getParcelableExtra(PassphraseDialogActivity.RESULT_CRYPTO_INPUT);
mSmartcardDevice.setPin(input.getPassphrase()); mSecurityTokenHelper.setPin(input.getPassphrase());
break; break;
} }
default: default:
@@ -402,16 +401,16 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
protected void handleSmartcard(Transport transport) throws IOException { protected void handleSmartcard(Transport transport) throws IOException {
// Don't reconnect if device was already connected // Don't reconnect if device was already connected
if (!(mSmartcardDevice.isConnected() if (!(mSecurityTokenHelper.isConnected()
&& mSmartcardDevice.getTransport().equals(transport))) { && mSecurityTokenHelper.getTransport().equals(transport))) {
mSmartcardDevice.setTransport(transport); mSecurityTokenHelper.setTransport(transport);
mSmartcardDevice.connectToDevice(); mSecurityTokenHelper.connectToDevice();
} }
doSmartcardInBackground(); doSecurityTokenInBackground();
} }
public boolean isSmartcardConnected() { public boolean isSmartcardConnected() {
return mSmartcardDevice.isConnected(); return mSecurityTokenHelper.isConnected();
} }
public static class IsoDepNotSupportedException extends IOException { public static class IsoDepNotSupportedException extends IOException {
@@ -470,8 +469,8 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity
mUsbDispatcher.onStart(); mUsbDispatcher.onStart();
} }
public SmartcardDevice getSmartcardDevice() { public SecurityTokenHelper getSecurityTokenHelper() {
return mSmartcardDevice; return mSecurityTokenHelper;
} }
/** /**

View File

@@ -26,7 +26,7 @@ import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager; import android.hardware.usb.UsbManager;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.smartcard.UsbTransport; import org.sufficientlysecure.keychain.securitytoken.UsbTransport;
import org.sufficientlysecure.keychain.ui.UsbEventReceiverActivity; import org.sufficientlysecure.keychain.ui.UsbEventReceiverActivity;
public class UsbConnectionDispatcher { public class UsbConnectionDispatcher {