explicitly pass around instance of SecurityTokenConnection
This commit is contained in:
@@ -87,30 +87,34 @@ public class SecurityTokenConnection {
|
|||||||
|
|
||||||
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 static SecurityTokenConnection sCachedInstance;
|
||||||
|
|
||||||
private final JcaKeyFingerprintCalculator fingerprintCalculator = new JcaKeyFingerprintCalculator();
|
private final JcaKeyFingerprintCalculator fingerprintCalculator = new JcaKeyFingerprintCalculator();
|
||||||
|
|
||||||
private Transport mTransport;
|
@NonNull
|
||||||
|
private final Transport mTransport;
|
||||||
|
@NonNull
|
||||||
|
private final Passphrase mPin;
|
||||||
|
|
||||||
private CardCapabilities mCardCapabilities;
|
private CardCapabilities mCardCapabilities;
|
||||||
private OpenPgpCapabilities mOpenPgpCapabilities;
|
private OpenPgpCapabilities mOpenPgpCapabilities;
|
||||||
private SecureMessaging mSecureMessaging;
|
private SecureMessaging mSecureMessaging;
|
||||||
|
|
||||||
private Passphrase mPin;
|
|
||||||
private Passphrase mAdminPin;
|
|
||||||
private boolean mPw1ValidatedForSignature;
|
private boolean mPw1ValidatedForSignature;
|
||||||
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;
|
||||||
|
|
||||||
private SecurityTokenConnection() {
|
public static SecurityTokenConnection getInstanceForTransport(Transport transport, Passphrase pin) {
|
||||||
|
if (sCachedInstance == null || !sCachedInstance.isPersistentConnectionAllowed() ||
|
||||||
|
!sCachedInstance.isConnected() || !sCachedInstance.mTransport.equals(transport)) {
|
||||||
|
sCachedInstance = new SecurityTokenConnection(transport, pin);
|
||||||
|
}
|
||||||
|
return sCachedInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double parseOpenPgpVersion(final byte[] aid) {
|
private SecurityTokenConnection(@NonNull Transport transport, @NonNull Passphrase pin) {
|
||||||
float minv = aid[7];
|
this.mTransport = transport;
|
||||||
while (minv > 0) minv /= 10.0;
|
this.mPin = pin;
|
||||||
return aid[6] + minv;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SecurityTokenConnection getInstance() {
|
|
||||||
return LazyHolder.SECURITY_TOKEN_HELPER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getHolderName(byte[] name) {
|
private String getHolderName(byte[] name) {
|
||||||
@@ -126,23 +130,7 @@ public class SecurityTokenConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Passphrase getPin() {
|
public void changeKey(CanonicalizedSecretKey secretKey, Passphrase passphrase, Passphrase adminPin) throws IOException {
|
||||||
return mPin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPin(final Passphrase pin) {
|
|
||||||
this.mPin = pin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Passphrase getAdminPin() {
|
|
||||||
return mAdminPin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAdminPin(final Passphrase adminPin) {
|
|
||||||
this.mAdminPin = adminPin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void changeKey(CanonicalizedSecretKey secretKey, Passphrase passphrase) throws IOException {
|
|
||||||
long keyGenerationTimestamp = secretKey.getCreationTime().getTime() / 1000;
|
long keyGenerationTimestamp = secretKey.getCreationTime().getTime() / 1000;
|
||||||
byte[] timestampBytes = ByteBuffer.allocate(4).putInt((int) keyGenerationTimestamp).array();
|
byte[] timestampBytes = ByteBuffer.allocate(4).putInt((int) keyGenerationTimestamp).array();
|
||||||
KeyType keyType = KeyType.from(secretKey);
|
KeyType keyType = KeyType.from(secretKey);
|
||||||
@@ -160,9 +148,9 @@ public class SecurityTokenConnection {
|
|||||||
keyType.toString()));
|
keyType.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
putKey(keyType, secretKey, passphrase);
|
putKey(keyType, secretKey, passphrase, adminPin);
|
||||||
putData(keyType.getFingerprintObjectId(), secretKey.getFingerprint());
|
putData(adminPin, keyType.getFingerprintObjectId(), secretKey.getFingerprint());
|
||||||
putData(keyType.getTimestampObjectId(), timestampBytes);
|
putData(adminPin, keyType.getTimestampObjectId(), timestampBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSlotEmpty(KeyType keyType) throws IOException {
|
private boolean isSlotEmpty(KeyType keyType) throws IOException {
|
||||||
@@ -179,12 +167,18 @@ public class SecurityTokenConnection {
|
|||||||
return java.util.Arrays.equals(getKeyFingerprint(keyType), fingerprint);
|
return java.util.Arrays.equals(getKeyFingerprint(keyType), fingerprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void connectIfNecessary(Context context) throws IOException {
|
||||||
|
if (isConnected()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connectToDevice(context);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to device and select pgp applet
|
* Connect to device and select pgp applet
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
*/
|
||||||
public void connectToDevice(final Context ctx) throws IOException {
|
private void connectToDevice(Context context) throws IOException {
|
||||||
// Connect on transport layer
|
// Connect on transport layer
|
||||||
mCardCapabilities = new CardCapabilities();
|
mCardCapabilities = new CardCapabilities();
|
||||||
|
|
||||||
@@ -208,7 +202,7 @@ public class SecurityTokenConnection {
|
|||||||
|
|
||||||
if (mOpenPgpCapabilities.isHasSCP11bSM()) {
|
if (mOpenPgpCapabilities.isHasSCP11bSM()) {
|
||||||
try {
|
try {
|
||||||
SCP11bSecureMessaging.establish(this, ctx);
|
SCP11bSecureMessaging.establish(this, context);
|
||||||
} catch (SecureMessagingException e) {
|
} catch (SecureMessagingException e) {
|
||||||
mSecureMessaging = null;
|
mSecureMessaging = null;
|
||||||
Log.e(Constants.TAG, "failed to establish secure messaging", e);
|
Log.e(Constants.TAG, "failed to establish secure messaging", e);
|
||||||
@@ -217,9 +211,9 @@ public class SecurityTokenConnection {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetPin(String newPinStr) throws IOException {
|
public void resetPin(Passphrase adminPin, String newPinStr) throws IOException {
|
||||||
if (!mPw3Validated) {
|
if (!mPw3Validated) {
|
||||||
verifyPin(0x83); // (Verify PW1 with mode 82 for decryption)
|
verifyAdminPin(adminPin);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] newPin = newPinStr.getBytes();
|
byte[] newPin = newPinStr.getBytes();
|
||||||
@@ -246,7 +240,7 @@ public class SecurityTokenConnection {
|
|||||||
* @param pw For PW1, this is 0x81. For PW3 (Admin PIN), mode is 0x83.
|
* @param pw For PW1, this is 0x81. For PW3 (Admin PIN), mode is 0x83.
|
||||||
* @param newPin The new PW1 or PW3.
|
* @param newPin The new PW1 or PW3.
|
||||||
*/
|
*/
|
||||||
public void modifyPin(int pw, byte[] newPin) throws IOException {
|
public void modifyPin(int pw, byte[] newPin, Passphrase adminPin) throws IOException {
|
||||||
final int MAX_PW1_LENGTH_INDEX = 1;
|
final int MAX_PW1_LENGTH_INDEX = 1;
|
||||||
final int MAX_PW3_LENGTH_INDEX = 3;
|
final int MAX_PW3_LENGTH_INDEX = 3;
|
||||||
|
|
||||||
@@ -266,7 +260,10 @@ public class SecurityTokenConnection {
|
|||||||
|
|
||||||
byte[] pin;
|
byte[] pin;
|
||||||
if (pw == 0x83) {
|
if (pw == 0x83) {
|
||||||
pin = mAdminPin.toStringUnsafe().getBytes();
|
if (adminPin == null) {
|
||||||
|
throw new IllegalArgumentException("Changing the admin pin requires admin pin argument!");
|
||||||
|
}
|
||||||
|
pin = adminPin.toStringUnsafe().getBytes();
|
||||||
} else {
|
} else {
|
||||||
pin = mPin.toStringUnsafe().getBytes();
|
pin = mPin.toStringUnsafe().getBytes();
|
||||||
}
|
}
|
||||||
@@ -422,28 +419,30 @@ public class SecurityTokenConnection {
|
|||||||
* For PW3 (Admin PIN), mode is 0x83.
|
* For PW3 (Admin PIN), mode is 0x83.
|
||||||
*/
|
*/
|
||||||
private void verifyPin(int mode) throws IOException {
|
private void verifyPin(int mode) throws IOException {
|
||||||
if (mPin != null || mode == 0x83) {
|
byte[] pin = mPin.toStringUnsafe().getBytes();
|
||||||
|
|
||||||
byte[] pin;
|
ResponseAPDU response = tryPin(mode, pin);// login
|
||||||
if (mode == 0x83) {
|
if (response.getSW() != APDU_SW_SUCCESS) {
|
||||||
pin = mAdminPin.toStringUnsafe().getBytes();
|
throw new CardException("Bad PIN!", response.getSW());
|
||||||
} else {
|
|
||||||
pin = mPin.toStringUnsafe().getBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
ResponseAPDU response = tryPin(mode, pin);// login
|
|
||||||
if (response.getSW() != APDU_SW_SUCCESS) {
|
|
||||||
throw new CardException("Bad PIN!", response.getSW());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == 0x81) {
|
|
||||||
mPw1ValidatedForSignature = true;
|
|
||||||
} else if (mode == 0x82) {
|
|
||||||
mPw1ValidatedForDecrypt = true;
|
|
||||||
} else if (mode == 0x83) {
|
|
||||||
mPw3Validated = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mode == 0x81) {
|
||||||
|
mPw1ValidatedForSignature = true;
|
||||||
|
} else if (mode == 0x82) {
|
||||||
|
mPw1ValidatedForDecrypt = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies the user's PW1 or PW3 with the appropriate mode.
|
||||||
|
*/
|
||||||
|
private void verifyAdminPin(Passphrase adminPin) throws IOException {
|
||||||
|
ResponseAPDU response = tryPin(0x83, adminPin.toStringUnsafe().getBytes());
|
||||||
|
if (response.getSW() != APDU_SW_SUCCESS) {
|
||||||
|
throw new CardException("Bad PIN!", response.getSW());
|
||||||
|
}
|
||||||
|
|
||||||
|
mPw3Validated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -454,16 +453,17 @@ public class SecurityTokenConnection {
|
|||||||
* @param dataObject The data object to be stored.
|
* @param dataObject The data object to be stored.
|
||||||
* @param data The data to store in the object
|
* @param data The data to store in the object
|
||||||
*/
|
*/
|
||||||
private void putData(int dataObject, byte[] data) throws IOException {
|
private void putData(Passphrase adminPin, int dataObject, byte[] data) throws IOException {
|
||||||
if (data.length > 254) {
|
if (data.length > 254) {
|
||||||
throw new IOException("Cannot PUT DATA with length > 254");
|
throw new IOException("Cannot PUT DATA with length > 254");
|
||||||
}
|
}
|
||||||
|
// TODO use admin pin regardless, if we have it?
|
||||||
if (dataObject == 0x0101 || dataObject == 0x0103) {
|
if (dataObject == 0x0101 || dataObject == 0x0103) {
|
||||||
if (!mPw1ValidatedForDecrypt) {
|
if (!mPw1ValidatedForDecrypt) {
|
||||||
verifyPin(0x82); // (Verify PW1 for non-signing operations)
|
verifyPin(0x82); // (Verify PW1 for non-signing operations)
|
||||||
}
|
}
|
||||||
} else if (!mPw3Validated) {
|
} else if (!mPw3Validated) {
|
||||||
verifyPin(0x83); // (Verify PW3)
|
verifyAdminPin(adminPin);
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandAPDU command = new CommandAPDU(0x00, 0xDA, (dataObject & 0xFF00) >> 8, dataObject & 0xFF, data);
|
CommandAPDU command = new CommandAPDU(0x00, 0xDA, (dataObject & 0xFF00) >> 8, dataObject & 0xFF, data);
|
||||||
@@ -475,7 +475,7 @@ public class SecurityTokenConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void setKeyAttributes(final KeyType slot, final CanonicalizedSecretKey secretKey)
|
private void setKeyAttributes(Passphrase adminPin, final KeyType slot, final CanonicalizedSecretKey secretKey)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
if (mOpenPgpCapabilities.isAttributesChangable()) {
|
if (mOpenPgpCapabilities.isAttributesChangable()) {
|
||||||
@@ -493,7 +493,7 @@ public class SecurityTokenConnection {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
putData(tag, SecurityTokenUtils.attributesFromSecretKey(slot, secretKey));
|
putData(adminPin, tag, SecurityTokenUtils.attributesFromSecretKey(slot, secretKey));
|
||||||
|
|
||||||
mOpenPgpCapabilities.updateWithData(getData(0x00, tag));
|
mOpenPgpCapabilities.updateWithData(getData(0x00, tag));
|
||||||
|
|
||||||
@@ -512,14 +512,14 @@ public class SecurityTokenConnection {
|
|||||||
* 0xB8: Decipherment Key
|
* 0xB8: Decipherment Key
|
||||||
* 0xA4: Authentication Key
|
* 0xA4: Authentication Key
|
||||||
*/
|
*/
|
||||||
private void putKey(KeyType slot, CanonicalizedSecretKey secretKey, Passphrase passphrase)
|
private void putKey(KeyType slot, CanonicalizedSecretKey secretKey, Passphrase passphrase, Passphrase adminPin)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
RSAPrivateCrtKey crtSecretKey;
|
RSAPrivateCrtKey crtSecretKey;
|
||||||
ECPrivateKey ecSecretKey;
|
ECPrivateKey ecSecretKey;
|
||||||
ECPublicKey ecPublicKey;
|
ECPublicKey ecPublicKey;
|
||||||
|
|
||||||
if (!mPw3Validated) {
|
if (!mPw3Validated) {
|
||||||
verifyPin(0x83); // (Verify PW3 with mode 83)
|
verifyAdminPin(adminPin);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we're ready to communicate with the token.
|
// Now we're ready to communicate with the token.
|
||||||
@@ -528,7 +528,7 @@ public class SecurityTokenConnection {
|
|||||||
try {
|
try {
|
||||||
secretKey.unlock(passphrase);
|
secretKey.unlock(passphrase);
|
||||||
|
|
||||||
setKeyAttributes(slot, secretKey);
|
setKeyAttributes(adminPin, slot, secretKey);
|
||||||
|
|
||||||
switch (mOpenPgpCapabilities.getFormatForKeyType(slot).keyFormatType()) {
|
switch (mOpenPgpCapabilities.getFormatForKeyType(slot).keyFormatType()) {
|
||||||
case RSAKeyFormatType:
|
case RSAKeyFormatType:
|
||||||
@@ -836,15 +836,6 @@ public class SecurityTokenConnection {
|
|||||||
return lastResponse;
|
return lastResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Transport getTransport() {
|
|
||||||
return mTransport;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTransport(Transport mTransport) {
|
|
||||||
clearSecureMessaging();
|
|
||||||
this.mTransport = mTransport;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isFidesmoToken() {
|
public boolean isFidesmoToken() {
|
||||||
if (isConnected()) { // Check if we can still talk to the card
|
if (isConnected()) { // Check if we can still talk to the card
|
||||||
try {
|
try {
|
||||||
@@ -873,13 +864,13 @@ public class SecurityTokenConnection {
|
|||||||
* @return the public key data objects, in TLV format. For RSA this will be the public modulus
|
* @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.
|
* (0x81) and exponent (0x82). These may come out of order; proper TLV parsing is required.
|
||||||
*/
|
*/
|
||||||
public byte[] generateKey(int slot) throws IOException {
|
public byte[] generateKey(Passphrase adminPin, int slot) throws IOException {
|
||||||
if (slot != 0xB6 && slot != 0xB8 && slot != 0xA4) {
|
if (slot != 0xB6 && slot != 0xB8 && slot != 0xA4) {
|
||||||
throw new IOException("Invalid key slot");
|
throw new IOException("Invalid key slot");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mPw3Validated) {
|
if (!mPw3Validated) {
|
||||||
verifyPin(0x83); // (Verify PW3 with mode 83)
|
verifyAdminPin(adminPin);
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandAPDU apdu = new CommandAPDU(0x00, 0x47, 0x80, 0x00, new byte[]{(byte) slot, 0x00}, MAX_APDU_NE_EXT);
|
CommandAPDU apdu = new CommandAPDU(0x00, 0x47, 0x80, 0x00, new byte[]{(byte) slot, 0x00}, MAX_APDU_NE_EXT);
|
||||||
@@ -962,14 +953,12 @@ public class SecurityTokenConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPersistentConnectionAllowed() {
|
public boolean isPersistentConnectionAllowed() {
|
||||||
return mTransport != null &&
|
return mTransport.isPersistentConnectionAllowed() &&
|
||||||
mTransport.isPersistentConnectionAllowed() &&
|
(mSecureMessaging == null || !mSecureMessaging.isEstablished());
|
||||||
(mSecureMessaging == null ||
|
|
||||||
!mSecureMessaging.isEstablished());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConnected() {
|
public boolean isConnected() {
|
||||||
return mTransport != null && mTransport.isConnected();
|
return mTransport.isConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearSecureMessaging() {
|
public void clearSecureMessaging() {
|
||||||
@@ -1006,7 +995,9 @@ public class SecurityTokenConnection {
|
|||||||
return SecurityTokenInfo.create(fingerprints, aid, userId, url, pwInfo[4], pwInfo[6]);
|
return SecurityTokenInfo.create(fingerprints, aid, userId, url, pwInfo[4], pwInfo[6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LazyHolder {
|
public static double parseOpenPgpVersion(final byte[] aid) {
|
||||||
private static final SecurityTokenConnection SECURITY_TOKEN_HELPER = new SecurityTokenConnection();
|
float minv = aid[7];
|
||||||
|
while (minv > 0) minv /= 10.0;
|
||||||
|
return aid[6] + minv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import android.support.v4.app.TaskStackBuilder;
|
|||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.securitytoken.KeyFormat;
|
import org.sufficientlysecure.keychain.securitytoken.KeyFormat;
|
||||||
|
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenConnection;
|
||||||
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo;
|
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo;
|
||||||
import org.sufficientlysecure.keychain.ui.base.BaseSecurityTokenActivity;
|
import org.sufficientlysecure.keychain.ui.base.BaseSecurityTokenActivity;
|
||||||
import org.sufficientlysecure.keychain.ui.token.ManageSecurityTokenFragment;
|
import org.sufficientlysecure.keychain.ui.token.ManageSecurityTokenFragment;
|
||||||
@@ -133,17 +134,17 @@ public class CreateKeyActivity extends BaseSecurityTokenActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doSecurityTokenInBackground() throws IOException {
|
protected void doSecurityTokenInBackground(SecurityTokenConnection stConnection) throws IOException {
|
||||||
if (mCurrentFragment instanceof SecurityTokenListenerFragment) {
|
if (mCurrentFragment instanceof SecurityTokenListenerFragment) {
|
||||||
((SecurityTokenListenerFragment) mCurrentFragment).doSecurityTokenInBackground();
|
((SecurityTokenListenerFragment) mCurrentFragment).doSecurityTokenInBackground();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenInfo = mSecurityTokenConnection.getTokenInfo();
|
tokenInfo = stConnection.getTokenInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSecurityTokenPostExecute() {
|
protected void onSecurityTokenPostExecute(SecurityTokenConnection stConnection) {
|
||||||
handleTokenInfo(tokenInfo);
|
handleTokenInfo(tokenInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import android.widget.ViewAnimator;
|
|||||||
import nordpol.android.NfcGuideView;
|
import nordpol.android.NfcGuideView;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenConnection;
|
||||||
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo;
|
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo;
|
||||||
import org.sufficientlysecure.keychain.service.input.SecurityTokenChangePinParcel;
|
import org.sufficientlysecure.keychain.service.input.SecurityTokenChangePinParcel;
|
||||||
import org.sufficientlysecure.keychain.ui.base.BaseSecurityTokenActivity;
|
import org.sufficientlysecure.keychain.ui.base.BaseSecurityTokenActivity;
|
||||||
@@ -138,15 +139,15 @@ public class SecurityTokenChangePinOperationActivity extends BaseSecurityTokenAc
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doSecurityTokenInBackground() throws IOException {
|
protected void doSecurityTokenInBackground(SecurityTokenConnection stConnection) throws IOException {
|
||||||
mSecurityTokenConnection.setAdminPin(new Passphrase(changePinInput.getAdminPin()));
|
Passphrase adminPin = new Passphrase(changePinInput.getAdminPin());
|
||||||
mSecurityTokenConnection.resetPin(changePinInput.getNewPin());
|
stConnection.resetPin(adminPin, changePinInput.getNewPin());
|
||||||
|
|
||||||
resultTokenInfo = mSecurityTokenConnection.getTokenInfo();
|
resultTokenInfo = stConnection.getTokenInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final void onSecurityTokenPostExecute() {
|
protected final void onSecurityTokenPostExecute(final SecurityTokenConnection stConnection) {
|
||||||
Intent result = new Intent();
|
Intent result = new Intent();
|
||||||
result.putExtra(RESULT_TOKEN_INFO, resultTokenInfo);
|
result.putExtra(RESULT_TOKEN_INFO, resultTokenInfo);
|
||||||
setResult(RESULT_OK, result);
|
setResult(RESULT_OK, result);
|
||||||
@@ -156,17 +157,17 @@ public class SecurityTokenChangePinOperationActivity extends BaseSecurityTokenAc
|
|||||||
|
|
||||||
nfcGuideView.setCurrentStatus(NfcGuideView.NfcGuideViewStatus.DONE);
|
nfcGuideView.setCurrentStatus(NfcGuideView.NfcGuideViewStatus.DONE);
|
||||||
|
|
||||||
if (mSecurityTokenConnection.isPersistentConnectionAllowed()) {
|
if (stConnection.isPersistentConnectionAllowed()) {
|
||||||
// Just close
|
// Just close
|
||||||
finish();
|
finish();
|
||||||
} else {
|
} else {
|
||||||
mSecurityTokenConnection.clearSecureMessaging();
|
stConnection.clearSecureMessaging();
|
||||||
new AsyncTask<Void, Void, Void>() {
|
new AsyncTask<Void, Void, Void>() {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
// check all 200ms if Security Token has been taken away
|
// check all 200ms if Security Token has been taken away
|
||||||
while (true) {
|
while (true) {
|
||||||
if (isSecurityTokenConnected()) {
|
if (stConnection.isConnected()) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(200);
|
Thread.sleep(200);
|
||||||
} catch (InterruptedException ignored) {
|
} catch (InterruptedException ignored) {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
|||||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||||
import org.sufficientlysecure.keychain.securitytoken.KeyType;
|
import org.sufficientlysecure.keychain.securitytoken.KeyType;
|
||||||
|
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenConnection;
|
||||||
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo;
|
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo;
|
||||||
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;
|
||||||
@@ -185,12 +186,12 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doSecurityTokenInBackground() throws IOException {
|
protected void doSecurityTokenInBackground(SecurityTokenConnection stConnection) throws IOException {
|
||||||
|
|
||||||
switch (mRequiredInput.mType) {
|
switch (mRequiredInput.mType) {
|
||||||
case SECURITY_TOKEN_DECRYPT: {
|
case SECURITY_TOKEN_DECRYPT: {
|
||||||
long tokenKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(
|
long tokenKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(
|
||||||
mSecurityTokenConnection.getKeyFingerprint(KeyType.ENCRYPT));
|
stConnection.getKeyFingerprint(KeyType.ENCRYPT));
|
||||||
|
|
||||||
if (tokenKeyId != mRequiredInput.getSubKeyId()) {
|
if (tokenKeyId != mRequiredInput.getSubKeyId()) {
|
||||||
throw new IOException(getString(R.string.error_wrong_security_token));
|
throw new IOException(getString(R.string.error_wrong_security_token));
|
||||||
@@ -208,7 +209,7 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
|
|||||||
|
|
||||||
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 = mSecurityTokenConnection
|
byte[] decryptedSessionKey = stConnection
|
||||||
.decryptSessionKey(encryptedSessionKey, publicKeyRing.getPublicKey(tokenKeyId));
|
.decryptSessionKey(encryptedSessionKey, publicKeyRing.getPublicKey(tokenKeyId));
|
||||||
mInputParcel = mInputParcel.withCryptoData(encryptedSessionKey, decryptedSessionKey);
|
mInputParcel = mInputParcel.withCryptoData(encryptedSessionKey, decryptedSessionKey);
|
||||||
}
|
}
|
||||||
@@ -216,7 +217,7 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
|
|||||||
}
|
}
|
||||||
case SECURITY_TOKEN_SIGN: {
|
case SECURITY_TOKEN_SIGN: {
|
||||||
long tokenKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(
|
long tokenKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(
|
||||||
mSecurityTokenConnection.getKeyFingerprint(KeyType.SIGN));
|
stConnection.getKeyFingerprint(KeyType.SIGN));
|
||||||
|
|
||||||
if (tokenKeyId != mRequiredInput.getSubKeyId()) {
|
if (tokenKeyId != mRequiredInput.getSubKeyId()) {
|
||||||
throw new IOException(getString(R.string.error_wrong_security_token));
|
throw new IOException(getString(R.string.error_wrong_security_token));
|
||||||
@@ -227,15 +228,13 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
|
|||||||
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 = mSecurityTokenConnection.calculateSignature(hash, algo);
|
byte[] signedHash = stConnection.calculateSignature(hash, algo);
|
||||||
mInputParcel = mInputParcel.withCryptoData(hash, signedHash);
|
mInputParcel = mInputParcel.withCryptoData(hash, signedHash);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SECURITY_TOKEN_MOVE_KEY_TO_CARD: {
|
case SECURITY_TOKEN_MOVE_KEY_TO_CARD: {
|
||||||
// TODO: assume PIN and Admin PIN to be default for this operation
|
Passphrase adminPin = new Passphrase("12345678");
|
||||||
mSecurityTokenConnection.setPin(new Passphrase("123456"));
|
|
||||||
mSecurityTokenConnection.setAdminPin(new Passphrase("12345678"));
|
|
||||||
|
|
||||||
KeyRepository keyRepository =
|
KeyRepository keyRepository =
|
||||||
KeyRepository.create(this);
|
KeyRepository.create(this);
|
||||||
@@ -257,7 +256,7 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
|
|||||||
long subkeyId = buf.getLong();
|
long subkeyId = buf.getLong();
|
||||||
|
|
||||||
CanonicalizedSecretKey key = secretKeyRing.getSecretKey(subkeyId);
|
CanonicalizedSecretKey key = secretKeyRing.getSecretKey(subkeyId);
|
||||||
byte[] tokenSerialNumber = Arrays.copyOf(mSecurityTokenConnection.getAid(), 16);
|
byte[] tokenSerialNumber = Arrays.copyOf(stConnection.getAid(), 16);
|
||||||
|
|
||||||
Passphrase passphrase;
|
Passphrase passphrase;
|
||||||
try {
|
try {
|
||||||
@@ -267,21 +266,21 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
|
|||||||
throw new IOException("Unable to get cached passphrase!");
|
throw new IOException("Unable to get cached passphrase!");
|
||||||
}
|
}
|
||||||
|
|
||||||
mSecurityTokenConnection.changeKey(key, passphrase);
|
stConnection.changeKey(key, passphrase, adminPin);
|
||||||
|
|
||||||
// TODO: Is this really used anywhere?
|
// TODO: Is this really used anywhere?
|
||||||
mInputParcel = mInputParcel.withCryptoData(subkeyBytes, tokenSerialNumber);
|
mInputParcel = mInputParcel.withCryptoData(subkeyBytes, tokenSerialNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
// change PINs afterwards
|
// change PINs afterwards
|
||||||
mSecurityTokenConnection.modifyPin(0x81, newPin);
|
stConnection.modifyPin(0x81, newPin, null);
|
||||||
mSecurityTokenConnection.modifyPin(0x83, newAdminPin);
|
stConnection.modifyPin(0x83, newAdminPin, adminPin);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SECURITY_TOKEN_RESET_CARD: {
|
case SECURITY_TOKEN_RESET_CARD: {
|
||||||
mSecurityTokenConnection.resetAndWipeToken();
|
stConnection.resetAndWipeToken();
|
||||||
mResultTokenInfo = mSecurityTokenConnection.getTokenInfo();
|
mResultTokenInfo = stConnection.getTokenInfo();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -293,7 +292,7 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final void onSecurityTokenPostExecute() {
|
protected final void onSecurityTokenPostExecute(final SecurityTokenConnection stConnection) {
|
||||||
handleResult(mInputParcel);
|
handleResult(mInputParcel);
|
||||||
|
|
||||||
// show finish
|
// show finish
|
||||||
@@ -301,17 +300,17 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
|
|||||||
|
|
||||||
nfcGuideView.setCurrentStatus(NfcGuideView.NfcGuideViewStatus.DONE);
|
nfcGuideView.setCurrentStatus(NfcGuideView.NfcGuideViewStatus.DONE);
|
||||||
|
|
||||||
if (mSecurityTokenConnection.isPersistentConnectionAllowed()) {
|
if (stConnection.isPersistentConnectionAllowed()) {
|
||||||
// Just close
|
// Just close
|
||||||
finish();
|
finish();
|
||||||
} else {
|
} else {
|
||||||
mSecurityTokenConnection.clearSecureMessaging();
|
stConnection.clearSecureMessaging();
|
||||||
new AsyncTask<Void, Void, Void>() {
|
new AsyncTask<Void, Void, Void>() {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
// check all 200ms if Security Token has been taken away
|
// check all 200ms if Security Token has been taken away
|
||||||
while (true) {
|
while (true) {
|
||||||
if (isSecurityTokenConnected()) {
|
if (stConnection.isConnected()) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(200);
|
Thread.sleep(200);
|
||||||
} catch (InterruptedException ignored) {
|
} catch (InterruptedException ignored) {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import android.view.animation.DecelerateInterpolator;
|
|||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.securitytoken.NfcSweetspotData;
|
import org.sufficientlysecure.keychain.securitytoken.NfcSweetspotData;
|
||||||
|
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenConnection;
|
||||||
import org.sufficientlysecure.keychain.ui.base.BaseSecurityTokenActivity;
|
import org.sufficientlysecure.keychain.ui.base.BaseSecurityTokenActivity;
|
||||||
|
|
||||||
|
|
||||||
@@ -88,7 +89,7 @@ public class ShowNfcSweetspotActivity extends BaseSecurityTokenActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSecurityTokenPostExecute() {
|
protected void onSecurityTokenPostExecute(SecurityTokenConnection stConnection) {
|
||||||
Intent result = new Intent();
|
Intent result = new Intent();
|
||||||
result.putExtra(EXTRA_TOKEN_INFO, tokenInfo);
|
result.putExtra(EXTRA_TOKEN_INFO, tokenInfo);
|
||||||
setResult(Activity.RESULT_OK, result);
|
setResult(Activity.RESULT_OK, result);
|
||||||
|
|||||||
@@ -68,12 +68,12 @@ public abstract class BaseSecurityTokenActivity 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 SecurityTokenConnection mSecurityTokenConnection = SecurityTokenConnection.getInstance();
|
|
||||||
protected TagDispatcher mNfcTagDispatcher;
|
protected TagDispatcher mNfcTagDispatcher;
|
||||||
protected UsbConnectionDispatcher mUsbDispatcher;
|
protected UsbConnectionDispatcher mUsbDispatcher;
|
||||||
private boolean mTagHandlingEnabled;
|
private boolean mTagHandlingEnabled;
|
||||||
|
|
||||||
protected SecurityTokenInfo tokenInfo;
|
protected SecurityTokenInfo tokenInfo;
|
||||||
|
private Passphrase mCachedPin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override to change UI before SecurityToken handling (UI thread)
|
* Override to change UI before SecurityToken handling (UI thread)
|
||||||
@@ -84,15 +84,15 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
|
|||||||
/**
|
/**
|
||||||
* Override to implement SecurityToken operations (background thread)
|
* Override to implement SecurityToken operations (background thread)
|
||||||
*/
|
*/
|
||||||
protected void doSecurityTokenInBackground() throws IOException {
|
protected void doSecurityTokenInBackground(SecurityTokenConnection stConnection) throws IOException {
|
||||||
tokenInfo = mSecurityTokenConnection.getTokenInfo();
|
tokenInfo = stConnection.getTokenInfo();
|
||||||
Log.d(Constants.TAG, "Security Token: " + tokenInfo);
|
Log.d(Constants.TAG, "Security Token: " + tokenInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override to handle result of SecurityToken operations (UI thread)
|
* Override to handle result of SecurityToken operations (UI thread)
|
||||||
*/
|
*/
|
||||||
protected void onSecurityTokenPostExecute() {
|
protected void onSecurityTokenPostExecute(SecurityTokenConnection stConnection) {
|
||||||
Intent intent = new Intent(this, CreateKeyActivity.class);
|
Intent intent = new Intent(this, CreateKeyActivity.class);
|
||||||
intent.putExtra(CreateKeyActivity.EXTRA_SECURITY_TOKEN_INFO, tokenInfo);
|
intent.putExtra(CreateKeyActivity.EXTRA_SECURITY_TOKEN_INFO, tokenInfo);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
@@ -138,6 +138,10 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
|
|||||||
// Actual Security Token operations are executed in doInBackground to not block the UI thread
|
// Actual Security Token operations are executed in doInBackground to not block the UI thread
|
||||||
if (!mTagHandlingEnabled)
|
if (!mTagHandlingEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
final SecurityTokenConnection stConnection =
|
||||||
|
SecurityTokenConnection.getInstanceForTransport(transport, mCachedPin);
|
||||||
|
|
||||||
new AsyncTask<Void, Void, IOException>() {
|
new AsyncTask<Void, Void, IOException>() {
|
||||||
@Override
|
@Override
|
||||||
protected void onPreExecute() {
|
protected void onPreExecute() {
|
||||||
@@ -148,7 +152,9 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
|
|||||||
@Override
|
@Override
|
||||||
protected IOException doInBackground(Void... params) {
|
protected IOException doInBackground(Void... params) {
|
||||||
try {
|
try {
|
||||||
handleSecurityToken(transport, BaseSecurityTokenActivity.this);
|
stConnection.connectIfNecessary(getBaseContext());
|
||||||
|
|
||||||
|
handleSecurityToken(stConnection);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -161,11 +167,11 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
|
|||||||
super.onPostExecute(exception);
|
super.onPostExecute(exception);
|
||||||
|
|
||||||
if (exception != null) {
|
if (exception != null) {
|
||||||
handleSecurityTokenError(exception);
|
handleSecurityTokenError(stConnection, exception);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSecurityTokenPostExecute();
|
onSecurityTokenPostExecute(stConnection);
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
@@ -223,7 +229,7 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
|
|||||||
mNfcTagDispatcher.interceptIntent(intent);
|
mNfcTagDispatcher.interceptIntent(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSecurityTokenError(IOException e) {
|
private void handleSecurityTokenError(SecurityTokenConnection stConnection, IOException e) {
|
||||||
|
|
||||||
if (e instanceof TagLostException) {
|
if (e instanceof TagLostException) {
|
||||||
onSecurityTokenError(getString(R.string.security_token_error_tag_lost));
|
onSecurityTokenError(getString(R.string.security_token_error_tag_lost));
|
||||||
@@ -250,7 +256,7 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
|
|||||||
|
|
||||||
SecurityTokenInfo tokeninfo = null;
|
SecurityTokenInfo tokeninfo = null;
|
||||||
try {
|
try {
|
||||||
tokeninfo = mSecurityTokenConnection.getTokenInfo();
|
tokeninfo = stConnection.getTokenInfo();
|
||||||
} catch (IOException e2) {
|
} catch (IOException e2) {
|
||||||
// don't care
|
// don't care
|
||||||
}
|
}
|
||||||
@@ -271,7 +277,7 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
|
|||||||
case 0x6982: {
|
case 0x6982: {
|
||||||
SecurityTokenInfo tokeninfo = null;
|
SecurityTokenInfo tokeninfo = null;
|
||||||
try {
|
try {
|
||||||
tokeninfo = mSecurityTokenConnection.getTokenInfo();
|
tokeninfo = stConnection.getTokenInfo();
|
||||||
} catch (IOException e2) {
|
} catch (IOException e2) {
|
||||||
// don't care
|
// don't care
|
||||||
}
|
}
|
||||||
@@ -325,7 +331,7 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
|
|||||||
}
|
}
|
||||||
// 6A82 app not installed on security token!
|
// 6A82 app not installed on security token!
|
||||||
case 0x6A82: {
|
case 0x6A82: {
|
||||||
if (mSecurityTokenConnection.isFidesmoToken()) {
|
if (stConnection.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();
|
||||||
@@ -391,12 +397,11 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void obtainSecurityTokenPin(RequiredInputParcel requiredInput) {
|
protected void obtainSecurityTokenPin(RequiredInputParcel requiredInput) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Passphrase passphrase = PassphraseCacheService.getCachedPassphrase(this,
|
Passphrase passphrase = PassphraseCacheService.getCachedPassphrase(this,
|
||||||
requiredInput.getMasterKeyId(), requiredInput.getSubKeyId());
|
requiredInput.getMasterKeyId(), requiredInput.getSubKeyId());
|
||||||
if (passphrase != null) {
|
if (passphrase != null) {
|
||||||
mSecurityTokenConnection.setPin(passphrase);
|
mCachedPin = passphrase;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,7 +426,7 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CryptoInputParcel input = data.getParcelableExtra(PassphraseDialogActivity.RESULT_CRYPTO_INPUT);
|
CryptoInputParcel input = data.getParcelableExtra(PassphraseDialogActivity.RESULT_CRYPTO_INPUT);
|
||||||
mSecurityTokenConnection.setPin(input.getPassphrase());
|
mCachedPin = input.getPassphrase();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -429,19 +434,8 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleSecurityToken(Transport transport, Context ctx) throws IOException {
|
protected void handleSecurityToken(SecurityTokenConnection stConnection) throws IOException {
|
||||||
// Don't reconnect if device was already connected
|
doSecurityTokenInBackground(stConnection);
|
||||||
if (!(mSecurityTokenConnection.isPersistentConnectionAllowed()
|
|
||||||
&& mSecurityTokenConnection.isConnected()
|
|
||||||
&& mSecurityTokenConnection.getTransport().equals(transport))) {
|
|
||||||
mSecurityTokenConnection.setTransport(transport);
|
|
||||||
mSecurityTokenConnection.connectToDevice(ctx);
|
|
||||||
}
|
|
||||||
doSecurityTokenInBackground();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSecurityTokenConnected() {
|
|
||||||
return mSecurityTokenConnection.isConnected();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class IsoDepNotSupportedException extends IOException {
|
public static class IsoDepNotSupportedException extends IOException {
|
||||||
@@ -500,10 +494,6 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
|
|||||||
mUsbDispatcher.onStart();
|
mUsbDispatcher.onStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecurityTokenConnection getSecurityTokenHelper() {
|
|
||||||
return mSecurityTokenConnection;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run Security Token routines if last used token is connected and supports
|
* Run Security Token routines if last used token is connected and supports
|
||||||
* persistent connections
|
* persistent connections
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ import org.sufficientlysecure.keychain.provider.KeyRepository;
|
|||||||
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
|
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenConnection;
|
||||||
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
|
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
|
||||||
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
|
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
|
||||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||||
@@ -619,8 +620,8 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSecurityTokenPostExecute() {
|
protected void onSecurityTokenPostExecute(SecurityTokenConnection stConnection) {
|
||||||
super.onSecurityTokenPostExecute();
|
super.onSecurityTokenPostExecute(stConnection);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user