diff options
6 files changed, 113 insertions, 64 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index d7107d695..4e4e8c4e0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -49,6 +49,8 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult; +import org.sufficientlysecure.keychain.service.results.OperationResultParcel.LogLevel; +import org.sufficientlysecure.keychain.service.results.OperationResultParcel.LogType; import org.sufficientlysecure.keychain.service.results.OperationResultParcel.OperationLog; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; @@ -70,6 +72,7 @@ import java.util.Set; */ public class PgpDecryptVerify { private ProviderHelper mProviderHelper; + private PassphraseCache mPassphraseCache; private InputData mData; private OutputStream mOutStream; @@ -83,6 +86,7 @@ public class PgpDecryptVerify { private PgpDecryptVerify(Builder builder) { // private Constructor can only be called from Builder this.mProviderHelper = builder.mProviderHelper; + this.mPassphraseCache = builder.mPassphraseCache; this.mData = builder.mData; this.mOutStream = builder.mOutStream; @@ -97,6 +101,7 @@ public class PgpDecryptVerify { public static class Builder { // mandatory parameter private ProviderHelper mProviderHelper; + private PassphraseCache mPassphraseCache; private InputData mData; private OutputStream mOutStream; @@ -108,8 +113,10 @@ public class PgpDecryptVerify { private boolean mDecryptMetadataOnly = false; private byte[] mDecryptedSessionKey = null; - public Builder(ProviderHelper providerHelper, InputData data, OutputStream outStream) { + public Builder(ProviderHelper providerHelper, PassphraseCache passphraseCache, + InputData data, OutputStream outStream) { this.mProviderHelper = providerHelper; + this.mPassphraseCache = passphraseCache; this.mData = data; this.mOutStream = outStream; } @@ -169,6 +176,16 @@ public class PgpDecryptVerify { } } + public interface PassphraseCache { + public String getCachedPassphrase(long masterKeyId) + throws NoSecretKeyException; + } + + public static class NoSecretKeyException extends Exception { + public NoSecretKeyException() { + } + } + /** * Decrypts and/or verifies data based on parameters of class */ @@ -286,12 +303,24 @@ public class PgpDecryptVerify { encryptedDataAsymmetric = encData; - // if passphrase was not cached, return here indicating that a passphrase is missing! + // if no passphrase was explicitly set try to get it from the cache service if (mPassphrase == null) { - DecryptVerifyResult result = - new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE, log); - result.setKeyIdPassphraseNeeded(subKeyId); - return result; + try { + // returns "" if key has no passphrase + mPassphrase = mPassphraseCache.getCachedPassphrase(subKeyId); + } catch (NoSecretKeyException e) { + // log.add(LogLevel.ERROR, LogType.MSG_DEC_ERROR_NO_KEY); + return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); + } + + // if passphrase was not cached, return here + // indicating that a passphrase is missing! + if (mPassphrase == null) { + DecryptVerifyResult result = + new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE, log); + result.setKeyIdPassphraseNeeded(subKeyId); + return result; + } } // break out of while, only decrypt the first packet where we have a key diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 1092fe7b4..3dc6f8a6e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -462,32 +462,23 @@ public class OpenPgpService extends RemoteService { .setDecryptMetadataOnly(decryptMetadataOnly) .setNfcState(nfcDecryptedSessionKey); - DecryptVerifyResult decryptVerifyResult; - try { - // TODO: currently does not support binary signed-only content - decryptVerifyResult = builder.build().execute(); - - // throw exceptions upwards to client with meaningful messages - } catch (PgpDecryptVerify.InvalidDataException e) { - throw new Exception(getString(R.string.error_invalid_data)); - } catch (PgpDecryptVerify.KeyExtractionException e) { - throw new Exception(getString(R.string.error_could_not_extract_private_key)); - } catch (PgpDecryptVerify.WrongPassphraseException e) { - throw new Exception(getString(R.string.error_wrong_passphrase)); - } catch (PgpDecryptVerify.NoSecretKeyException e) { - throw new Exception(getString(R.string.error_no_secret_key_found)); - } catch (PgpDecryptVerify.IntegrityCheckFailedException e) { - throw new Exception(getString(R.string.error_integrity_check_failed)); - } catch (PgpDecryptVerify.NeedNfcDataException e) { - // return PendingIntent to execute NFC activity - return getNfcDecryptIntent(data, e.mPassphrase, e.mEncryptedSessionKey); - } - - if (DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE == decryptVerifyResult.getStatus()) { - // get PendingIntent for passphrase input, add it to given params and return to client - return getPassphraseIntent(data, decryptVerifyResult.getKeyIdPassphraseNeeded()); - } else if (DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE == decryptVerifyResult.getStatus()) { - throw new PgpGeneralException("Decryption of symmetric content not supported by API!"); + // TODO: currently does not support binary signed-only content + DecryptVerifyResult decryptVerifyResult = builder.build().execute(); + + if (decryptVerifyResult.isPending()) { + switch (decryptVerifyResult.getResult()) { + case DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE: + return getPassphraseIntent(data, decryptVerifyResult.getKeyIdPassphraseNeeded()); + case DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE: + throw new PgpGeneralException( + "Decryption of symmetric content not supported by API!"); + case DecryptVerifyResult.RESULT_PENDING_NFC: + // TODO get passphrase here? currently not in DecryptVerifyResult + return getNfcDecryptIntent( + data, null, decryptVerifyResult.getNfcEncryptedSessionKey()); + } + throw new PgpGeneralException( + "Encountered unhandled type of pending action not supported by API!"); } OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 2366e0237..966c43597 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -337,15 +337,22 @@ public class KeychainIntentService extends IntentService implements Progressable Bundle resultData = new Bundle(); - /* TODO find passphrase from cache, if not provided - return PassphraseCacheService.getCachedPassphrase( - KeychainIntentService.this, masterKeyId); - */ - // verifyText and decrypt returning additional resultData values for the // verification of signatures PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder( - new ProviderHelper(this), inputData, outStream + new ProviderHelper(this), + new PgpDecryptVerify.PassphraseCache() { + @Override + public String getCachedPassphrase(long masterKeyId) { + try { + return PassphraseCacheService.getCachedPassphrase( + KeychainIntentService.this, masterKeyId); + } catch (PassphraseCacheService.KeyNotFoundException e) { + return null; + } + } + }, + inputData, outStream ); builder.setProgressable(this) .setAllowSymmetricDecryption(true) @@ -378,15 +385,22 @@ public class KeychainIntentService extends IntentService implements Progressable Bundle resultData = new Bundle(); - /* TODO find passphrase from cache, if not provided - return PassphraseCacheService.getCachedPassphrase( - KeychainIntentService.this, masterKeyId); - */ - // verifyText and decrypt returning additional resultData values for the // verification of signatures PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder( - new ProviderHelper(this), inputData, null + new ProviderHelper(this), + new PgpDecryptVerify.PassphraseCache() { + @Override + public String getCachedPassphrase(long masterKeyId) throws PgpDecryptVerify.NoSecretKeyException { + try { + return PassphraseCacheService.getCachedPassphrase( + KeychainIntentService.this, masterKeyId); + } catch (PassphraseCacheService.KeyNotFoundException e) { + throw new PgpDecryptVerify.NoSecretKeyException(); + } + } + }, + inputData, null ); builder.setProgressable(this) .setAllowSymmetricDecryption(true) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java index 909f9f9be..e7ac209bf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java @@ -18,7 +18,6 @@ package org.sufficientlysecure.keychain.service.results; import android.os.Parcel; -import android.os.Parcelable; import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpSignatureResult; @@ -34,7 +33,7 @@ public class DecryptVerifyResult extends OperationResultParcel { public static final int RESULT_PENDING_NFC = RESULT_PENDING +48; long mKeyIdPassphraseNeeded; - byte[] mSessionKey; + byte[] mNfcSessionKey; OpenPgpSignatureResult mSignatureResult; OpenPgpMetadata mDecryptMetadata; @@ -48,7 +47,11 @@ public class DecryptVerifyResult extends OperationResultParcel { } public void setNfcEncryptedSessionKey(byte[] sessionKey) { - mSessionKey = sessionKey; + mNfcSessionKey = sessionKey; + } + + public byte[] getNfcEncryptedSessionKey() { + return mNfcSessionKey; } public OpenPgpSignatureResult getSignatureResult() { @@ -80,7 +83,7 @@ public class DecryptVerifyResult extends OperationResultParcel { mKeyIdPassphraseNeeded = source.readLong(); mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader()); mDecryptMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader()); - mSessionKey = source.readInt() != 0 ? source.createByteArray() : null; + mNfcSessionKey = source.readInt() != 0 ? source.createByteArray() : null; } public int describeContents() { @@ -92,9 +95,9 @@ public class DecryptVerifyResult extends OperationResultParcel { dest.writeLong(mKeyIdPassphraseNeeded); dest.writeParcelable(mSignatureResult, 0); dest.writeParcelable(mDecryptMetadata, 0); - if (mSessionKey != null) { + if (mNfcSessionKey != null) { dest.writeInt(1); - dest.writeByteArray(mSessionKey); + dest.writeByteArray(mNfcSessionKey); } else { dest.writeInt(0); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java index ec0f68ced..7d9b2b9b3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java @@ -261,13 +261,18 @@ public class DecryptFileFragment extends DecryptFragment { DecryptVerifyResult result = returnData.getParcelable(KeychainIntentService.RESULT_DECRYPT_VERIFY_RESULT); - switch (result.getResult()) { - case DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE: - showPassphraseDialog(result.getKeyIdPassphraseNeeded()); - return; - case DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE: - showPassphraseDialog(Constants.key.symmetric); - return; + if (result.isPending()) { + switch (result.getResult()) { + case DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE: + showPassphraseDialog(result.getKeyIdPassphraseNeeded()); + return; + case DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE: + showPassphraseDialog(Constants.key.symmetric); + return; + } + // error, we can't work with this! + result.createNotify(getActivity()); + return; } // display signature result in activity diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java index 01ea4b042..75e38d5c6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java @@ -146,13 +146,18 @@ public class DecryptMessageFragment extends DecryptFragment { DecryptVerifyResult result = returnData.getParcelable(KeychainIntentService.RESULT_DECRYPT_VERIFY_RESULT); - switch (result.getResult()) { - case DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE: - showPassphraseDialog(result.getKeyIdPassphraseNeeded()); - return; - case DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE: - showPassphraseDialog(Constants.key.symmetric); - return; + if (result.isPending()) { + switch (result.getResult()) { + case DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE: + showPassphraseDialog(result.getKeyIdPassphraseNeeded()); + return; + case DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE: + showPassphraseDialog(Constants.key.symmetric); + return; + } + // error, we can't work with this! + result.createNotify(getActivity()); + return; } byte[] decryptedMessage = returnData @@ -160,6 +165,8 @@ public class DecryptMessageFragment extends DecryptFragment { mMessage.setText(new String(decryptedMessage)); mMessage.setHorizontallyScrolling(false); + result.createNotify(getActivity()); + // display signature result in activity onResult(result); } |