aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java32
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java16
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java89
-rw-r--r--OpenKeychain/src/main/res/layout/decrypt_list_entry.xml32
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml1
7 files changed, 160 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
diff --git a/OpenKeychain/src/main/res/layout/decrypt_list_entry.xml b/OpenKeychain/src/main/res/layout/decrypt_list_entry.xml
index d58542e62..92f366eda 100644
--- a/OpenKeychain/src/main/res/layout/decrypt_list_entry.xml
+++ b/OpenKeychain/src/main/res/layout/decrypt_list_entry.xml
@@ -286,6 +286,38 @@
</LinearLayout>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:orientation="horizontal">
+
+ <TextView
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginLeft="8dp"
+ android:layout_marginStart="8dp"
+ android:layout_gravity="center_vertical"
+ android:drawablePadding="12dp"
+ android:text="@string/msg_cancelled"
+ android:drawableLeft="@drawable/status_signature_invalid_cutout_24dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ />
+
+ <ImageView
+ android:id="@+id/cancel_retry"
+ android:scaleType="center"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:clickable="true"
+ android:padding="6dp"
+ android:background="?android:selectableItemBackground"
+ android:src="@drawable/ic_repeat_grey_24dp"
+ android:layout_gravity="center_vertical" />
+
+ </LinearLayout>
+
</org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator>
</android.support.v7.widget.CardView> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index a6052dffe..9135c24c5 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -1103,6 +1103,7 @@
<string name="msg_dc_clear_signature">"Saving signature data for later"</string>
<string name="msg_dc_clear">"Processing cleartext data"</string>
<string name="msg_dc_error_bad_passphrase">"Error unlocking key, bad password!"</string>
+ <string name="msg_dc_error_sym_passphrase">"Error decrypting data! (Bad passphrase?)"</string>
<string name="msg_dc_error_corrupt_data">"Data is corrupt!"</string>
<string name="msg_dc_error_extract_key">"Unknown error unlocking key!"</string>
<string name="msg_dc_error_integrity_check">"Integrity check error!"</string>