Skip to content

Commit

Permalink
Merge pull request #535 from CROSSINGTUD/develop
Browse files Browse the repository at this point in the history
Merge develop for new release
  • Loading branch information
schlichtig authored Mar 15, 2024
2 parents e5820a1 + ffc1e7f commit c1f9ded
Show file tree
Hide file tree
Showing 24 changed files with 676 additions and 180 deletions.
17 changes: 7 additions & 10 deletions CryptoAnalysis/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

<properties>
<spdsVersion>2.5.1</spdsVersion>
<sootVersion>4.2.1</sootVersion>
<sootVersion>4.4.1</sootVersion>
</properties>
<build>
<pluginManagement>
Expand Down Expand Up @@ -308,7 +308,6 @@
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.77</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bctls-jdk18on -->
<dependency>
Expand All @@ -319,18 +318,17 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.11</version>
<version>2.0.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.11</version>
<version>2.0.12</version>
</dependency>
<dependency>
<groupId>com.google.crypto.tink</groupId>
<artifactId>tink</artifactId>
<version>1.3.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
Expand All @@ -346,31 +344,30 @@
<dependency>
<groupId>org.eclipse.xtext</groupId>
<artifactId>org.eclipse.xtext.xbase</artifactId>
<version>2.33.0</version>
<version>2.34.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.eclipse.emf/org.eclipse.emf.common -->
<dependency>
<groupId>org.eclipse.emf</groupId>
<artifactId>org.eclipse.emf.common</artifactId>
<version>2.29.0</version>
<version>2.30.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.eclipse.emf/org.eclipse.emf.ecore -->
<dependency>
<groupId>org.eclipse.emf</groupId>
<artifactId>org.eclipse.emf.ecore</artifactId>
<version>2.35.0</version>
<version>2.36.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.16.1</version>
<version>2.16.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
Expand Down
22 changes: 15 additions & 7 deletions CryptoAnalysis/src/main/java/crypto/HeadlessCryptoScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import boomerang.callgraph.ObservableICFG;
import boomerang.debugger.Debugger;
import boomerang.debugger.IDEVizDebugger;
import boomerang.preanalysis.BoomerangPretransformer;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
import crypto.analysis.CrySLAnalysisListener;
Expand All @@ -16,8 +15,8 @@
import crypto.analysis.IAnalysisSeed;
import crypto.exceptions.CryptoAnalysisException;
import crypto.exceptions.CryptoAnalysisParserException;
import crypto.preanalysis.ExceptionAwareTransformer;
import crypto.preanalysis.SeedFactory;
import crypto.preanalysis.TransformerSetup;
import crypto.providerdetection.ProviderDetection;
import crypto.reporting.CSVReporter;
import crypto.reporting.CSVSummaryReporter;
Expand Down Expand Up @@ -138,7 +137,7 @@ public void exec() {
} catch (CryptoAnalysisException e) {
LOGGER.error("Error happened when executing HeadlessCryptoScanner.", e);
}
ExceptionAwareTransformer.setup(rules);

LOGGER.info("Analysis soot setup done in {} ", stopwatch);
analyse();
LOGGER.info("Analysis finished in {}", stopwatch);
Expand Down Expand Up @@ -189,8 +188,8 @@ private Transformer createAnalysisTransformer() {

@Override
protected void internalTransform(String phaseName, Map<String, String> options) {
BoomerangPretransformer.v().reset();
BoomerangPretransformer.v().apply();
TransformerSetup.v().setupPreTransformer(rules);

ObservableDynamicICFG observableDynamicICFG = new ObservableDynamicICFG(false);
List<CrySLRule> rules = HeadlessCryptoScanner.rules;

Expand Down Expand Up @@ -336,6 +335,14 @@ private void initializeSootWithEntryPointAllReachable(boolean wholeProgram) thro
Options.v().set_no_bodies_for_excluded(true);
Options.v().set_allow_phantom_refs(true);
Options.v().set_keep_line_number(true);

/* This phase is new in soot 4.3.0 and manipulates the jimple code in a
* way that CryptoAnalysis is not able to find seeds in some cases (see
* https://github.com/CROSSINGTUD/CryptoAnalysis/issues/293). Therefore,
* it is disabled.
*/
Options.v().setPhaseOption("jb.sils", "enabled:false");

// JAVA 8
if(getJavaVersion() < 9)
{
Expand Down Expand Up @@ -380,13 +387,14 @@ private List<String> getIncludeList() {
includeList.add("java.lang.String");
includeList.add("java.lang.StringCoding");
includeList.add("java.lang.StringIndexOutOfBoundsException");
return includeList;
return new LinkedList<>();
}

private List<String> getExcludeList() {
List<String> exList = new LinkedList<String>();
List<CrySLRule> rules = getRules();
for(CrySLRule r : rules) {

for (CrySLRule r : rules) {
exList.add(r.getClassName());
}
return exList;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,18 @@
package crypto.analysis;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import boomerang.callgraph.ObservableICFG;
import boomerang.debugger.Debugger;
import boomerang.jimple.AllocVal;
import boomerang.jimple.Statement;
import boomerang.jimple.Val;
import boomerang.results.ForwardBoomerangResults;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.collect.Table;
import com.google.common.collect.Table.Cell;

import boomerang.callgraph.ObservableICFG;
import boomerang.debugger.Debugger;
import boomerang.jimple.AllocVal;
import boomerang.jimple.Statement;
import boomerang.jimple.Val;
import boomerang.results.ForwardBoomerangResults;
import crypto.analysis.errors.AbstractError;
import crypto.analysis.errors.IncompleteOperationError;
import crypto.analysis.errors.RequiredPredicateError;
Expand Down Expand Up @@ -61,14 +48,25 @@
import soot.jimple.Constant;
import soot.jimple.IntConstant;
import soot.jimple.InvokeExpr;
import soot.jimple.Stmt;
import soot.jimple.StringConstant;
import soot.jimple.ThrowStmt;
import sync.pds.solver.nodes.Node;
import typestate.TransitionFunction;
import typestate.finiteautomata.ITransition;
import typestate.finiteautomata.State;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;

public class AnalysisSeedWithSpecification extends IAnalysisSeed {

private final ClassSpecification spec;
Expand Down Expand Up @@ -182,9 +180,10 @@ private void computeTypestateErrorUnits() {

private void computeTypestateErrorsForEndOfObjectLifeTime() {
Table<Statement, Val, TransitionFunction> endPathOfPropagation = results.getObjectDestructingStatements();
Map<Statement, Set<SootMethod>> incompleteOperations = new HashMap<>();

for (Cell<Statement, Val, TransitionFunction> c : endPathOfPropagation.cellSet()) {
Set<SootMethod> expectedMethodsToBeCalled = Sets.newHashSet();
Set<SootMethod> expectedMethodsToBeCalled = new HashSet<>();

for (ITransition n : c.getValue().values()) {
if (n.to() == null) {
Expand All @@ -209,18 +208,89 @@ private void computeTypestateErrorsForEndOfObjectLifeTime() {
}

if (!expectedMethodsToBeCalled.isEmpty()) {
Statement s = c.getRowKey();
Val val = c.getColumnKey();
incompleteOperations.put(c.getRowKey(), expectedMethodsToBeCalled);
}
}

// No incomplete operations were found
if (incompleteOperations.entrySet().isEmpty()) {
return;
}

/* If there is only one incomplete operation, then there is only one dataflow path. Hence,
* the error can be reported directly.
*/
if (incompleteOperations.entrySet().size() == 1) {
Entry<Statement, Set<SootMethod>> entry = incompleteOperations.entrySet().iterator().next();
Statement s = entry.getKey();
Set<SootMethod> methodsToBeCalled = entry.getValue();

if (!s.getUnit().isPresent()) {
return;
}

if (s.getUnit().get() instanceof ThrowStmt) {
return;
}

IncompleteOperationError incompleteOperationError = new IncompleteOperationError(this, s, spec.getRule(), methodsToBeCalled);
this.addError(incompleteOperationError);
cryptoScanner.getAnalysisListener().reportError(this, incompleteOperationError);
}

/* Multiple incomplete operations were found. Depending on the dataflow paths, the
* errors are reported:
* 1) A dataflow path ends in an accepting state: No error is reported
* 2) A dataflow path does not end in an accepting state: Report the error on the last used statement on this path
*/
if (incompleteOperations.size() > 1) {
for (Entry<Statement, Set<SootMethod>> entry : incompleteOperations.entrySet()) {
Statement statement = entry.getKey();
Set<SootMethod> expectedMethodsToBeCalled = entry.getValue();

// Extract the called SootMethod from the statement
if (!statement.getUnit().isPresent()) {
continue;
}

if (statement.getUnit().get() instanceof ThrowStmt) {
continue;
}

if (!statement.getUnit().get().containsInvokeExpr()) {
continue;
}

if (!(s.getUnit().get() instanceof ThrowStmt)) {
IncompleteOperationError incompleteOperationError = new IncompleteOperationError(s, val, getSpec().getRule(), this, expectedMethodsToBeCalled);
this.addError(incompleteOperationError);
cryptoScanner.getAnalysisListener().reportError(this, incompleteOperationError);
// Only if the path does not end in an accepting state, the error should be reported
InvokeExpr invokeExpr = statement.getUnit().get().getInvokeExpr();
if (isMethodToAcceptingState(invokeExpr.getMethod())) {
continue;
}

IncompleteOperationError incompleteOperationError = new IncompleteOperationError(this, statement, spec.getRule(), expectedMethodsToBeCalled, true);
this.addError(incompleteOperationError);
cryptoScanner.getAnalysisListener().reportError(this, incompleteOperationError);
}
}
}

private boolean isMethodToAcceptingState(SootMethod method) {
Collection<TransitionEdge> transitions = spec.getRule().getUsagePattern().getAllTransitions();
Collection<CrySLMethod> methods = CrySLMethodToSootMethod.v().convert(method);

for (TransitionEdge edge : transitions) {
if (edge.getLabel().stream().noneMatch(e -> methods.contains(e))) {
continue;
}

if (edge.to().getAccepting()) {
return true;
}
}

return false;
}

private void typeStateChangeAtStatement(Statement curr, State stateNode) {
if (typeStateChange.put(curr, stateNode)) {
if (stateNode instanceof ReportingErrorStateNode) {
Expand Down
Loading

0 comments on commit c1f9ded

Please sign in to comment.