add override button to security problem dialog

This commit is contained in:
Vincent Breitmoser
2017-04-28 22:46:08 +02:00
parent 78c3e17d0a
commit 10112eeea8
8 changed files with 282 additions and 40 deletions

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}
});
}
}

View File

@@ -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();
}
}