add override button to security problem dialog
This commit is contained in:
@@ -331,7 +331,8 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
||||
|
||||
// Check for insecure encryption algorithms!
|
||||
EncryptionAlgorithmProblem symmetricSecurityProblem =
|
||||
PgpSecurityConstants.checkSecureSymmetricAlgorithm(esResult.symmetricEncryptionAlgo);
|
||||
PgpSecurityConstants.checkSecureSymmetricAlgorithm(
|
||||
esResult.symmetricEncryptionAlgo, esResult.sessionKey);
|
||||
if (symmetricSecurityProblem != null) {
|
||||
log.add(LogType.MSG_DC_INSECURE_SYMMETRIC_ENCRYPTION_ALGO, indent + 1);
|
||||
securityProblemBuilder.addSymmetricSecurityProblem(symmetricSecurityProblem);
|
||||
@@ -542,7 +543,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
||||
// Handle missing integrity protection like failed integrity protection!
|
||||
// The MDC packet can be stripped by an attacker!
|
||||
log.add(LogType.MSG_DC_INSECURE_MDC_MISSING, indent);
|
||||
securityProblemBuilder.addSymmetricSecurityProblem(new MissingMdc());
|
||||
securityProblemBuilder.addSymmetricSecurityProblem(new MissingMdc(esResult.sessionKey));
|
||||
decryptionResultBuilder.setInsecure(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,9 +74,9 @@ public class PgpSecurityConstants {
|
||||
// CAMELLIA_256: not used widely
|
||||
));
|
||||
|
||||
public static EncryptionAlgorithmProblem checkSecureSymmetricAlgorithm(int id) {
|
||||
public static EncryptionAlgorithmProblem checkSecureSymmetricAlgorithm(int id, byte[] sessionKey) {
|
||||
if (!sSymmetricAlgorithmsWhitelist.contains(id)) {
|
||||
return new InsecureEncryptionAlgorithm(id);
|
||||
return new InsecureEncryptionAlgorithm(sessionKey, id);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -18,10 +18,40 @@
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
|
||||
|
||||
public abstract class SecurityProblem implements Serializable {
|
||||
|
||||
String getIdentifier() {
|
||||
if (!isIdentifiable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(out);
|
||||
oos.writeObject(this);
|
||||
oos.close();
|
||||
|
||||
byte[] digest = MessageDigest.getInstance("SHA1").digest(out.toByteArray());
|
||||
return Base64.toBase64String(digest);
|
||||
} catch (NoSuchAlgorithmException | IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isIdentifiable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static abstract class KeySecurityProblem extends SecurityProblem {
|
||||
public final long masterKeyId;
|
||||
public final long subKeyId;
|
||||
@@ -32,10 +62,25 @@ public abstract class SecurityProblem implements Serializable {
|
||||
this.subKeyId = subKeyId;
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentifiable() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class EncryptionAlgorithmProblem extends SecurityProblem {
|
||||
@SuppressWarnings("unused") // used for identifying this specific problem
|
||||
private final byte[] sessionKey;
|
||||
|
||||
private EncryptionAlgorithmProblem(byte[] sessionKey) {
|
||||
this.sessionKey = sessionKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentifiable() {
|
||||
return sessionKey != null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class InsecureBitStrength extends KeySecurityProblem {
|
||||
@@ -73,12 +118,16 @@ public abstract class SecurityProblem implements Serializable {
|
||||
public static class InsecureEncryptionAlgorithm extends EncryptionAlgorithmProblem {
|
||||
public final int symmetricAlgorithm;
|
||||
|
||||
InsecureEncryptionAlgorithm(int symmetricAlgorithm) {
|
||||
InsecureEncryptionAlgorithm(byte[] sessionKey, int symmetricAlgorithm) {
|
||||
super(sessionKey);
|
||||
this.symmetricAlgorithm = symmetricAlgorithm;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MissingMdc extends EncryptionAlgorithmProblem {
|
||||
|
||||
MissingMdc(byte[] sessionKey) {
|
||||
super(sessionKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,12 +39,14 @@ import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ViewAnimator;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.remote.ui.SecurityProblemPresenter.RemoteSecurityProblemView;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.ThemeChanger;
|
||||
import org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator;
|
||||
|
||||
|
||||
public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
|
||||
@@ -79,11 +81,17 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
|
||||
}
|
||||
|
||||
public static class RemoteRegisterDialogFragment extends DialogFragment {
|
||||
public static final int SECONDARY_CHILD_NONE = 0;
|
||||
public static final int SECONDARY_CHILD_RECOMMENDATION = 1;
|
||||
public static final int SECONDARY_CHILD_OVERRIDE = 2;
|
||||
public static final int SECONDARY_CHILD_OVERRIDE_OK = 3;
|
||||
private SecurityProblemPresenter presenter;
|
||||
private RemoteSecurityProblemView mvpView;
|
||||
|
||||
private Button buttonGotIt;
|
||||
private Button buttonViewKey;
|
||||
private Button buttonOverride;
|
||||
private Button buttonOverrideUndo;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
@@ -99,6 +107,8 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
|
||||
|
||||
buttonGotIt = (Button) view.findViewById(R.id.button_allow);
|
||||
buttonViewKey = (Button) view.findViewById(R.id.button_view_key);
|
||||
buttonOverride = (Button) view.findViewById(R.id.button_override);
|
||||
buttonOverrideUndo = (Button) view.findViewById(R.id.button_override_undo);
|
||||
|
||||
setupListenersForPresenter();
|
||||
mvpView = createMvpView(view);
|
||||
@@ -139,9 +149,13 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
|
||||
final ImageView iconClientApp = (ImageView) view.findViewById(R.id.icon_client_app);
|
||||
final TextView explanationText = (TextView) insecureWarningLayout.findViewById(R.id.dialog_insecure_text);
|
||||
final TextView recommendText = (TextView) insecureWarningLayout.findViewById(R.id.dialog_insecure_recommend_text);
|
||||
final View recommendLayout = insecureWarningLayout.findViewById(R.id.dialog_insecure_recommend_layout);
|
||||
final TextView overrideText = (TextView) insecureWarningLayout.findViewById(R.id.dialog_insecure_override_text);
|
||||
final ToolableViewAnimator secondaryLayoutAnimator =
|
||||
(ToolableViewAnimator) insecureWarningLayout.findViewById(R.id.dialog_insecure_secondary_layout);
|
||||
|
||||
return new RemoteSecurityProblemView() {
|
||||
private boolean layoutInitialized = false;
|
||||
|
||||
@Override
|
||||
public void finishAsCancelled() {
|
||||
FragmentActivity activity = getActivity();
|
||||
@@ -167,26 +181,30 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
|
||||
|
||||
private void showGeneric(@StringRes int explanationStringRes) {
|
||||
explanationText.setText(explanationStringRes);
|
||||
recommendLayout.setVisibility(View.GONE);
|
||||
secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_NONE, layoutInitialized);
|
||||
layoutInitialized = true;
|
||||
}
|
||||
|
||||
private void showGeneric(String explanationString) {
|
||||
explanationText.setText(explanationString);
|
||||
recommendLayout.setVisibility(View.GONE);
|
||||
secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_NONE, layoutInitialized);
|
||||
layoutInitialized = true;
|
||||
}
|
||||
|
||||
private void showGenericWithRecommendation(
|
||||
@StringRes int explanationStringRes, @StringRes int recommendationStringRes) {
|
||||
explanationText.setText(explanationStringRes);
|
||||
recommendText.setText(recommendationStringRes);
|
||||
recommendLayout.setVisibility(View.VISIBLE);
|
||||
secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_RECOMMENDATION, layoutInitialized);
|
||||
layoutInitialized = true;
|
||||
}
|
||||
|
||||
private void showGenericWithRecommendation(
|
||||
String explanationString, @StringRes int recommendationStringRes) {
|
||||
explanationText.setText(explanationString);
|
||||
recommendText.setText(recommendationStringRes);
|
||||
recommendLayout.setVisibility(View.VISIBLE);
|
||||
secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_RECOMMENDATION, layoutInitialized);
|
||||
layoutInitialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -246,10 +264,33 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
|
||||
showGeneric(R.string.insecure_sign_unidentified);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showOverrideMessage(int countdown) {
|
||||
secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_OVERRIDE, true);
|
||||
overrideText.setText(getString(R.string.dialog_insecure_override, countdown));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showOverrideOk() {
|
||||
secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_OVERRIDE_OK, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showViewKeyButton() {
|
||||
buttonViewKey.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showOverrideButton() {
|
||||
buttonOverride.setVisibility(View.VISIBLE);
|
||||
buttonOverrideUndo.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showOverrideUndoButton() {
|
||||
buttonOverride.setVisibility(View.GONE);
|
||||
buttonOverrideUndo.setVisibility(View.VISIBLE);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -266,6 +307,18 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
|
||||
presenter.onClickViewKey();
|
||||
}
|
||||
});
|
||||
buttonOverride.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
presenter.onClickOverride();
|
||||
}
|
||||
});
|
||||
buttonOverrideUndo.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
presenter.onClickOverrideUndo();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,12 +24,18 @@ import org.sufficientlysecure.keychain.ui.ViewKeyActivity;
|
||||
|
||||
|
||||
class SecurityProblemPresenter {
|
||||
private static final int OVERRIDE_REQUIRED_COUNT = 3;
|
||||
|
||||
|
||||
private final Context context;
|
||||
private final PackageManager packageManager;
|
||||
|
||||
|
||||
private RemoteSecurityProblemView view;
|
||||
private Long viewKeyMasterKeyId;
|
||||
private int overrideCounter;
|
||||
private String packageName;
|
||||
private Serializable securityProblem;
|
||||
|
||||
|
||||
SecurityProblemPresenter(Context context) {
|
||||
@@ -42,17 +48,19 @@ class SecurityProblemPresenter {
|
||||
}
|
||||
|
||||
void setupFromIntentData(String packageName, Serializable securityProblem) {
|
||||
this.packageName = packageName;
|
||||
this.securityProblem = securityProblem;
|
||||
|
||||
refreshSecurityProblemDisplay();
|
||||
refreshPackageInfo();
|
||||
}
|
||||
|
||||
private void refreshSecurityProblemDisplay() {
|
||||
if (securityProblem instanceof DecryptVerifySecurityProblem) {
|
||||
setupFromDecryptVerifySecurityProblem((DecryptVerifySecurityProblem) securityProblem);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unhandled security problem type!");
|
||||
}
|
||||
|
||||
try {
|
||||
setPackageInfo(packageName);
|
||||
} catch (NameNotFoundException e) {
|
||||
throw new IllegalStateException("Unable to find info of calling app!", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupFromDecryptVerifySecurityProblem(DecryptVerifySecurityProblem securityProblem) {
|
||||
@@ -71,6 +79,10 @@ class SecurityProblemPresenter {
|
||||
viewKeyMasterKeyId = keySecurityProblem.masterKeyId;
|
||||
view.showViewKeyButton();
|
||||
|
||||
if (keySecurityProblem.isIdentifiable()) {
|
||||
view.showOverrideButton();
|
||||
}
|
||||
|
||||
if (keySecurityProblem instanceof InsecureBitStrength) {
|
||||
InsecureBitStrength problem = (InsecureBitStrength) keySecurityProblem;
|
||||
view.showLayoutEncryptInsecureBitsize(problem.algorithm, problem.bitStrength);
|
||||
@@ -116,14 +128,30 @@ class SecurityProblemPresenter {
|
||||
view.showLayoutInsecureHashAlgorithm(signatureSecurityProblem.hashAlgorithm);
|
||||
}
|
||||
|
||||
private void setPackageInfo(String packageName) throws NameNotFoundException {
|
||||
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, 0);
|
||||
private void refreshPackageInfo() {
|
||||
ApplicationInfo applicationInfo;
|
||||
try {
|
||||
applicationInfo = packageManager.getApplicationInfo(packageName, 0);
|
||||
} catch (NameNotFoundException e) {
|
||||
throw new IllegalStateException("Could not retrieve package info!");
|
||||
}
|
||||
Drawable appIcon = packageManager.getApplicationIcon(applicationInfo);
|
||||
// CharSequence appName = packageManager.getApplicationLabel(applicationInfo);
|
||||
|
||||
view.setTitleClientIcon(appIcon);
|
||||
}
|
||||
|
||||
private void incrementOverrideAndDisplayOrTrigger() {
|
||||
int overrideCountLeft = OVERRIDE_REQUIRED_COUNT - overrideCounter;
|
||||
if (overrideCountLeft > 0) {
|
||||
overrideCounter++;
|
||||
view.showOverrideMessage(overrideCountLeft);
|
||||
} else {
|
||||
view.showOverrideOk();
|
||||
view.showOverrideUndoButton();
|
||||
}
|
||||
}
|
||||
|
||||
void onClickGotIt() {
|
||||
view.finishAsCancelled();
|
||||
}
|
||||
@@ -134,6 +162,15 @@ class SecurityProblemPresenter {
|
||||
context.startActivity(viewKeyIntent);
|
||||
}
|
||||
|
||||
void onClickOverride() {
|
||||
incrementOverrideAndDisplayOrTrigger();
|
||||
}
|
||||
|
||||
void onClickOverrideUndo() {
|
||||
overrideCounter = 0;
|
||||
refreshSecurityProblemDisplay();
|
||||
}
|
||||
|
||||
void onCancel() {
|
||||
view.finishAsCancelled();
|
||||
}
|
||||
@@ -154,6 +191,11 @@ class SecurityProblemPresenter {
|
||||
|
||||
void showLayoutInsecureHashAlgorithm(int hashAlgorithm);
|
||||
|
||||
void showOverrideMessage(int countdown);
|
||||
void showOverrideOk();
|
||||
|
||||
void showViewKeyButton();
|
||||
void showOverrideButton();
|
||||
void showOverrideUndoButton();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user