change security problem structure

This commit is contained in:
Vincent Breitmoser
2017-04-27 21:48:30 +02:00
parent 10dfcb08fc
commit c1ba764ce8
11 changed files with 150 additions and 124 deletions

View File

@@ -19,16 +19,12 @@
package org.sufficientlysecure.keychain.operations.results; package org.sufficientlysecure.keychain.operations.results;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import android.os.Parcel; import android.os.Parcel;
import org.openintents.openpgp.OpenPgpDecryptionResult; import org.openintents.openpgp.OpenPgpDecryptionResult;
import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpMetadata;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
import org.sufficientlysecure.keychain.pgp.SecurityProblem; import org.sufficientlysecure.keychain.pgp.DecryptVerifySecurityProblem;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
@@ -40,7 +36,7 @@ public class DecryptVerifyResult extends InputPendingResult {
OpenPgpSignatureResult mSignatureResult; OpenPgpSignatureResult mSignatureResult;
OpenPgpDecryptionResult mDecryptionResult; OpenPgpDecryptionResult mDecryptionResult;
OpenPgpMetadata mDecryptionMetadata; OpenPgpMetadata mDecryptionMetadata;
ArrayList<SecurityProblem> mSecurityProblems; DecryptVerifySecurityProblem mSecurityProblem;
CryptoInputParcel mCachedCryptoInputParcel; CryptoInputParcel mCachedCryptoInputParcel;
@@ -73,7 +69,7 @@ public class DecryptVerifyResult extends InputPendingResult {
mCachedCryptoInputParcel = source.readParcelable(CryptoInputParcel.class.getClassLoader()); mCachedCryptoInputParcel = source.readParcelable(CryptoInputParcel.class.getClassLoader());
mSkippedDisallowedKeys = source.createLongArray(); mSkippedDisallowedKeys = source.createLongArray();
mSecurityProblems = (ArrayList<SecurityProblem>) source.readSerializable(); mSecurityProblem = (DecryptVerifySecurityProblem) source.readSerializable();
} }
@@ -137,7 +133,7 @@ public class DecryptVerifyResult extends InputPendingResult {
dest.writeParcelable(mCachedCryptoInputParcel, flags); dest.writeParcelable(mCachedCryptoInputParcel, flags);
dest.writeLongArray(mSkippedDisallowedKeys); dest.writeLongArray(mSkippedDisallowedKeys);
dest.writeSerializable(mSecurityProblems); dest.writeSerializable(mSecurityProblem);
} }
public static final Creator<DecryptVerifyResult> CREATOR = new Creator<DecryptVerifyResult>() { public static final Creator<DecryptVerifyResult> CREATOR = new Creator<DecryptVerifyResult>() {
@@ -150,28 +146,11 @@ public class DecryptVerifyResult extends InputPendingResult {
} }
}; };
public void addSecurityProblem(SecurityProblem securityProblem) { public DecryptVerifySecurityProblem getSecurityProblem() {
if (securityProblem == null) { return mSecurityProblem;
return;
}
if (mSecurityProblems == null) {
mSecurityProblems = new ArrayList<>();
}
mSecurityProblems.add(securityProblem);
} }
public void addSecurityProblems(List<SecurityProblem> securityProblems) { public void setSecurityProblemResult(DecryptVerifySecurityProblem securityProblem) {
if (securityProblems == null) { mSecurityProblem = securityProblem;
return;
}
if (mSecurityProblems == null) {
mSecurityProblems = new ArrayList<>();
}
mSecurityProblems.addAll(securityProblems);
}
public List<SecurityProblem> getSecurityProblems() {
return mSecurityProblems != null ?
Collections.unmodifiableList(mSecurityProblems) : Collections.<SecurityProblem>emptyList();
} }
} }

View File

@@ -0,0 +1,54 @@
package org.sufficientlysecure.keychain.pgp;
import java.io.Serializable;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureSigningAlgorithm;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.EncryptionAlgorithmProblem;
public class DecryptVerifySecurityProblem implements Serializable {
public final KeySecurityProblem encryptionKeySecurityProblem;
public final KeySecurityProblem signingKeySecurityProblem;
public final EncryptionAlgorithmProblem symmetricSecurityProblem;
public final InsecureSigningAlgorithm signatureSecurityProblem;
private DecryptVerifySecurityProblem(DecryptVerifySecurityProblemBuilder builder) {
encryptionKeySecurityProblem = builder.encryptionKeySecurityProblem;
signingKeySecurityProblem = builder.signingKeySecurityProblem;
symmetricSecurityProblem = builder.symmetricSecurityProblem;
signatureSecurityProblem = builder.signatureSecurityProblem;
}
static class DecryptVerifySecurityProblemBuilder {
private KeySecurityProblem encryptionKeySecurityProblem;
private KeySecurityProblem signingKeySecurityProblem;
private EncryptionAlgorithmProblem symmetricSecurityProblem;
private InsecureSigningAlgorithm signatureSecurityProblem;
void addEncryptionKeySecurityProblem(KeySecurityProblem encryptionKeySecurityProblem) {
this.encryptionKeySecurityProblem = encryptionKeySecurityProblem;
}
void addSigningKeyProblem(KeySecurityProblem keySecurityProblem) {
this.signingKeySecurityProblem = keySecurityProblem;
}
void addSymmetricSecurityProblem(EncryptionAlgorithmProblem symmetricSecurityProblem) {
this.symmetricSecurityProblem = symmetricSecurityProblem;
}
void addSignatureSecurityProblem(InsecureSigningAlgorithm signatureSecurityProblem) {
this.signatureSecurityProblem = signatureSecurityProblem;
}
public DecryptVerifySecurityProblem build() {
if (encryptionKeySecurityProblem == null && signingKeySecurityProblem == null &&
symmetricSecurityProblem == null && signatureSecurityProblem == null) {
return null;
}
return new DecryptVerifySecurityProblem(this);
}
}
}

View File

@@ -17,33 +17,20 @@
package org.sufficientlysecure.keychain.pgp; package org.sufficientlysecure.keychain.pgp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.openintents.openpgp.OpenPgpDecryptionResult; import org.openintents.openpgp.OpenPgpDecryptionResult;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.SymmetricAlgorithmProblem;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
public class OpenPgpDecryptionResultBuilder { class OpenPgpDecryptionResultBuilder {
// builder // builder
private boolean isInsecure = false;
private boolean isEncrypted = false; private boolean isEncrypted = false;
private byte[] sessionKey; private byte[] sessionKey;
private byte[] decryptedSessionKey; private byte[] decryptedSessionKey;
private ArrayList<SecurityProblem> securityProblems;
public void addSecurityProblem(SecurityProblem securityProblem) { public void setInsecure(boolean insecure) {
if (securityProblems == null) { this.isInsecure = insecure;
securityProblems = new ArrayList<>();
}
securityProblems.add(securityProblem);
}
public List<SecurityProblem> getKeySecurityProblems() {
return securityProblems != null ? Collections.unmodifiableList(securityProblems) : null;
} }
public void setEncrypted(boolean encrypted) { public void setEncrypted(boolean encrypted) {
@@ -51,15 +38,14 @@ public class OpenPgpDecryptionResultBuilder {
} }
public OpenPgpDecryptionResult build() { public OpenPgpDecryptionResult build() {
if (securityProblems != null && !securityProblems.isEmpty()) { if (isInsecure) {
Log.d(Constants.TAG, "RESULT_INSECURE"); Log.d(Constants.TAG, "RESULT_INSECURE");
return new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_INSECURE, sessionKey, decryptedSessionKey); return new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_INSECURE, sessionKey, decryptedSessionKey);
} }
if (isEncrypted) { if (isEncrypted) {
Log.d(Constants.TAG, "RESULT_ENCRYPTED"); Log.d(Constants.TAG, "RESULT_ENCRYPTED");
return new OpenPgpDecryptionResult( return new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_ENCRYPTED, sessionKey, decryptedSessionKey);
OpenPgpDecryptionResult.RESULT_ENCRYPTED, sessionKey, decryptedSessionKey);
} }
Log.d(Constants.TAG, "RESULT_NOT_ENCRYPTED"); Log.d(Constants.TAG, "RESULT_NOT_ENCRYPTED");
@@ -67,12 +53,11 @@ public class OpenPgpDecryptionResultBuilder {
} }
public void setSessionKey(byte[] sessionKey, byte[] decryptedSessionKey) { void setSessionKey(byte[] sessionKey, byte[] decryptedSessionKey) {
if ((sessionKey == null) != (decryptedSessionKey == null)) { if ((sessionKey == null) != (decryptedSessionKey == null)) {
throw new AssertionError("sessionKey must be null iff decryptedSessionKey is null!"); throw new AssertionError("sessionKey must be null iff decryptedSessionKey is null!");
} }
this.sessionKey = sessionKey; this.sessionKey = sessionKey;
this.decryptedSessionKey = decryptedSessionKey; this.decryptedSessionKey = decryptedSessionKey;
} }
} }

View File

@@ -19,9 +19,7 @@ package org.sufficientlysecure.keychain.pgp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
import org.openintents.openpgp.OpenPgpSignatureResult.SenderStatusResult; import org.openintents.openpgp.OpenPgpSignatureResult.SenderStatusResult;
@@ -55,9 +53,9 @@ public class OpenPgpSignatureResultBuilder {
private boolean mIsSignatureKeyCertified = false; private boolean mIsSignatureKeyCertified = false;
private boolean mIsKeyRevoked = false; private boolean mIsKeyRevoked = false;
private boolean mIsKeyExpired = false; private boolean mIsKeyExpired = false;
private boolean mInsecure = false;
private String mSenderAddress; private String mSenderAddress;
private Date mSignatureTimestamp; private Date mSignatureTimestamp;
private ArrayList<SecurityProblem> mSecurityProblems;
public OpenPgpSignatureResultBuilder(KeyRepository keyRepository) { public OpenPgpSignatureResultBuilder(KeyRepository keyRepository) {
this.mKeyRepository = keyRepository; this.mKeyRepository = keyRepository;
@@ -83,15 +81,8 @@ public class OpenPgpSignatureResultBuilder {
this.mValidSignature = validSignature; this.mValidSignature = validSignature;
} }
public void addSecurityProblem(SecurityProblem securityProblem) { public void setInsecure(boolean insecure) {
if (mSecurityProblems == null) { this.mInsecure = insecure;
mSecurityProblems = new ArrayList<>();
}
mSecurityProblems.add(securityProblem);
}
public List<SecurityProblem> getSecurityProblems() {
return mSecurityProblems != null ? Collections.unmodifiableList(mSecurityProblems) : null;
} }
public void setSignatureKeyCertified(boolean isSignatureKeyCertified) { public void setSignatureKeyCertified(boolean isSignatureKeyCertified) {
@@ -115,6 +106,10 @@ public class OpenPgpSignatureResultBuilder {
this.mConfirmedUserIds = confirmedUserIds; this.mConfirmedUserIds = confirmedUserIds;
} }
public boolean isInsecure() {
return mInsecure;
}
public void initValid(CanonicalizedPublicKey signingKey) { public void initValid(CanonicalizedPublicKey signingKey) {
setSignatureAvailable(true); setSignatureAvailable(true);
setKnownKey(true); setKnownKey(true);
@@ -189,7 +184,7 @@ public class OpenPgpSignatureResultBuilder {
} else if (mIsKeyExpired) { } else if (mIsKeyExpired) {
Log.d(Constants.TAG, "RESULT_INVALID_KEY_EXPIRED"); Log.d(Constants.TAG, "RESULT_INVALID_KEY_EXPIRED");
signatureStatus = OpenPgpSignatureResult.RESULT_INVALID_KEY_EXPIRED; signatureStatus = OpenPgpSignatureResult.RESULT_INVALID_KEY_EXPIRED;
} else if (mSecurityProblems != null && !mSecurityProblems.isEmpty()) { } else if (mInsecure) {
Log.d(Constants.TAG, "RESULT_INVALID_INSECURE"); Log.d(Constants.TAG, "RESULT_INVALID_INSECURE");
signatureStatus = OpenPgpSignatureResult.RESULT_INVALID_KEY_INSECURE; signatureStatus = OpenPgpSignatureResult.RESULT_INVALID_KEY_INSECURE;
} else if (mIsSignatureKeyCertified) { } else if (mIsSignatureKeyCertified) {

View File

@@ -68,9 +68,11 @@ import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.pgp.DecryptVerifySecurityProblem.DecryptVerifySecurityProblemBuilder;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureBitStrength;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem; import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.MissingMdc; import org.sufficientlysecure.keychain.pgp.SecurityProblem.MissingMdc;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.SymmetricAlgorithmProblem; import org.sufficientlysecure.keychain.pgp.SecurityProblem.EncryptionAlgorithmProblem;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
@@ -301,6 +303,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
JcaSkipMarkerPGPObjectFactory plainFact; JcaSkipMarkerPGPObjectFactory plainFact;
Object dataChunk; Object dataChunk;
EncryptStreamResult esResult = null; EncryptStreamResult esResult = null;
DecryptVerifySecurityProblemBuilder securityProblemBuilder = new DecryptVerifySecurityProblemBuilder();
{ // resolve encrypted (symmetric and asymmetric) packets { // resolve encrypted (symmetric and asymmetric) packets
JcaSkipMarkerPGPObjectFactory pgpF = new JcaSkipMarkerPGPObjectFactory(in); JcaSkipMarkerPGPObjectFactory pgpF = new JcaSkipMarkerPGPObjectFactory(in);
Object obj = pgpF.nextObject(); Object obj = pgpF.nextObject();
@@ -322,15 +325,17 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
if (esResult.encryptionKeySecurityProblem != null) { if (esResult.encryptionKeySecurityProblem != null) {
log.add(LogType.MSG_DC_INSECURE_SYMMETRIC_ENCRYPTION_ALGO, indent + 1); log.add(LogType.MSG_DC_INSECURE_SYMMETRIC_ENCRYPTION_ALGO, indent + 1);
decryptionResultBuilder.addSecurityProblem(esResult.encryptionKeySecurityProblem); securityProblemBuilder.addEncryptionKeySecurityProblem(esResult.encryptionKeySecurityProblem);
decryptionResultBuilder.setInsecure(true);
} }
// Check for insecure encryption algorithms! // Check for insecure encryption algorithms!
SymmetricAlgorithmProblem symmetricSecurityProblem = EncryptionAlgorithmProblem symmetricSecurityProblem =
PgpSecurityConstants.checkSecureSymmetricAlgorithm(esResult.symmetricEncryptionAlgo); PgpSecurityConstants.checkSecureSymmetricAlgorithm(esResult.symmetricEncryptionAlgo);
if (symmetricSecurityProblem != null) { if (symmetricSecurityProblem != null) {
log.add(LogType.MSG_DC_INSECURE_SYMMETRIC_ENCRYPTION_ALGO, indent + 1); log.add(LogType.MSG_DC_INSECURE_SYMMETRIC_ENCRYPTION_ALGO, indent + 1);
decryptionResultBuilder.addSecurityProblem(symmetricSecurityProblem); securityProblemBuilder.addSymmetricSecurityProblem(symmetricSecurityProblem);
decryptionResultBuilder.setInsecure(true);
} }
plainFact = new JcaSkipMarkerPGPObjectFactory(esResult.cleartextStream); plainFact = new JcaSkipMarkerPGPObjectFactory(esResult.cleartextStream);
@@ -361,7 +366,8 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
plainFact = fact; plainFact = fact;
} }
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mKeyRepository, input.getSenderAddress()); PgpSignatureChecker signatureChecker = new PgpSignatureChecker(
mKeyRepository, input.getSenderAddress(), securityProblemBuilder);
if (signatureChecker.initializeOnePassSignature(dataChunk, log, indent +1)) { if (signatureChecker.initializeOnePassSignature(dataChunk, log, indent +1)) {
dataChunk = plainFact.nextObject(); dataChunk = plainFact.nextObject();
} }
@@ -536,7 +542,8 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
// Handle missing integrity protection like failed integrity protection! // Handle missing integrity protection like failed integrity protection!
// The MDC packet can be stripped by an attacker! // The MDC packet can be stripped by an attacker!
log.add(LogType.MSG_DC_INSECURE_MDC_MISSING, indent); log.add(LogType.MSG_DC_INSECURE_MDC_MISSING, indent);
decryptionResultBuilder.addSecurityProblem(new MissingMdc()); securityProblemBuilder.addSymmetricSecurityProblem(new MissingMdc());
decryptionResultBuilder.setInsecure(true);
} }
} }
@@ -549,8 +556,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
result.setCachedCryptoInputParcel(cryptoInput); result.setCachedCryptoInputParcel(cryptoInput);
result.setSignatureResult(signatureChecker.getSignatureResult()); result.setSignatureResult(signatureChecker.getSignatureResult());
result.setDecryptionResult(decryptionResultBuilder.build()); result.setDecryptionResult(decryptionResultBuilder.build());
result.addSecurityProblems(signatureChecker.getSecurityProblems()); result.setSecurityProblemResult(securityProblemBuilder.build());
result.addSecurityProblems(decryptionResultBuilder.getKeySecurityProblems());
result.setDecryptionMetadata(metadata); result.setDecryptionMetadata(metadata);
result.mOperationTime = opTime; result.mOperationTime = opTime;
@@ -888,7 +894,9 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
updateProgress(R.string.progress_processing_signature, 60, 100); updateProgress(R.string.progress_processing_signature, 60, 100);
JcaSkipMarkerPGPObjectFactory pgpFact = new JcaSkipMarkerPGPObjectFactory(aIn); JcaSkipMarkerPGPObjectFactory pgpFact = new JcaSkipMarkerPGPObjectFactory(aIn);
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mKeyRepository, input.getSenderAddress()); DecryptVerifySecurityProblemBuilder securityProblemBuilder = new DecryptVerifySecurityProblemBuilder();
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mKeyRepository, input.getSenderAddress(),
securityProblemBuilder);
Object o = pgpFact.nextObject(); Object o = pgpFact.nextObject();
if (!signatureChecker.initializeSignature(o, log, indent+1)) { if (!signatureChecker.initializeSignature(o, log, indent+1)) {
@@ -919,6 +927,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
result.setSignatureResult(signatureChecker.getSignatureResult()); result.setSignatureResult(signatureChecker.getSignatureResult());
result.setDecryptionResult( result.setDecryptionResult(
new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED)); new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED));
result.setSecurityProblemResult(securityProblemBuilder.build());
result.setDecryptionMetadata(metadata); result.setDecryptionMetadata(metadata);
return result; return result;
} }
@@ -943,7 +952,9 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
o = pgpFact.nextObject(); o = pgpFact.nextObject();
} }
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mKeyRepository, input.getSenderAddress()); DecryptVerifySecurityProblemBuilder securityProblemBuilder = new DecryptVerifySecurityProblemBuilder();
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mKeyRepository, input.getSenderAddress(),
securityProblemBuilder);
if ( ! signatureChecker.initializeSignature(o, log, indent+1)) { if ( ! signatureChecker.initializeSignature(o, log, indent+1)) {
log.add(LogType.MSG_DC_ERROR_INVALID_DATA, 0); log.add(LogType.MSG_DC_ERROR_INVALID_DATA, 0);
@@ -994,6 +1005,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
result.setSignatureResult(signatureChecker.getSignatureResult()); result.setSignatureResult(signatureChecker.getSignatureResult());
result.setSecurityProblemResult(securityProblemBuilder.build());
result.setDecryptionResult( result.setDecryptionResult(
new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED)); new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED));
return result; return result;

View File

@@ -31,11 +31,11 @@ import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.crypto.ec.CustomNamedCurves;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureBitStrength; import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureBitStrength;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureHashAlgorithm; import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureSigningAlgorithm;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureSymmetricAlgorithm; import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureEncryptionAlgorithm;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem; import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.NotWhitelistedCurve; import org.sufficientlysecure.keychain.pgp.SecurityProblem.NotWhitelistedCurve;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.SymmetricAlgorithmProblem; import org.sufficientlysecure.keychain.pgp.SecurityProblem.EncryptionAlgorithmProblem;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.UnidentifiedKeyProblem; import org.sufficientlysecure.keychain.pgp.SecurityProblem.UnidentifiedKeyProblem;
@@ -74,9 +74,9 @@ public class PgpSecurityConstants {
// CAMELLIA_256: not used widely // CAMELLIA_256: not used widely
)); ));
public static SymmetricAlgorithmProblem checkSecureSymmetricAlgorithm(int id) { public static EncryptionAlgorithmProblem checkSecureSymmetricAlgorithm(int id) {
if (!sSymmetricAlgorithmsWhitelist.contains(id)) { if (!sSymmetricAlgorithmsWhitelist.contains(id)) {
return new InsecureSymmetricAlgorithm(id); return new InsecureEncryptionAlgorithm(id);
} }
return null; return null;
} }
@@ -107,9 +107,9 @@ public class PgpSecurityConstants {
// SHA224: Not used widely, Yahoo argues against it // SHA224: Not used widely, Yahoo argues against it
)); ));
public static InsecureHashAlgorithm checkSignatureAlgorithmForSecurityProblems(int hashAlgorithm) { static InsecureSigningAlgorithm checkSignatureAlgorithmForSecurityProblems(int hashAlgorithm) {
if (!sHashAlgorithmsWhitelist.contains(hashAlgorithm)) { if (!sHashAlgorithmsWhitelist.contains(hashAlgorithm)) {
return new InsecureHashAlgorithm(hashAlgorithm); return new InsecureSigningAlgorithm(hashAlgorithm);
} }
return null; return null;
} }

View File

@@ -25,7 +25,6 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.security.SignatureException; import java.security.SignatureException;
import java.util.List;
import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPOnePassSignature; import org.bouncycastle.openpgp.PGPOnePassSignature;
@@ -37,11 +36,12 @@ import org.openintents.openpgp.OpenPgpSignatureResult;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.provider.KeyWritableRepository; import org.sufficientlysecure.keychain.pgp.DecryptVerifySecurityProblem.DecryptVerifySecurityProblemBuilder;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureHashAlgorithm; import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureSigningAlgorithm;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem; import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeyRepository; import org.sufficientlysecure.keychain.provider.KeyRepository;
import org.sufficientlysecure.keychain.provider.KeyWritableRepository;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
@@ -52,20 +52,24 @@ import org.sufficientlysecure.keychain.util.Log;
class PgpSignatureChecker { class PgpSignatureChecker {
private final OpenPgpSignatureResultBuilder signatureResultBuilder; private final OpenPgpSignatureResultBuilder signatureResultBuilder;
private final DecryptVerifySecurityProblemBuilder securityProblemBuilder;
private CanonicalizedPublicKey signingKey; private CanonicalizedPublicKey signingKey;
private int signatureIndex; private int signatureIndex;
PGPOnePassSignature onePassSignature; private PGPOnePassSignature onePassSignature;
PGPSignature signature; private PGPSignature signature;
KeyRepository mKeyRepository; private KeyRepository mKeyRepository;
PgpSignatureChecker(KeyRepository keyRepository, String senderAddress) { PgpSignatureChecker(KeyRepository keyRepository, String senderAddress,
DecryptVerifySecurityProblemBuilder securityProblemBuilder) {
mKeyRepository = keyRepository; mKeyRepository = keyRepository;
signatureResultBuilder = new OpenPgpSignatureResultBuilder(keyRepository); signatureResultBuilder = new OpenPgpSignatureResultBuilder(keyRepository);
signatureResultBuilder.setSenderAddress(senderAddress); signatureResultBuilder.setSenderAddress(senderAddress);
this.securityProblemBuilder = securityProblemBuilder;
} }
boolean initializeSignature(Object dataChunk, OperationLog log, int indent) throws PGPException { boolean initializeSignature(Object dataChunk, OperationLog log, int indent) throws PGPException {
@@ -142,11 +146,12 @@ class PgpSignatureChecker {
PgpSecurityConstants.checkForSecurityProblems(signingKey); PgpSecurityConstants.checkForSecurityProblems(signingKey);
if (keySecurityProblem != null) { if (keySecurityProblem != null) {
log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1); log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1);
signatureResultBuilder.addSecurityProblem(keySecurityProblem); securityProblemBuilder.addSigningKeyProblem(keySecurityProblem);
signatureResultBuilder.setInsecure(true);
} }
} }
public boolean isInitialized() { boolean isInitialized() {
return signingKey != null; return signingKey != null;
} }
@@ -173,7 +178,7 @@ class PgpSignatureChecker {
} }
} }
public void findAvailableSignature(PGPSignatureList sigList) { private void findAvailableSignature(PGPSignatureList sigList) {
// go through all signatures (should be just one), make sure we have // go through all signatures (should be just one), make sure we have
// the key and it matches the one were looking for // the key and it matches the one were looking for
for (int i = 0; i < sigList.size(); ++i) { for (int i = 0; i < sigList.size(); ++i) {
@@ -238,11 +243,12 @@ class PgpSignatureChecker {
} }
// check for insecure hash algorithms // check for insecure hash algorithms
InsecureHashAlgorithm signatureSecurityProblem = InsecureSigningAlgorithm signatureSecurityProblem =
PgpSecurityConstants.checkSignatureAlgorithmForSecurityProblems(signature.getHashAlgorithm()); PgpSecurityConstants.checkSignatureAlgorithmForSecurityProblems(signature.getHashAlgorithm());
if (signatureSecurityProblem != null) { if (signatureSecurityProblem != null) {
log.add(LogType.MSG_DC_INSECURE_HASH_ALGO, indent + 1); log.add(LogType.MSG_DC_INSECURE_HASH_ALGO, indent + 1);
signatureResultBuilder.addSecurityProblem(signatureSecurityProblem); securityProblemBuilder.addSignatureSecurityProblem(signatureSecurityProblem);
signatureResultBuilder.setInsecure(true);
} }
signatureResultBuilder.setSignatureTimestamp(signature.getCreationTime()); signatureResultBuilder.setSignatureTimestamp(signature.getCreationTime());
@@ -275,11 +281,12 @@ class PgpSignatureChecker {
} }
// check for insecure hash algorithms // check for insecure hash algorithms
InsecureHashAlgorithm signatureSecurityProblem = InsecureSigningAlgorithm signatureSecurityProblem =
PgpSecurityConstants.checkSignatureAlgorithmForSecurityProblems(onePassSignature.getHashAlgorithm()); PgpSecurityConstants.checkSignatureAlgorithmForSecurityProblems(onePassSignature.getHashAlgorithm());
if (signatureSecurityProblem != null) { if (signatureSecurityProblem != null) {
log.add(LogType.MSG_DC_INSECURE_HASH_ALGO, indent + 1); log.add(LogType.MSG_DC_INSECURE_HASH_ALGO, indent + 1);
signatureResultBuilder.addSecurityProblem(signatureSecurityProblem); securityProblemBuilder.addSignatureSecurityProblem(signatureSecurityProblem);
signatureResultBuilder.setInsecure(true);
} }
signatureResultBuilder.setSignatureTimestamp(messageSignature.getCreationTime()); signatureResultBuilder.setSignatureTimestamp(messageSignature.getCreationTime());
@@ -297,10 +304,6 @@ class PgpSignatureChecker {
return signatureResultBuilder.build(); return signatureResultBuilder.build();
} }
public List<SecurityProblem> getSecurityProblems() {
return signatureResultBuilder.getSecurityProblems();
}
/** /**
* Mostly taken from ClearSignedFileProcessor in Bouncy Castle * Mostly taken from ClearSignedFileProcessor in Bouncy Castle
*/ */

View File

@@ -34,7 +34,7 @@ public abstract class SecurityProblem implements Serializable {
} }
} }
public static abstract class SymmetricAlgorithmProblem extends SecurityProblem { public static abstract class EncryptionAlgorithmProblem extends SecurityProblem {
} }
@@ -62,23 +62,23 @@ public abstract class SecurityProblem implements Serializable {
} }
} }
public static class InsecureHashAlgorithm extends SecurityProblem { public static class InsecureSigningAlgorithm extends SecurityProblem {
public final int hashAlgorithm; public final int hashAlgorithm;
InsecureHashAlgorithm(int hashAlgorithm) { InsecureSigningAlgorithm(int hashAlgorithm) {
this.hashAlgorithm = hashAlgorithm; this.hashAlgorithm = hashAlgorithm;
} }
} }
public static class InsecureSymmetricAlgorithm extends SymmetricAlgorithmProblem { public static class InsecureEncryptionAlgorithm extends EncryptionAlgorithmProblem {
public final int symmetricAlgorithm; public final int symmetricAlgorithm;
InsecureSymmetricAlgorithm(int symmetricAlgorithm) { InsecureEncryptionAlgorithm(int symmetricAlgorithm) {
this.symmetricAlgorithm = symmetricAlgorithm; this.symmetricAlgorithm = symmetricAlgorithm;
} }
} }
public static class MissingMdc extends SymmetricAlgorithmProblem { public static class MissingMdc extends EncryptionAlgorithmProblem {
} }
} }

View File

@@ -25,7 +25,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build; import android.os.Build;
import org.sufficientlysecure.keychain.pgp.SecurityProblem; import org.sufficientlysecure.keychain.pgp.DecryptVerifySecurityProblem;
import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.remote.ui.RemoteBackupActivity; import org.sufficientlysecure.keychain.remote.ui.RemoteBackupActivity;
import org.sufficientlysecure.keychain.remote.ui.RemoteErrorActivity; import org.sufficientlysecure.keychain.remote.ui.RemoteErrorActivity;
@@ -143,10 +143,10 @@ public class ApiPendingIntentFactory {
return createInternal(data, intent); return createInternal(data, intent);
} }
PendingIntent createSecurityProblemIntent(String packageName, SecurityProblem keySecurityProblem) { PendingIntent createSecurityProblemIntent(String packageName, DecryptVerifySecurityProblem securityProblem) {
Intent intent = new Intent(mContext, RemoteSecurityProblemDialogActivity.class); Intent intent = new Intent(mContext, RemoteSecurityProblemDialogActivity.class);
intent.putExtra(RemoteSecurityProblemDialogActivity.EXTRA_PACKAGE_NAME, packageName); intent.putExtra(RemoteSecurityProblemDialogActivity.EXTRA_PACKAGE_NAME, packageName);
intent.putExtra(RemoteSecurityProblemDialogActivity.EXTRA_SECURITY_PROBLEM, keySecurityProblem); intent.putExtra(RemoteSecurityProblemDialogActivity.EXTRA_SECURITY_PROBLEM, securityProblem);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//noinspection ResourceType, looks like lint is missing FLAG_IMMUTABLE //noinspection ResourceType, looks like lint is missing FLAG_IMMUTABLE

View File

@@ -53,6 +53,7 @@ import org.sufficientlysecure.keychain.operations.results.ExportResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel;
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
import org.sufficientlysecure.keychain.pgp.DecryptVerifySecurityProblem;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants; import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
@@ -60,7 +61,6 @@ import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInputParcel; import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation; import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation;
import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.SecurityProblem;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.ApiDataAccessObject; import org.sufficientlysecure.keychain.provider.ApiDataAccessObject;
import org.sufficientlysecure.keychain.provider.KeyRepository; import org.sufficientlysecure.keychain.provider.KeyRepository;
@@ -430,17 +430,14 @@ public class OpenPgpService extends Service {
} }
private void processSecurityProblemsPendingIntent(Intent result, DecryptVerifyResult decryptVerifyResult) { private void processSecurityProblemsPendingIntent(Intent result, DecryptVerifyResult decryptVerifyResult) {
List<SecurityProblem> securityProblems = decryptVerifyResult.getSecurityProblems(); DecryptVerifySecurityProblem securityProblem = decryptVerifyResult.getSecurityProblem();
if (securityProblems.isEmpty()) { if (securityProblem == null) {
return; return;
} }
// TODO what if there is multiple?
SecurityProblem keySecurityProblem = securityProblems.get(0);
String packageName = mApiPermissionHelper.getCurrentCallingPackage(); String packageName = mApiPermissionHelper.getCurrentCallingPackage();
result.putExtra(OpenPgpApi.RESULT_INSECURE_DETAIL_INTENT, result.putExtra(OpenPgpApi.RESULT_INSECURE_DETAIL_INTENT,
mApiPendingIntentFactory.createSecurityProblemIntent(packageName, keySecurityProblem)); mApiPendingIntentFactory.createSecurityProblemIntent(packageName, securityProblem));
} }
private void processDecryptionResultForResultIntent(int targetApiVersion, Intent result, private void processDecryptionResultForResultIntent(int targetApiVersion, Intent result,

View File

@@ -18,6 +18,15 @@
package org.sufficientlysecure.keychain.ui.util; package org.sufficientlysecure.keychain.ui.util;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.DigestException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.Locale;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Color; import android.graphics.Color;
@@ -48,14 +57,6 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.DigestException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.Locale;
public class KeyFormattingUtils { public class KeyFormattingUtils {
public static String getAlgorithmInfo(int algorithm, Integer keySize, String oid) { public static String getAlgorithmInfo(int algorithm, Integer keySize, String oid) {