From 57378be1c07893e2231e485d6289d53d522aa7d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 25 Jul 2015 14:32:47 +0200 Subject: Introduce constants in OpenPgpSignature and DecryptionResult for unsigned/unencrypted content, update API, introduce simple checks for insecure symmetric algos --- .../keychain/ui/DecryptFragment.java | 72 +++++++++----- .../keychain/ui/DecryptListFragment.java | 14 +-- .../keychain/ui/EncryptFilesFragment.java | 12 ++- .../keychain/ui/EncryptTextFragment.java | 10 +- .../keychain/ui/util/KeyFormattingUtils.java | 106 +++++++++++++++------ 5 files changed, 148 insertions(+), 66 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java index aaf337f42..37dd6afad 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -36,6 +36,7 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.ViewAnimator; +import org.openintents.openpgp.OpenPgpDecryptionResult; import org.openintents.openpgp.OpenPgpSignatureResult; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -208,37 +209,50 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager. mDecryptVerifyResult = decryptVerifyResult; mSignatureResult = decryptVerifyResult.getSignatureResult(); + OpenPgpDecryptionResult decryptionResult = decryptVerifyResult.getDecryptionResult(); mResultLayout.setVisibility(View.VISIBLE); - // unsigned data - if (mSignatureResult == null) { + switch (decryptionResult.getResult()) { + case OpenPgpDecryptionResult.RESULT_ENCRYPTED: { + mEncryptionText.setText(R.string.decrypt_result_encrypted); + KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED); + break; + } + + case OpenPgpDecryptionResult.RESULT_INSECURE: { + mEncryptionText.setText(R.string.decrypt_result_insecure); + KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.INSECURE); + break; + } + + default: + case OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED: { + mEncryptionText.setText(R.string.decrypt_result_not_encrypted); + KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.NOT_ENCRYPTED); + break; + } + } + + if (mSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_NO_SIGNATURE) { + // no signature setSignatureLayoutVisibility(View.GONE); mSignatureText.setText(R.string.decrypt_result_no_signature); KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.NOT_SIGNED); - mEncryptionText.setText(R.string.decrypt_result_encrypted); - KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED); getLoaderManager().destroyLoader(LOADER_ID_UNIFIED); showErrorOverlay(false); onVerifyLoaded(true); - - return; - } - - if (mSignatureResult.isSignatureOnly()) { - mEncryptionText.setText(R.string.decrypt_result_not_encrypted); - KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.NOT_ENCRYPTED); } else { - mEncryptionText.setText(R.string.decrypt_result_encrypted); - KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED); - } + // signature present - getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, this); + // after loader is restarted signature results are checked + getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, this); + } } private void setSignatureLayoutVisibility(int visibility) { @@ -313,8 +327,9 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager. // NOTE: Don't use revoked and expired fields from database, they don't show // revoked/expired subkeys - boolean isRevoked = mSignatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED; - boolean isExpired = mSignatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED; + boolean isRevoked = mSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_KEY_REVOKED; + boolean isExpired = mSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_KEY_EXPIRED; + boolean isInsecure = mSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_INSECURE; boolean isVerified = data.getInt(INDEX_VERIFIED) > 0; boolean isYours = data.getInt(INDEX_HAS_ANY_SECRET) != 0; @@ -338,6 +353,17 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager. onVerifyLoaded(true); + } else if (isInsecure) { + mSignatureText.setText(R.string.decrypt_result_insecure_cryptography); + KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.INSECURE); + + setSignatureLayoutVisibility(View.VISIBLE); + setShowAction(signatureKeyId); + + showErrorOverlay(false); + + onVerifyLoaded(true); + } else if (isYours) { mSignatureText.setText(R.string.decrypt_result_signature_secret); @@ -389,9 +415,9 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager. final long signatureKeyId = mSignatureResult.getKeyId(); - int result = mSignatureResult.getStatus(); - if (result != OpenPgpSignatureResult.SIGNATURE_KEY_MISSING - && result != OpenPgpSignatureResult.SIGNATURE_ERROR) { + int result = mSignatureResult.getResult(); + if (result != OpenPgpSignatureResult.RESULT_KEY_MISSING + && result != OpenPgpSignatureResult.RESULT_INVALID_SIGNATURE) { Log.e(Constants.TAG, "got missing status for non-missing key, shouldn't happen!"); } @@ -409,9 +435,9 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager. getActivity(), mSignatureResult.getKeyId())); } - switch (mSignatureResult.getStatus()) { + switch (mSignatureResult.getResult()) { - case OpenPgpSignatureResult.SIGNATURE_KEY_MISSING: { + case OpenPgpSignatureResult.RESULT_KEY_MISSING: { mSignatureText.setText(R.string.decrypt_result_signature_missing_key); KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNKNOWN_KEY); @@ -433,7 +459,7 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager. break; } - case OpenPgpSignatureResult.SIGNATURE_ERROR: { + case OpenPgpSignatureResult.RESULT_INVALID_SIGNATURE: { mSignatureText.setText(R.string.decrypt_result_invalid_signature); KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.INVALID); 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 567589821..f57d2d056 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java @@ -321,11 +321,11 @@ public class DecryptListFragment protected Drawable doInBackground(Void... params) { Context context = getActivity(); - if (result.getDecryptMetadata() == null || context == null) { + if (result.getDecryptionMetadata() == null || context == null) { return null; } - String type = result.getDecryptMetadata().getMimeType(); + String type = result.getDecryptionMetadata().getMimeType(); Uri outputUri = mOutputUris.get(uri); if (type == null || outputUri == null) { return null; @@ -368,7 +368,7 @@ public class DecryptListFragment OpenPgpSignatureResult sigResult = result.getSignatureResult(); if (sigResult != null) { final long keyId = sigResult.getKeyId(); - if (sigResult.getStatus() != OpenPgpSignatureResult.SIGNATURE_KEY_MISSING) { + if (sigResult.getResult() != OpenPgpSignatureResult.RESULT_KEY_MISSING) { onKeyClick = new OnClickListener() { @Override public void onClick(View view) { @@ -384,7 +384,7 @@ public class DecryptListFragment } } - if (result.success() && result.getDecryptMetadata() != null) { + if (result.success() && result.getDecryptionMetadata() != null) { onFileClick = new OnClickListener() { @Override public void onClick(View view) { @@ -425,7 +425,7 @@ public class DecryptListFragment return; } - final OpenPgpMetadata metadata = result.getDecryptMetadata(); + final OpenPgpMetadata metadata = result.getDecryptionMetadata(); // text/plain is a special case where we extract the uri content into // the EXTRA_TEXT extra ourselves, and display a chooser which includes @@ -529,7 +529,7 @@ public class DecryptListFragment activity.startActivity(intent); return true; case R.id.decrypt_save: - OpenPgpMetadata metadata = result.getDecryptMetadata(); + OpenPgpMetadata metadata = result.getDecryptionMetadata(); if (metadata == null) { return true; } @@ -724,7 +724,7 @@ public class DecryptListFragment KeyFormattingUtils.setStatus(mContext, holder, model.mResult); - final OpenPgpMetadata metadata = model.mResult.getDecryptMetadata(); + final OpenPgpMetadata metadata = model.mResult.getDecryptionMetadata(); String filename; if (metadata == null) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java index 3dc93872d..7bf662da3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java @@ -553,14 +553,18 @@ public class EncryptFilesFragment data.addInputUris(mFilesAdapter.getAsArrayList()); if (mUseCompression) { - data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.get(0)); + data.setCompressionAlgorithm( + PgpConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT); } else { - data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED); + data.setCompressionAlgorithm( + PgpConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED); } data.setHiddenRecipients(mHiddenRecipients); data.setEnableAsciiArmorOutput(mAfterEncryptAction == AfterEncryptAction.COPY || mUseArmor); - data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); - data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); + data.setSymmetricEncryptionAlgorithm( + PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT); + data.setSignatureHashAlgorithm( + PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT); EncryptActivity encryptActivity = (EncryptActivity) getActivity(); EncryptModeFragment modeFragment = encryptActivity.getModeFragment(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java index 32257eba5..60a2c9905 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java @@ -223,15 +223,17 @@ public class EncryptTextFragment data.setCleartextSignature(true); if (mUseCompression) { - data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.get(0)); + data.setCompressionAlgorithm( + PgpConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT); } else { - data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED); + data.setCompressionAlgorithm( + PgpConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED); } data.setHiddenRecipients(mHiddenRecipients); data.setSymmetricEncryptionAlgorithm( - PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); + PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT); data.setSignatureHashAlgorithm( - PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); + PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT); // Always use armor for messages data.setEnableAsciiArmorOutput(true); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java index 224e0085b..9984c245e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java @@ -28,6 +28,7 @@ import android.view.View; import android.widget.ImageView; import android.widget.TextView; +import org.openintents.openpgp.OpenPgpDecryptionResult; import org.openintents.openpgp.OpenPgpSignatureResult; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.nist.NISTNamedCurves; @@ -40,7 +41,6 @@ import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve; -import org.sufficientlysecure.keychain.ui.util.FormattingUtils; import org.sufficientlysecure.keychain.util.Log; import java.nio.ByteBuffer; @@ -408,7 +408,8 @@ public class KeyFormattingUtils { UNVERIFIED, UNKNOWN_KEY, INVALID, - NOT_SIGNED + NOT_SIGNED, + INSECURE } public static void setStatusImage(Context context, ImageView statusIcon, State state) { @@ -443,18 +444,33 @@ public class KeyFormattingUtils { @SuppressWarnings("deprecation") // context.getDrawable is api lvl 21, need to use deprecated public static void setStatus(Context context, StatusHolder holder, DecryptVerifyResult result) { - OpenPgpSignatureResult signatureResult = result.getSignatureResult(); - if (holder.hasEncrypt()) { + OpenPgpDecryptionResult decryptionResult = result.getDecryptionResult(); + int encText, encIcon, encColor; - if (signatureResult != null && signatureResult.isSignatureOnly()) { - encIcon = R.drawable.status_lock_open_24dp; - encText = R.string.decrypt_result_not_encrypted; - encColor = R.color.key_flag_red; - } else { - encIcon = R.drawable.status_lock_closed_24dp; - encText = R.string.decrypt_result_encrypted; - encColor = R.color.key_flag_green; + + switch (decryptionResult.getResult()) { + case OpenPgpDecryptionResult.RESULT_ENCRYPTED: { + encText = R.string.decrypt_result_encrypted; + encIcon = R.drawable.status_lock_closed_24dp; + encColor = R.color.key_flag_green; + break; + } + + case OpenPgpDecryptionResult.RESULT_INSECURE: { + encText = R.string.decrypt_result_insecure; + encIcon = R.drawable.status_signature_invalid_cutout_24dp; + encColor = R.color.key_flag_red; + break; + } + + default: + case OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED: { + encText = R.string.decrypt_result_not_encrypted; + encIcon = R.drawable.status_lock_open_24dp; + encColor = R.color.key_flag_red; + break; + } } int encColorRes = context.getResources().getColor(encColor); @@ -464,22 +480,27 @@ public class KeyFormattingUtils { holder.getEncryptionStatusText().setTextColor(encColorRes); } + OpenPgpSignatureResult signatureResult = result.getSignatureResult(); + int sigText, sigIcon, sigColor; int sigActionText, sigActionIcon; - if (signatureResult == null) { + switch (signatureResult.getResult()) { - sigText = R.string.decrypt_result_no_signature; - sigIcon = R.drawable.status_signature_invalid_cutout_24dp; - sigColor = R.color.key_flag_gray; + case OpenPgpSignatureResult.RESULT_NO_SIGNATURE: { + // no signature - // won't be used, but makes compiler happy - sigActionText = 0; - sigActionIcon = 0; + sigText = R.string.decrypt_result_no_signature; + sigIcon = R.drawable.status_signature_invalid_cutout_24dp; + sigColor = R.color.key_flag_gray; - } else switch (signatureResult.getStatus()) { + // won't be used, but makes compiler happy + sigActionText = 0; + sigActionIcon = 0; + break; + } - case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: { + case OpenPgpSignatureResult.RESULT_VALID_CONFIRMED: { sigText = R.string.decrypt_result_signature_certified; sigIcon = R.drawable.status_signature_verified_cutout_24dp; sigColor = R.color.key_flag_green; @@ -489,7 +510,7 @@ public class KeyFormattingUtils { break; } - case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: { + case OpenPgpSignatureResult.RESULT_VALID_UNCONFIRMED: { sigText = R.string.decrypt_result_signature_uncertified; sigIcon = R.drawable.status_signature_unverified_cutout_24dp; sigColor = R.color.key_flag_orange; @@ -499,7 +520,7 @@ public class KeyFormattingUtils { break; } - case OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED: { + case OpenPgpSignatureResult.RESULT_INVALID_KEY_REVOKED: { sigText = R.string.decrypt_result_signature_revoked_key; sigIcon = R.drawable.status_signature_revoked_cutout_24dp; sigColor = R.color.key_flag_red; @@ -509,7 +530,7 @@ public class KeyFormattingUtils { break; } - case OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED: { + case OpenPgpSignatureResult.RESULT_INVALID_KEY_EXPIRED: { sigText = R.string.decrypt_result_signature_expired_key; sigIcon = R.drawable.status_signature_expired_cutout_24dp; sigColor = R.color.key_flag_red; @@ -519,7 +540,7 @@ public class KeyFormattingUtils { break; } - case OpenPgpSignatureResult.SIGNATURE_KEY_MISSING: { + case OpenPgpSignatureResult.RESULT_KEY_MISSING: { sigText = R.string.decrypt_result_signature_missing_key; sigIcon = R.drawable.status_signature_unknown_cutout_24dp; sigColor = R.color.key_flag_red; @@ -529,8 +550,18 @@ public class KeyFormattingUtils { break; } + case OpenPgpSignatureResult.RESULT_INVALID_INSECURE: { + sigText = R.string.decrypt_result_insecure_cryptography; + sigIcon = R.drawable.status_signature_invalid_cutout_24dp; + sigColor = R.color.key_flag_red; + + sigActionText = R.string.decrypt_result_action_show; + sigActionIcon = R.drawable.ic_vpn_key_grey_24dp; + break; + } + default: - case OpenPgpSignatureResult.SIGNATURE_ERROR: { + case OpenPgpSignatureResult.RESULT_INVALID_SIGNATURE: { sigText = R.string.decrypt_result_invalid_signature; sigIcon = R.drawable.status_signature_invalid_cutout_24dp; sigColor = R.color.key_flag_red; @@ -548,7 +579,8 @@ public class KeyFormattingUtils { holder.getSignatureStatusText().setText(sigText); holder.getSignatureStatusText().setTextColor(sigColorRes); - if (signatureResult != null) { + if (signatureResult.getResult() != OpenPgpSignatureResult.RESULT_NO_SIGNATURE) { + // has a signature, thus display layouts holder.getSignatureLayout().setVisibility(View.VISIBLE); @@ -556,7 +588,7 @@ public class KeyFormattingUtils { holder.getSignatureAction().setCompoundDrawablesWithIntrinsicBounds( 0, 0, sigActionIcon, 0); - String userId = signatureResult.getPrimaryUserId(); + String userId = result.getSignatureResult().getPrimaryUserId(); KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId); if (userIdSplit.name != null) { holder.getSignatureUserName().setText(userIdSplit.name); @@ -687,6 +719,24 @@ public class KeyFormattingUtils { } break; } + case INSECURE: { + if (big) { + statusIcon.setImageDrawable( + context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout_96dp)); + } else { + statusIcon.setImageDrawable( + context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout_24dp)); + } + if (color == KeyFormattingUtils.DEFAULT_COLOR) { + color = R.color.key_flag_red; + } + statusIcon.setColorFilter(context.getResources().getColor(color), + PorterDuff.Mode.SRC_IN); + if (statusText != null) { + statusText.setTextColor(context.getResources().getColor(color)); + } + break; + } case NOT_ENCRYPTED: { statusIcon.setImageDrawable( context.getResources().getDrawable(R.drawable.status_lock_open_24dp)); -- cgit v1.2.3