add AndroidPassphraseCacheInterface abstraction

This commit is contained in:
Vincent Breitmoser 2018-07-18 18:15:06 +02:00
parent 83f5f557f0
commit 0987c18d8b
8 changed files with 68 additions and 75 deletions

View File

@ -0,0 +1,47 @@
package org.sufficientlysecure.keychain.operations;
import android.content.Context;
import org.sufficientlysecure.keychain.Constants.key;
import org.sufficientlysecure.keychain.daos.KeyRepository;
import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.util.Passphrase;
public class AndroidPassphraseCacheInterface implements PassphraseCacheInterface {
public static AndroidPassphraseCacheInterface getInstance(Context context) {
KeyRepository keyRepository = KeyRepository.create(context);
return new AndroidPassphraseCacheInterface(context, keyRepository);
}
private Context context;
private KeyRepository keyRepository;
private AndroidPassphraseCacheInterface(Context context, KeyRepository keyRepository) {
this.context = context;
this.keyRepository = keyRepository;
}
@Override
public Passphrase getCachedPassphrase(long subKeyId) {
if (subKeyId != key.symmetric) {
Long masterKeyId = keyRepository.getMasterKeyIdBySubkeyId(subKeyId);
if (masterKeyId == null) {
return null;
}
return getCachedPassphrase(masterKeyId, subKeyId);
}
return getCachedPassphrase(key.symmetric, key.symmetric);
}
@Override
public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) {
try {
return PassphraseCacheService.getCachedPassphrase(context, masterKeyId, subKeyId);
} catch (PassphraseCacheService.KeyNotFoundException e) {
return null;
}
}
}

View File

@ -25,22 +25,20 @@ import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import org.sufficientlysecure.keychain.Constants.key;
import org.sufficientlysecure.keychain.daos.KeyRepository;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.util.Passphrase;
public abstract class BaseOperation<T extends Parcelable> implements PassphraseCacheInterface {
public abstract class BaseOperation<T extends Parcelable> {
final public Context mContext;
final public Progressable mProgressable;
final public AtomicBoolean mCancelled;
final public KeyRepository mKeyRepository;
final public AndroidPassphraseCacheInterface passphraseCacheInterface;
/** An abstract base class for all *Operation classes. It provides a number
* of common methods for progress, cancellation and passphrase cache handling.
@ -68,6 +66,7 @@ public abstract class BaseOperation<T extends Parcelable> implements PassphraseC
this.mContext = context;
this.mProgressable = progressable;
this.mKeyRepository = keyRepository;
this.passphraseCacheInterface = AndroidPassphraseCacheInterface.getInstance(context);
mCancelled = null;
}
@ -76,6 +75,7 @@ public abstract class BaseOperation<T extends Parcelable> implements PassphraseC
mContext = context;
mProgressable = progressable;
mKeyRepository = keyRepository;
passphraseCacheInterface = AndroidPassphraseCacheInterface.getInstance(context);
mCancelled = cancelled;
}
@ -103,27 +103,4 @@ public abstract class BaseOperation<T extends Parcelable> implements PassphraseC
mProgressable.setPreventCancel();
}
}
@Override
public Passphrase getCachedPassphrase(long subKeyId) throws NoSecretKeyException {
if (subKeyId != key.symmetric) {
Long masterKeyId = mKeyRepository.getMasterKeyIdBySubkeyId(subKeyId);
if (masterKeyId == null) {
throw new PassphraseCacheInterface.NoSecretKeyException();
}
return getCachedPassphrase(masterKeyId, subKeyId);
}
return getCachedPassphrase(key.symmetric, key.symmetric);
}
@Override
public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException {
try {
return PassphraseCacheService.getCachedPassphrase(
mContext, masterKeyId, subKeyId);
} catch (PassphraseCacheService.KeyNotFoundException e) {
throw new PassphraseCacheInterface.NoSecretKeyException();
}
}
}

View File

@ -35,7 +35,6 @@ import org.sufficientlysecure.keychain.operations.results.UploadResult;
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface;
import org.sufficientlysecure.keychain.pgp.PgpCertifyOperation;
import org.sufficientlysecure.keychain.pgp.PgpCertifyOperation.PgpCertifyResult;
import org.sufficientlysecure.keychain.pgp.Progressable;
@ -89,11 +88,7 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
case PASSPHRASE:
passphrase = cryptoInput.getPassphrase();
if (passphrase == null) {
try {
passphrase = getCachedPassphrase(masterKeyId, masterKeyId);
} catch (PassphraseCacheInterface.NoSecretKeyException ignored) {
// treat as a cache miss for error handling purposes
}
passphrase = passphraseCacheInterface.getCachedPassphrase(masterKeyId, masterKeyId);
}
if (passphrase == null) {

View File

@ -20,13 +20,6 @@ package org.sufficientlysecure.keychain.pgp;
import org.sufficientlysecure.keychain.util.Passphrase;
public interface PassphraseCacheInterface {
class NoSecretKeyException extends Exception {
public NoSecretKeyException() {
}
}
Passphrase getCachedPassphrase(long subKeyId) throws NoSecretKeyException;
Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException;
Passphrase getCachedPassphrase(long subKeyId);
Passphrase getCachedPassphrase(long masterKeyId, long subKeyId);
}

View File

@ -679,18 +679,11 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
} else if (cryptoInput.hasPassphraseForSubkey(subKeyId)) {
passphrase = cryptoInput.getPassphrase();
} else {
// if no passphrase was explicitly set try to get it from the cache service
try {
// returns "" if key has no passphrase
passphrase = getCachedPassphrase(subKeyId);
// returns "" if key has no passphrase
passphrase = passphraseCacheInterface.getCachedPassphrase(subKeyId);
if (passphrase != null) {
log.add(LogType.MSG_DC_PASS_CACHED, indent + 1);
} catch (PassphraseCacheInterface.NoSecretKeyException e) {
log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1);
return result.with(new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log));
}
// if passphrase was not cached, return here indicating that a passphrase is missing!
if (passphrase == null) {
} else {
log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1);
requirePassphraseBuilder.add(masterKeyId, subKeyId);
continue;
@ -741,14 +734,10 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
// indicating that a passphrase is missing!
if (!cryptoInput.hasPassphraseForSymmetric()) {
try {
passphrase = getCachedPassphrase(key.symmetric);
passphrase = passphraseCacheInterface.getCachedPassphrase(key.symmetric);
if (passphrase != null) {
log.add(LogType.MSG_DC_PASS_CACHED, indent + 1);
} catch (PassphraseCacheInterface.NoSecretKeyException e) {
// nvm
}
if (passphrase == null) {
} else {
log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1);
RequiredInputParcel requiredInputParcel = customRequiredInputParcel != null ?
customRequiredInputParcel : RequiredInputParcel.createRequiredSymmetricPassphrase();

View File

@ -270,10 +270,8 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
case PASSPHRASE: {
Passphrase localPassphrase = cryptoInput.getPassphrase();
if (localPassphrase == null) {
try {
localPassphrase = getCachedPassphrase(signingMasterKeyId, signingKey.getKeyId());
} catch (PassphraseCacheInterface.NoSecretKeyException ignored) {
}
localPassphrase = passphraseCacheInterface.getCachedPassphrase(
signingMasterKeyId, signingKey.getKeyId());
}
if (localPassphrase == null) {
log.add(LogType.MSG_PSE_PENDING_PASSPHRASE, indent + 1);

View File

@ -26,15 +26,14 @@ import android.support.annotation.NonNull;
import org.bouncycastle.openpgp.AuthenticationSignatureGenerator;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder;
import org.sufficientlysecure.keychain.daos.KeyRepository;
import org.sufficientlysecure.keychain.daos.KeyRepository.NotFoundException;
import org.sufficientlysecure.keychain.operations.BaseOperation;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.daos.KeyRepository;
import org.sufficientlysecure.keychain.daos.KeyRepository.NotFoundException;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.util.Passphrase;
@ -172,10 +171,7 @@ public class AuthenticationOperation extends BaseOperation<AuthenticationParcel>
case PASSPHRASE: {
Passphrase localPassphrase = cryptoInput.getPassphrase();
if (localPassphrase == null) {
try {
localPassphrase = getCachedPassphrase(authMasterKeyId, authKey.getKeyId());
} catch (PassphraseCacheInterface.NoSecretKeyException ignored) {
}
localPassphrase = passphraseCacheInterface.getCachedPassphrase(authMasterKeyId, authKey.getKeyId());
}
if (localPassphrase == null) {
log.add(LogType.MSG_AUTH_PENDING_PASSPHRASE, indent + 1);

View File

@ -1084,9 +1084,7 @@ public class PgpEncryptDecryptTest {
return new PgpDecryptVerifyOperation(RuntimeEnvironment.application,
KeyWritableRepository.create(RuntimeEnvironment.application), null) {
@Override
public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId)
throws NoSecretKeyException {
public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) {
if (checkMasterKeyId != null) {
Assert.assertEquals("requested passphrase should be for expected master key id",
(long) checkMasterKeyId, masterKeyId);