Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add detection of subsequent errors to CryptoAnalysis with release 3.1.0 #522

Merged
merged 7 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CryptoAnalysis/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
<artifactItem>
<groupId>de.darmstadt.tu.crossing</groupId>
<artifactId>JavaCryptographicArchitecture</artifactId>
<version>3.0.2</version>
<version>3.1.0</version>
<classifier>ruleset</classifier>
<type>zip</type>
<overWrite>true</overWrite>
Expand Down Expand Up @@ -117,7 +117,7 @@
<artifactItem>
<groupId>de.paderborn.uni</groupId>
<artifactId>BouncyCastle-JCA</artifactId>
<version>3.0.2</version>
<version>3.1.0</version>
<classifier>ruleset</classifier>
<type>zip</type>
<overWrite>true</overWrite>
Expand Down

Large diffs are not rendered by default.

91 changes: 91 additions & 0 deletions CryptoAnalysis/src/main/java/crypto/analysis/HiddenPredicate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package crypto.analysis;

import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import crypto.analysis.errors.AbstractError;
import crypto.analysis.errors.ConstraintError;
import crypto.analysis.errors.HardCodedError;
import crypto.analysis.errors.ImpreciseValueExtractionError;
import crypto.analysis.errors.IncompleteOperationError;
import crypto.analysis.errors.InstanceOfError;
import crypto.analysis.errors.NeverTypeOfError;
import crypto.analysis.errors.RequiredPredicateError;
import crypto.analysis.errors.TypestateError;
import crypto.extractparameter.CallSiteWithParamIndex;
import crypto.extractparameter.ExtractedValue;
import crypto.rules.CrySLPredicate;

import java.util.List;
import java.util.stream.Collectors;

public class HiddenPredicate extends EnsuredCrySLPredicate {

private final AnalysisSeedWithSpecification generatingSeed;
private final HiddenPredicateType type;

public HiddenPredicate(CrySLPredicate predicate, Multimap<CallSiteWithParamIndex, ExtractedValue> parametersToValues2, AnalysisSeedWithSpecification generatingSeed, HiddenPredicateType type) {
super(predicate, parametersToValues2);
this.generatingSeed = generatingSeed;
this.type = type;
}

public AnalysisSeedWithSpecification getGeneratingSeed() {
return generatingSeed;
}

public enum HiddenPredicateType {
GeneratingStateIsNeverReached,
ConstraintsAreNotSatisfied,
ConditionIsNotSatisfied
}

public HiddenPredicateType getType() {
return type;
}

/**
* Node: Errors are only in complete count at the end of the analysis.
* @return errors list of all preceding errors
*/
public List<AbstractError> getPrecedingErrors(){
List<AbstractError> results = Lists.newArrayList();
List<AbstractError> allErrors = generatingSeed.getErrors();
switch(type) {
case GeneratingStateIsNeverReached:
List<AbstractError> typestateErrors = allErrors.stream().filter(e -> (e instanceof IncompleteOperationError || e instanceof TypestateError)).collect(Collectors.toList());
if(typestateErrors.isEmpty()) {
// Seed object has no typestate errors that might be responsible for this hidden predicate
// TODO: report new info error type to report,
// that the seeds object could potentially ensure the missing predicate which might cause further subsequent errors
// but therefore requires a call to the predicate generating statement
}

// TODO: check whether the generating state is not reached due to a typestate error
return allErrors;

case ConstraintsAreNotSatisfied:
// Generating state was reached but constraints are not satisfied.
// Thus, return all constraints & required predicate errors.
return allErrors.stream().filter(e -> (e instanceof RequiredPredicateError || e instanceof ConstraintError || e instanceof HardCodedError || e instanceof ImpreciseValueExtractionError || e instanceof InstanceOfError || e instanceof NeverTypeOfError)).collect(Collectors.toList());
case ConditionIsNotSatisfied:
// Generating state was reached but the predicates condition is not satisfied.
// Thus, return all errors that causes the condition to be not satisfied
List<AbstractError> precedingErrors = Lists.newArrayList(generatingSeed.retrieveErrorsForPredCondition(this.getPredicate()));
// This method is called from a RequiredPredicateError that wants to retrieve its preceding errors.
// In this case, preceding errors are not reported yet because the predicate condition wasn't required to be satisfied.
// Since the hidden predicate is required to be an ensured predicate, we can assume the condition required to be satisfied.
// Thus, we report all errors that causes the condition to be not satisfied.
precedingErrors.forEach(e -> this.generatingSeed.cryptoScanner.getAnalysisListener().reportError(generatingSeed, e));
// Further, preceding errors can be of type RequiredPredicateError.
// Thus, we have to recursively map preceding errors for the newly reported errors.
for(AbstractError e: precedingErrors) {
if(e instanceof RequiredPredicateError) {
((RequiredPredicateError)e).mapPrecedingErrors();
}
}
return precedingErrors;

}
return results;
}
}
13 changes: 13 additions & 0 deletions CryptoAnalysis/src/main/java/crypto/analysis/IAnalysisSeed.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import boomerang.WeightedForwardQuery;
import boomerang.jimple.Statement;
import boomerang.jimple.Val;
import crypto.analysis.errors.AbstractError;
import crypto.predicates.PredicateHandler;
import soot.SootMethod;
import sync.pds.solver.nodes.Node;
Expand All @@ -17,18 +20,28 @@ public abstract class IAnalysisSeed extends WeightedForwardQuery<TransitionFunct

protected final CryptoScanner cryptoScanner;
protected final PredicateHandler predicateHandler;
protected final List<AbstractError> errorCollection;
private String objectId;

public IAnalysisSeed(CryptoScanner scanner, Statement stmt, Val fact, TransitionFunction func){
super(stmt,fact, func);
this.cryptoScanner = scanner;
this.predicateHandler = scanner.getPredicateHandler();
this.errorCollection = new ArrayList<>();
}
abstract void execute();

public SootMethod getMethod(){
return stmt().getMethod();
}

public void addError(AbstractError e) {
this.errorCollection.add(e);
}

public List<AbstractError> getErrors(){
return new ArrayList<>(errorCollection);
}

public String getObjectId() {
if(objectId == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,29 @@
import soot.jimple.internal.JReturnStmt;
import soot.jimple.internal.JReturnVoidStmt;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

public abstract class AbstractError implements IError{
private Statement errorLocation;
private CrySLRule rule;
private final String outerMethod;
private final String invokeMethod;
private final String declaringClass;

private Set<AbstractError> causedByErrors; // preceding
private Set<AbstractError> willCauseErrors; // subsequent

public AbstractError(Statement errorLocation, CrySLRule rule) {
this.errorLocation = errorLocation;
this.rule = rule;
this.outerMethod = errorLocation.getMethod().getSignature();
this.declaringClass = errorLocation.getMethod().getDeclaringClass().toString();

this.causedByErrors = new HashSet<>();
this.willCauseErrors = new HashSet<>();

Stmt errorStmt = errorLocation.getUnit().get();
if(errorStmt.containsInvokeExpr()) {
this.invokeMethod = errorStmt.getInvokeExpr().getMethod().toString();
Expand All @@ -33,6 +43,26 @@ public AbstractError(Statement errorLocation, CrySLRule rule) {
}
}

public void addCausingError(AbstractError parent) {
causedByErrors.add(parent);
}

public void addCausingError(Collection<AbstractError> parents) {
causedByErrors.addAll(parents);
}

public void addSubsequentError(AbstractError subsequentError) {
willCauseErrors.add(subsequentError);
}

public Set<AbstractError> getSubsequentErrors(){
return this.willCauseErrors;
}

public Set<AbstractError> getRootErrors(){
return this.causedByErrors;
}

public Statement getErrorLocation() {
return errorLocation;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package crypto.analysis.errors;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import boomerang.jimple.Statement;
import crypto.analysis.HiddenPredicate;
import crypto.extractparameter.CallSiteWithExtractedValue;
import crypto.rules.CrySLPredicate;
import crypto.rules.CrySLRule;
Expand All @@ -20,11 +23,25 @@ public class RequiredPredicateError extends AbstractError{

private List<CrySLPredicate> contradictedPredicate;
private CallSiteWithExtractedValue extractedValues;
private List<HiddenPredicate> hiddenPredicates;

public RequiredPredicateError(List<CrySLPredicate> contradictedPredicates, Statement location, CrySLRule rule, CallSiteWithExtractedValue multimap) {
super(location, rule);
this.contradictedPredicate = contradictedPredicates;
this.extractedValues = multimap;
this.hiddenPredicates = new ArrayList<>();
}

public void addHiddenPredicates(Collection<HiddenPredicate> hiddenPredicates) {
this.hiddenPredicates.addAll(hiddenPredicates);
}

public void mapPrecedingErrors() {
for (HiddenPredicate hiddenPredicate : hiddenPredicates) {
Collection<AbstractError> precedingErrors = hiddenPredicate.getPrecedingErrors();
this.addCausingError(precedingErrors);
precedingErrors.forEach(e -> e.addSubsequentError(this));
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ public int evaluateRelConstraints() {
break;
} else {
fail++;
this.object.addError(e);
getReporter().reportError(getObject(), e);
}
}
Expand Down Expand Up @@ -198,6 +199,11 @@ private List<RequiredCrySLPredicate> retrieveValuesForPred(ISLConstraint cons) {
}
}
}

// Extract predicates with 'this' as parameter
if (pred.getParameters().stream().anyMatch(param -> param.getName().equals("this"))) {
result.add(new RequiredCrySLPredicate(pred, object.stmt()));
}

return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public ExtractedValue getVal() {
public String toString() {
String res = "";
switch(cs.getIndex()) {
case -1:
return "Return value";
case 0:
res = "First ";
break;
Expand All @@ -44,7 +46,7 @@ public String toString() {
res = "Fourth ";
break;
case 4:
res = "Fiveth ";
res = "Fifth ";
break;
case 5:
res = "Sixth ";
Expand Down
Loading
Loading