diff options
Diffstat (limited to 'OpenKeychain/src/main/java')
5 files changed, 127 insertions, 19 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java index a8d1f0313..e4026eaaf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java @@ -21,6 +21,7 @@ import android.content.Context; import android.os.Parcelable; import android.support.annotation.NonNull; +import org.sufficientlysecure.keychain.Constants.key; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface; import org.sufficientlysecure.keychain.pgp.Progressable; @@ -111,8 +112,11 @@ public abstract class BaseOperation <T extends Parcelable> implements Passphrase @Override public Passphrase getCachedPassphrase(long subKeyId) throws NoSecretKeyException { try { - long masterKeyId = mProviderHelper.getMasterKeyId(subKeyId); - return getCachedPassphrase(masterKeyId, subKeyId); + if (subKeyId != key.symmetric) { + long masterKeyId = mProviderHelper.getMasterKeyId(subKeyId); + return getCachedPassphrase(masterKeyId, subKeyId); + } + return getCachedPassphrase(key.symmetric, key.symmetric); } catch (NotFoundException e) { throw new PassphraseCacheInterface.NoSecretKeyException(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index 9da3b94af..88d04350c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -605,6 +605,7 @@ public abstract class OperationResult implements Parcelable { MSG_DC_CLEAR_SIGNATURE_OK (LogLevel.OK, R.string.msg_dc_clear_signature_ok), MSG_DC_CLEAR_SIGNATURE (LogLevel.DEBUG, R.string.msg_dc_clear_signature), MSG_DC_ERROR_BAD_PASSPHRASE (LogLevel.ERROR, R.string.msg_dc_error_bad_passphrase), + MSG_DC_ERROR_SYM_PASSPHRASE (LogLevel.ERROR, R.string.msg_dc_error_sym_passphrase), MSG_DC_ERROR_CORRUPT_DATA (LogLevel.ERROR, R.string.msg_dc_error_corrupt_data), MSG_DC_ERROR_EXTRACT_KEY (LogLevel.ERROR, R.string.msg_dc_error_extract_key), MSG_DC_ERROR_INTEGRITY_CHECK (LogLevel.ERROR, R.string.msg_dc_error_integrity_check), 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 953150b72..7b61968a3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -26,6 +26,7 @@ import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpSignatureResult; import org.spongycastle.bcpg.ArmoredInputStream; import org.spongycastle.openpgp.PGPCompressedData; +import org.spongycastle.openpgp.PGPDataValidationException; import org.spongycastle.openpgp.PGPEncryptedData; import org.spongycastle.openpgp.PGPEncryptedDataList; import org.spongycastle.openpgp.PGPException; @@ -47,6 +48,7 @@ import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBu import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder; import org.spongycastle.util.encoders.DecoderException; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.Constants.key; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.BaseOperation; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; @@ -485,12 +487,23 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> // if no passphrase is given, return here // indicating that a passphrase is missing! if (!cryptoInput.hasPassphrase()) { - log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1); - return new DecryptVerifyResult(log, - RequiredInputParcel.createRequiredSymmetricPassphrase()); - } - passphrase = cryptoInput.getPassphrase(); + try { + passphrase = getCachedPassphrase(key.symmetric); + log.add(LogType.MSG_DC_PASS_CACHED, indent + 1); + } catch (PassphraseCacheInterface.NoSecretKeyException e) { + // nvm + } + + if (passphrase == null) { + log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1); + return new DecryptVerifyResult(log, + RequiredInputParcel.createRequiredSymmetricPassphrase()); + } + + } else { + passphrase = cryptoInput.getPassphrase(); + } // break out of while, only decrypt the first packet break; @@ -526,7 +539,14 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( passphrase.getCharArray()); - clear = encryptedDataSymmetric.getDataStream(decryptorFactory); + try { + clear = encryptedDataSymmetric.getDataStream(decryptorFactory); + } catch (PGPDataValidationException e) { + log.add(LogType.MSG_DC_ERROR_SYM_PASSPHRASE, indent +1); + return new DecryptVerifyResult(log, + RequiredInputParcel.createRequiredSymmetricPassphrase()); + } + encryptedData = encryptedDataSymmetric; symmetricEncryptionAlgo = encryptedDataSymmetric.getSymmetricAlgorithm(decryptorFactory); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index 7c0b7eaef..2a258b7e3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -232,21 +232,21 @@ public class PassphraseCacheService extends Service { * Internal implementation to get cached passphrase. */ private Passphrase getCachedPassphraseImpl(long masterKeyId, long subKeyId) throws ProviderHelper.NotFoundException { + // on "none" key, just do nothing + if (masterKeyId == Constants.key.none) { + return null; + } + // passphrase for symmetric encryption? if (masterKeyId == Constants.key.symmetric) { Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphraseImpl() for symmetric encryption"); - Passphrase cachedPassphrase = mPassphraseCache.get(Constants.key.symmetric).getPassphrase(); + CachedPassphrase cachedPassphrase = mPassphraseCache.get(Constants.key.symmetric); if (cachedPassphrase == null) { return null; } addCachedPassphrase(this, Constants.key.symmetric, Constants.key.symmetric, - cachedPassphrase, getString(R.string.passp_cache_notif_pwd)); - return cachedPassphrase; - } - - // on "none" key, just do nothing - if (masterKeyId == Constants.key.none) { - return null; + cachedPassphrase.getPassphrase(), getString(R.string.passp_cache_notif_pwd)); + return cachedPassphrase.getPassphrase(); } // try to get master key id which is used as an identifier for cached passphrases diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java index b38968753..3d0e51a85 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java @@ -85,6 +85,7 @@ public class DecryptListFragment public static final String ARG_INPUT_URIS = "input_uris"; public static final String ARG_OUTPUT_URIS = "output_uris"; + public static final String ARG_CANCELLED_URIS = "cancelled_uris"; public static final String ARG_RESULTS = "results"; private static final int REQUEST_CODE_OUTPUT = 0x00007007; @@ -92,6 +93,7 @@ public class DecryptListFragment private ArrayList<Uri> mInputUris; private HashMap<Uri, Uri> mOutputUris; private ArrayList<Uri> mPendingInputUris; + private ArrayList<Uri> mCancelledInputUris; private Uri mCurrentInputUri; @@ -155,6 +157,7 @@ public class DecryptListFragment outState.putParcelable(ARG_RESULTS, new ParcelableHashMap<>(results)); outState.putParcelable(ARG_OUTPUT_URIS, new ParcelableHashMap<>(mOutputUris)); + outState.putParcelableArrayList(ARG_CANCELLED_URIS, mCancelledInputUris); } @@ -165,25 +168,39 @@ public class DecryptListFragment Bundle args = savedInstanceState != null ? savedInstanceState : getArguments(); ArrayList<Uri> inputUris = getArguments().getParcelableArrayList(ARG_INPUT_URIS); + ArrayList<Uri> cancelledUris = args.getParcelableArrayList(ARG_CANCELLED_URIS); ParcelableHashMap<Uri,Uri> outputUris = args.getParcelable(ARG_OUTPUT_URIS); ParcelableHashMap<Uri,DecryptVerifyResult> results = args.getParcelable(ARG_RESULTS); - displayInputUris(inputUris, + displayInputUris(inputUris, cancelledUris, outputUris != null ? outputUris.getMap() : null, results != null ? results.getMap() : null ); } - private void displayInputUris(ArrayList<Uri> inputUris, HashMap<Uri,Uri> outputUris, + private void displayInputUris(ArrayList<Uri> inputUris, ArrayList<Uri> cancelledUris, + HashMap<Uri,Uri> outputUris, HashMap<Uri,DecryptVerifyResult> results) { mInputUris = inputUris; mOutputUris = outputUris != null ? outputUris : new HashMap<Uri,Uri>(inputUris.size()); + mCancelledInputUris = cancelledUris != null ? cancelledUris : new ArrayList<Uri>(); mPendingInputUris = new ArrayList<>(); - for (Uri uri : inputUris) { + for (final Uri uri : inputUris) { mAdapter.add(uri); + + if (mCancelledInputUris.contains(uri)) { + mAdapter.setCancelled(uri, new OnClickListener() { + @Override + public void onClick(View v) { + retryUri(uri); + } + }); + continue; + } + if (results != null && results.containsKey(uri)) { processResult(uri, results.get(uri)); } else { @@ -247,6 +264,7 @@ public class DecryptListFragment mAdapter.setProgress(mCurrentInputUri, progress, max, msg); return true; } + @Override public void onQueuedOperationError(DecryptVerifyResult result) { final Uri uri = mCurrentInputUri; @@ -267,6 +285,25 @@ public class DecryptListFragment cryptoOperation(); } + @Override + public void onCryptoOperationCancelled() { + super.onCryptoOperationCancelled(); + + final Uri uri = mCurrentInputUri; + mCurrentInputUri = null; + + mCancelledInputUris.add(uri); + mAdapter.setCancelled(uri, new OnClickListener() { + @Override + public void onClick(View v) { + retryUri(uri); + } + }); + + cryptoOperation(); + + } + private void processResult(final Uri uri, final DecryptVerifyResult result) { new AsyncTask<Void, Void, Drawable>() { @@ -350,6 +387,22 @@ public class DecryptListFragment } + public void retryUri(Uri uri) { + + // never interrupt running operations! + if (mCurrentInputUri != null) { + return; + } + + // un-cancel this one + mCancelledInputUris.remove(uri); + mPendingInputUris.add(uri); + mAdapter.setCancelled(uri, null); + + cryptoOperation(); + + } + public void displayWithViewIntent(final Uri uri) { Activity activity = getActivity(); if (activity == null || mCurrentInputUri != null) { @@ -528,12 +581,14 @@ public class DecryptListFragment int mProgress, mMax; String mProgressMsg; + OnClickListener mCancelled; ViewModel(Context context, Uri uri) { mContext = context; mInputUri = uri; mProgress = 0; mMax = 100; + mCancelled = null; } void addResult(DecryptVerifyResult result) { @@ -553,6 +608,10 @@ public class DecryptListFragment return mResult != null; } + void setCancelled(OnClickListener retryListener) { + mCancelled = retryListener; + } + void setProgress(int progress, int max, String msg) { if (msg != null) { mProgressMsg = msg; @@ -610,6 +669,11 @@ public class DecryptListFragment // - replace the contents of the view with that element final ViewModel model = mDataset.get(position); + if (model.mCancelled != null) { + bindItemCancelled(holder, model); + return; + } + if (!model.hasResult()) { bindItemProgress(holder, model); return; @@ -623,6 +687,14 @@ public class DecryptListFragment } + private void bindItemCancelled(ViewHolder holder, ViewModel model) { + if (holder.vAnimator.getDisplayedChild() != 3) { + holder.vAnimator.setDisplayedChild(3); + } + + holder.vCancelledRetry.setOnClickListener(model.mCancelled); + } + private void bindItemProgress(ViewHolder holder, ViewModel model) { if (holder.vAnimator.getDisplayedChild() != 0) { holder.vAnimator.setDisplayedChild(0); @@ -738,6 +810,13 @@ public class DecryptListFragment notifyItemChanged(pos); } + public void setCancelled(Uri uri, OnClickListener retryListener) { + ViewModel newModel = new ViewModel(mContext, uri); + int pos = mDataset.indexOf(newModel); + mDataset.get(pos).setCancelled(retryListener); + notifyItemChanged(pos); + } + public void addResult(Uri uri, DecryptVerifyResult result, Drawable icon, OnClickListener onFileClick, OnClickListener onKeyClick) { @@ -785,6 +864,8 @@ public class DecryptListFragment public TextView vErrorMsg; public ImageView vErrorViewLog; + public ImageView vCancelledRetry; + public ViewHolder(View itemView) { super(itemView); @@ -813,6 +894,8 @@ public class DecryptListFragment vErrorMsg = (TextView) itemView.findViewById(R.id.result_error_msg); vErrorViewLog = (ImageView) itemView.findViewById(R.id.result_error_log); + vCancelledRetry = (ImageView) itemView.findViewById(R.id.cancel_retry); + } @Override |