Merge pull request #1835 from nmikhailov/check_security_token

Check security token
This commit is contained in:
Dominik Schürmann
2016-04-16 11:50:23 +02:00
12 changed files with 48 additions and 29 deletions

View File

@@ -47,7 +47,7 @@ import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
import org.sufficientlysecure.keychain.service.UploadKeyringParcel;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.SecurityTokenSignOperationsBuilder;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Passphrase;
@@ -144,7 +144,7 @@ public class CertifyOperation extends BaseOperation<CertifyActionsParcel> {
int certifyOk = 0, certifyError = 0, uploadOk = 0, uploadError = 0;
NfcSignOperationsBuilder allRequiredInput = new NfcSignOperationsBuilder(
SecurityTokenSignOperationsBuilder allRequiredInput = new SecurityTokenSignOperationsBuilder(
cryptoInput.getSignatureTime(), masterKeyId, masterKeyId);
// Work through all requested certifications

View File

@@ -43,7 +43,7 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.SecurityTokenSignOperationsBuilder;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.RequiredInputType;
import org.sufficientlysecure.keychain.util.FileHelper;
import org.sufficientlysecure.keychain.util.InputData;
@@ -80,7 +80,7 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> {
int total = inputBytes != null ? 1 : inputUris.size(), count = 0;
ArrayList<PgpSignEncryptResult> results = new ArrayList<>();
NfcSignOperationsBuilder pendingInputBuilder = null;
SecurityTokenSignOperationsBuilder pendingInputBuilder = null;
// if signing subkey has not explicitly been set, get first usable subkey capable of signing
if (input.getSignatureMasterKeyId() != Constants.key.none
@@ -161,7 +161,7 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> {
return new SignEncryptResult(log, requiredInput, results, cryptoInput);
}
if (pendingInputBuilder == null) {
pendingInputBuilder = new NfcSignOperationsBuilder(requiredInput.mSignatureTime,
pendingInputBuilder = new SecurityTokenSignOperationsBuilder(requiredInput.mSignatureTime,
input.getSignatureMasterKeyId(), input.getSignatureSubKeyId());
}
pendingInputBuilder.addAll(requiredInput);

View File

@@ -37,7 +37,7 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogTyp
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.SecurityTokenSignOperationsBuilder;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
@@ -76,7 +76,7 @@ public class PgpCertifyOperation {
// get the master subkey (which we certify for)
PGPPublicKey publicKey = publicRing.getPublicKey().getPublicKey();
NfcSignOperationsBuilder requiredInput = new NfcSignOperationsBuilder(creationTimestamp,
SecurityTokenSignOperationsBuilder requiredInput = new SecurityTokenSignOperationsBuilder(creationTimestamp,
publicKey.getKeyID(), publicKey.getKeyID());
try {

View File

@@ -769,7 +769,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
&& !decryptorFactory.hasCachedSessionData(encryptedDataAsymmetric)) {
log.add(LogType.MSG_DC_PENDING_NFC, indent + 1);
return result.with(new DecryptVerifyResult(log, RequiredInputParcel.createNfcDecryptOperation(
return result.with(new DecryptVerifyResult(log, RequiredInputParcel.createSecurityTokenDecryptOperation(
decryptionKey.getRing().getMasterKeyId(),
decryptionKey.getKeyId(), encryptedDataAsymmetric.getSessionKey()[0]
), cryptoInput));

View File

@@ -78,8 +78,8 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcKeyToCardOperationsBuilder;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.SecurityTokenKeyToCardOperationsBuilder;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.SecurityTokenSignOperationsBuilder;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
@@ -496,10 +496,10 @@ public class PgpKeyOperation {
OperationLog log,
int indent) {
NfcSignOperationsBuilder nfcSignOps = new NfcSignOperationsBuilder(
SecurityTokenSignOperationsBuilder nfcSignOps = new SecurityTokenSignOperationsBuilder(
cryptoInput.getSignatureTime(), masterSecretKey.getKeyID(),
masterSecretKey.getKeyID());
NfcKeyToCardOperationsBuilder nfcKeyToCardOps = new NfcKeyToCardOperationsBuilder(
SecurityTokenKeyToCardOperationsBuilder nfcKeyToCardOps = new SecurityTokenKeyToCardOperationsBuilder(
masterSecretKey.getKeyID());
progress(R.string.progress_modify, 0);
@@ -1277,7 +1277,7 @@ public class PgpKeyOperation {
PGPPublicKey masterPublicKey,
int flags, long expiry,
CryptoInputParcel cryptoInput,
NfcSignOperationsBuilder nfcSignOps,
SecurityTokenSignOperationsBuilder nfcSignOps,
int indent, OperationLog log)
throws PGPException, IOException, SignatureException {

View File

@@ -520,7 +520,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
} catch (NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded e) {
// this secret key diverts to a OpenPGP card, throw exception with hash that will be signed
log.add(LogType.MSG_PSE_PENDING_NFC, indent);
return new PgpSignEncryptResult(log, RequiredInputParcel.createNfcSignOperation(
return new PgpSignEncryptResult(log, RequiredInputParcel.createSecurityTokenSignOperation(
signingKey.getRing().getMasterKeyId(), signingKey.getKeyId(),
e.hashToSign, e.hashAlgo, cryptoInput.getSignatureTime()), cryptoInput);
}

View File

@@ -53,7 +53,7 @@ public class ApiPendingIntentFactory {
case SECURITY_TOKEN_MOVE_KEY_TO_CARD:
case SECURITY_TOKEN_DECRYPT:
case SECURITY_TOKEN_SIGN: {
return createNfcOperationPendingIntent(data, requiredInput, cryptoInput);
return createSecurityTokenOperationPendingIntent(data, requiredInput, cryptoInput);
}
case PASSPHRASE: {
@@ -65,7 +65,7 @@ public class ApiPendingIntentFactory {
}
}
private PendingIntent createNfcOperationPendingIntent(Intent data, RequiredInputParcel requiredInput, CryptoInputParcel cryptoInput) {
private PendingIntent createSecurityTokenOperationPendingIntent(Intent data, RequiredInputParcel requiredInput, CryptoInputParcel cryptoInput) {
Intent intent = new Intent(mContext, RemoteSecurityTokenOperationActivity.class);
// pass params through to activity that it can be returned again later to repeat pgp operation
intent.putExtra(RemoteSecurityTokenOperationActivity.EXTRA_REQUIRED_INPUT, requiredInput);

View File

@@ -22,6 +22,8 @@
package org.sufficientlysecure.keychain.securitytoken;
import android.support.annotation.NonNull;
import org.bouncycastle.bcpg.HashAlgorithmTags;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Hex;
@@ -131,13 +133,13 @@ public class SecurityTokenHelper {
private boolean isSlotEmpty(KeyType keyType) throws IOException {
// Note: special case: This should not happen, but happens with
// https://github.com/FluffyKaon/OpenPGP-Card, thus for now assume true
if (getMasterKeyFingerprint(keyType.getIdx()) == null) return true;
if (getKeyFingerprint(keyType) == null) return true;
return keyMatchesFingerPrint(keyType, BLANK_FINGERPRINT);
}
public boolean keyMatchesFingerPrint(KeyType keyType, byte[] fingerprint) throws IOException {
return java.util.Arrays.equals(getMasterKeyFingerprint(keyType.getIdx()), fingerprint);
return java.util.Arrays.equals(getKeyFingerprint(keyType), fingerprint);
}
/**
@@ -723,10 +725,10 @@ public class SecurityTokenHelper {
* Return the fingerprint from application specific data stored on tag, or
* null if it doesn't exist.
*
* @param idx Index of the key to return the fingerprint from.
* @param keyType key type
* @return The fingerprint of the requested key, or null if not found.
*/
public byte[] getMasterKeyFingerprint(int idx) throws IOException {
public byte[] getKeyFingerprint(@NonNull KeyType keyType) throws IOException {
byte[] data = getFingerprints();
if (data == null) {
return null;
@@ -735,7 +737,7 @@ public class SecurityTokenHelper {
// return the master key fingerprint
ByteBuffer fpbuf = ByteBuffer.wrap(data);
byte[] fp = new byte[20];
fpbuf.position(idx * 20);
fpbuf.position(keyType.getIdx() * 20);
fpbuf.get(fp, 0, 20);
return fp;

View File

@@ -89,7 +89,7 @@ public class RequiredInputParcel implements Parcelable {
return new RequiredInputParcel(RequiredInputType.ENABLE_ORBOT, null, null, null, 0L, 0L);
}
public static RequiredInputParcel createNfcSignOperation(
public static RequiredInputParcel createSecurityTokenSignOperation(
long masterKeyId, long subKeyId,
byte[] inputHash, int signAlgo, Date signatureTime) {
return new RequiredInputParcel(RequiredInputType.SECURITY_TOKEN_SIGN,
@@ -97,13 +97,13 @@ public class RequiredInputParcel implements Parcelable {
signatureTime, masterKeyId, subKeyId);
}
public static RequiredInputParcel createNfcDecryptOperation(
public static RequiredInputParcel createSecurityTokenDecryptOperation(
long masterKeyId, long subKeyId, byte[] encryptedSessionKey) {
return new RequiredInputParcel(RequiredInputType.SECURITY_TOKEN_DECRYPT,
new byte[][] { encryptedSessionKey }, null, null, masterKeyId, subKeyId);
}
public static RequiredInputParcel createNfcReset() {
public static RequiredInputParcel createSecurityTokenReset() {
return new RequiredInputParcel(RequiredInputType.SECURITY_TOKEN_RESET_CARD,
null, null, null, null, null);
}
@@ -188,14 +188,14 @@ public class RequiredInputParcel implements Parcelable {
}
};
public static class NfcSignOperationsBuilder {
public static class SecurityTokenSignOperationsBuilder {
Date mSignatureTime;
ArrayList<Integer> mSignAlgos = new ArrayList<>();
ArrayList<byte[]> mInputHashes = new ArrayList<>();
long mMasterKeyId;
long mSubKeyId;
public NfcSignOperationsBuilder(Date signatureTime, long masterKeyId, long subKeyId) {
public SecurityTokenSignOperationsBuilder(Date signatureTime, long masterKeyId, long subKeyId) {
mSignatureTime = signatureTime;
mMasterKeyId = masterKeyId;
mSubKeyId = subKeyId;
@@ -238,13 +238,13 @@ public class RequiredInputParcel implements Parcelable {
}
public static class NfcKeyToCardOperationsBuilder {
public static class SecurityTokenKeyToCardOperationsBuilder {
ArrayList<byte[]> mSubkeysToExport = new ArrayList<>();
Long mMasterKeyId;
byte[] mPin;
byte[] mAdminPin;
public NfcKeyToCardOperationsBuilder(Long masterKeyId) {
public SecurityTokenKeyToCardOperationsBuilder(Long masterKeyId) {
mMasterKeyId = masterKeyId;
}

View File

@@ -230,7 +230,7 @@ public class CreateSecurityTokenImportResetFragment
public void resetCard() {
Intent intent = new Intent(getActivity(), SecurityTokenOperationActivity.class);
RequiredInputParcel resetP = RequiredInputParcel.createNfcReset();
RequiredInputParcel resetP = RequiredInputParcel.createSecurityTokenReset();
intent.putExtra(SecurityTokenOperationActivity.EXTRA_REQUIRED_INPUT, resetP);
intent.putExtra(SecurityTokenOperationActivity.EXTRA_CRYPTO_INPUT, new CryptoInputParcel());
startActivityForResult(intent, REQUEST_CODE_RESET);

View File

@@ -36,10 +36,12 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.securitytoken.KeyType;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.ui.base.BaseSecurityTokenNfcActivity;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.ThemeChanger;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.OrientationUtils;
@@ -183,6 +185,13 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenNfcActivity
switch (mRequiredInput.mType) {
case SECURITY_TOKEN_DECRYPT: {
long tokenKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(
mSecurityTokenHelper.getKeyFingerprint(KeyType.ENCRYPT));
if (tokenKeyId != mRequiredInput.getSubKeyId()) {
throw new IOException(getString(R.string.error_wrong_security_token));
}
for (int i = 0; i < mRequiredInput.mInputData.length; i++) {
byte[] encryptedSessionKey = mRequiredInput.mInputData[i];
byte[] decryptedSessionKey = mSecurityTokenHelper.decryptSessionKey(encryptedSessionKey);
@@ -191,6 +200,13 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenNfcActivity
break;
}
case SECURITY_TOKEN_SIGN: {
long tokenKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(
mSecurityTokenHelper.getKeyFingerprint(KeyType.SIGN));
if (tokenKeyId != mRequiredInput.getSubKeyId()) {
throw new IOException(getString(R.string.error_wrong_security_token));
}
mInputParcel.addSignatureTime(mRequiredInput.mSignatureTime);
for (int i = 0; i < mRequiredInput.mInputData.length; i++) {

View File

@@ -380,6 +380,7 @@
<string name="error_integrity_check_failed">"integrity check failed! Data has been modified!"</string>
<string name="error_wrong_passphrase">"wrong password"</string>
<string name="error_could_not_extract_private_key">"could not extract private key"</string>
<string name="error_wrong_security_token">"this security token doesn't contain required key"</string>
<!-- errors without preceeding Error: -->
<string name="error_jelly_bean_needed">"You need Android 4.1 to use Android's NFC Beam feature!"</string>