Skip to content

Commit

Permalink
Merge pull request #522 from CROSSINGTUD/develop
Browse files Browse the repository at this point in the history
Add detection of subsequent errors to CryptoAnalysis with release 3.1.0
  • Loading branch information
schlichtig authored Feb 5, 2024
2 parents fd942eb + e169111 commit 598ab7e
Show file tree
Hide file tree
Showing 34 changed files with 1,207 additions and 482 deletions.
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

0 comments on commit 598ab7e

Please sign in to comment.