diff --git a/CryptoAnalysis/src/main/java/crypto/HeadlessCryptoScanner.java b/CryptoAnalysis/src/main/java/crypto/HeadlessCryptoScanner.java index b29e01ee1..d3bd5888f 100644 --- a/CryptoAnalysis/src/main/java/crypto/HeadlessCryptoScanner.java +++ b/CryptoAnalysis/src/main/java/crypto/HeadlessCryptoScanner.java @@ -85,14 +85,13 @@ protected String applicationClassPath() { @Override protected List getRules() { - // TODO: Somehow optimize the rule getting because this has many code duplicates for no reason. switch(settings.getRulesetPathType()) { case DIR: try { rules.addAll(CrySLRuleReader.readFromDirectory(new File(settings.getRulesetPathDir()))); rulesetRootPath = settings.getRulesetPathDir().substring(0, settings.getRulesetPathDir().lastIndexOf(File.separator)); } catch (CryptoAnalysisException e) { - LOGGER.error("Error happened when getting the CrySL rules from the specified directory: "+settings.getRulesetPathDir(), e); + LOGGER.error("Error happened when getting the CrySL rules from the specified directory: " + settings.getRulesetPathDir(), e); } break; case ZIP: @@ -100,7 +99,7 @@ protected List getRules() { rules.addAll(CrySLRuleReader.readFromZipFile(new File(settings.getRulesetPathZip()))); rulesetRootPath = settings.getRulesetPathZip().substring(0, settings.getRulesetPathZip().lastIndexOf(File.separator)); } catch (CryptoAnalysisException e) { - LOGGER.error("Error happened when getting the CrySL rules from the specified file: "+settings.getRulesetPathZip(), e); + LOGGER.error("Error happened when getting the CrySL rules from the specified file: " + settings.getRulesetPathZip(), e); } break; default: @@ -274,13 +273,13 @@ public Debugger debugger(IDEALSeedSolver rules.clear(); switch(settings.getRulesetPathType()) { case DIR: - rules.addAll(providerDetection.chooseRules(rulesetRootPath+File.separator+detectedProvider)); + rules.addAll(providerDetection.chooseRules(rulesetRootPath + File.separator + detectedProvider)); break; case ZIP: - rules.addAll(providerDetection.chooseRulesZip(rulesetRootPath+File.separator+detectedProvider+".zip")); + rules.addAll(providerDetection.chooseRulesZip(rulesetRootPath + File.separator + detectedProvider + ".zip")); break; default: - rules.addAll(providerDetection.chooseRules(rulesetRootPath+File.separator+detectedProvider)); + rules.addAll(providerDetection.chooseRules(rulesetRootPath + File.separator + detectedProvider)); } } } diff --git a/CryptoAnalysis/src/main/java/crypto/analysis/CrySLRulesetSelector.java b/CryptoAnalysis/src/main/java/crypto/analysis/CrySLRulesetSelector.java index 35a3c1089..581ac12a2 100644 --- a/CryptoAnalysis/src/main/java/crypto/analysis/CrySLRulesetSelector.java +++ b/CryptoAnalysis/src/main/java/crypto/analysis/CrySLRulesetSelector.java @@ -1,6 +1,7 @@ package crypto.analysis; import java.io.File; +import java.util.Arrays; import java.util.List; import org.slf4j.Logger; @@ -88,14 +89,10 @@ public static List makeFromRulesetString(String rulesBasePath, RuleFo } private static List getRulesset(String rulesBasePath, RuleFormat ruleFormat, Ruleset s) throws CryptoAnalysisException { - List rules = Lists.newArrayList(); File[] listFiles = new File(rulesBasePath + s + "/").listFiles(); - for (File file : listFiles) { - CrySLRule rule = CrySLRuleReader.readFromSourceFile(file); - if(rule != null) { - rules.add(rule); - } - } + List files = Arrays.asList(listFiles); + + List rules = CrySLRuleReader.readFromSourceFiles(files); if (rules.isEmpty()) { throw new CryptoAnalysisException("No CrySL rules found in " + rulesBasePath+s+"/"); @@ -116,10 +113,12 @@ private static List getRulesset(String rulesBasePath, RuleFormat rule */ public static CrySLRule makeSingleRule(String rulesBasePath, RuleFormat ruleFormat, Ruleset ruleset, String rulename) throws CryptoAnalysisException { File file = new File(rulesBasePath + "/" + ruleset + "/" + rulename + RuleFormat.SOURCE); + if (file.exists() && file.isFile()) { CrySLRule rule = CrySLRuleReader.readFromSourceFile(file); + if(rule != null) { - return rule; + return rule; } else { throw new CryptoAnalysisException("CrySL rule couldn't created from path " + file.getAbsolutePath()); } diff --git a/CryptoAnalysis/src/main/java/crypto/cryslhandler/CrySLModelReader.java b/CryptoAnalysis/src/main/java/crypto/cryslhandler/CrySLModelReader.java index a836852ed..754f2c4ce 100644 --- a/CryptoAnalysis/src/main/java/crypto/cryslhandler/CrySLModelReader.java +++ b/CryptoAnalysis/src/main/java/crypto/cryslhandler/CrySLModelReader.java @@ -1,36 +1,31 @@ package crypto.cryslhandler; import java.io.File; -import java.io.InputStream; import java.io.IOException; - +import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; -import java.util.Arrays; 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; -import com.google.common.base.CharMatcher; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.google.inject.Injector; - import org.apache.commons.lang3.NotImplementedException; - import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.xtext.common.types.access.impl.ClasspathTypeProvider; -import org.eclipse.xtext.diagnostics.Severity; +import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.xtext.common.types.JvmDeclaredType; import org.eclipse.xtext.common.types.JvmTypeReference; -import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.common.types.access.impl.ClasspathTypeProvider; +import org.eclipse.xtext.diagnostics.Severity; +import org.eclipse.xtext.linking.lazy.LazyLinkingResource; import org.eclipse.xtext.resource.XtextResourceSet; import org.eclipse.xtext.util.CancelIndicator; import org.eclipse.xtext.validation.CheckMode; @@ -39,6 +34,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.CharMatcher; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.google.inject.Injector; + import crypto.exceptions.CryptoAnalysisException; import crypto.interfaces.ICrySLPredicateParameter; import crypto.interfaces.ISLConstraint; @@ -59,7 +59,7 @@ import crypto.rules.StateMachineGraph; import crypto.rules.StateNode; import crypto.rules.TransitionEdge; - +import de.darmstadt.tu.crossing.CrySLStandaloneSetup; import de.darmstadt.tu.crossing.crySL.AlternativeRequiredPredicates; import de.darmstadt.tu.crossing.crySL.BuiltinPredicate; import de.darmstadt.tu.crossing.crySL.ConditionalPredicate; @@ -87,7 +87,6 @@ import de.darmstadt.tu.crossing.crySL.PredicateParameter; import de.darmstadt.tu.crossing.crySL.RequiredPredicate; import de.darmstadt.tu.crossing.crySL.RequiresBlock; -import de.darmstadt.tu.crossing.CrySLStandaloneSetup; import de.darmstadt.tu.crossing.crySL.ThisPredicateParameter; import de.darmstadt.tu.crossing.crySL.TimedPredicate; import de.darmstadt.tu.crossing.crySL.WildcardPredicateParameter; @@ -106,12 +105,6 @@ public class CrySLModelReader { private static final String NULL = "null"; private static final String UNDERSCORE = "_"; - /** - * For some reason, xtext is not able to resolve a call to 'getEncoded()' for the class java.security.key - * and its subclasses. In these cases, we have to manually resolve the call - */ - private static final Set buggedKeyRules = new HashSet<>(Arrays.asList("java.security.Key", "javax.crypto.SecretKey", "java.security.PublicKey", "java.security.PrivateKey")); - /** * Creates a CrySLModelReader * @throws MalformedURLException If there is a problem with the URL @@ -131,7 +124,41 @@ public CrySLModelReader() throws MalformedURLException { URLClassLoader ucl = new URLClassLoader(classpath); this.resourceSet.setClasspathURIContext(new URLClassLoader(classpath)); new ClasspathTypeProvider(ucl, this.resourceSet, null, null); - this.resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE); + } + + /** + * Read the crysl rules from all given files. + * + * @param files a list of files to read from + * @return the list with the parsed CrySLRules + * @throws CryptoAnalysisException If a file cannot be read or there is a problem with a rule + */ + public List readRulesFromFiles(List files) throws CryptoAnalysisException { + Map ruleMap = new HashMap(); + + for (File file : files) { + resourceSet.getResource(URI.createFileURI(file.getAbsolutePath()), true); + } + + EcoreUtil.resolveAll(resourceSet); + + for (Resource resource : resourceSet.getResources()) { + if (resource == null) { + continue; + } + + if (!(resource instanceof LazyLinkingResource)) { + continue; + } + + CrySLRule rule = createRuleFromResource(resource); + + if (!ruleMap.containsKey(rule.getClassName())) { + ruleMap.put(rule.getClassName(), rule); + } + } + + return new ArrayList<>(ruleMap.values()); } /** @@ -219,20 +246,13 @@ private CrySLRule createRuleFromResource(Resource resource) throws CryptoAnalysi throw new CryptoAnalysisException("Internal error creating a CrySL rule: 'resource parameter was null'."); } - String currentClass = ((Domainmodel)resource.getContents().get(0)).getJavaType().getQualifiedName(); - if (runValidator(resource, Severity.WARNING)) { - if (buggedKeyRules.contains(currentClass)) { - LOGGER.info("Class " + currentClass + " is of type java.security.key. The call to 'getEncoded()' will be resolved manually."); - } else { - throw new CryptoAnalysisException("Skipping rule since it contains errors: " + resource.getURI()); - } + throw new CryptoAnalysisException("Skipping rule since it contains errors: " + resource.getURI()); } try { return createRuleFromDomainmodel((Domainmodel) resource.getContents().get(0)); } catch (Exception e) { - e.printStackTrace(); throw new CryptoAnalysisException("An error occured while reading the rule " + resource.getURI(), e); } } @@ -616,10 +636,6 @@ private ISLConstraint getBuiltinPredicate(BuiltinPredicate builtinPredicate) { } return new CrySLPredicate(null, name, parameters, negated); } - - public static Set getBuggedKeyRules() { - return buggedKeyRules; - } public static String filterQuotes(final String dirty) { return CharMatcher.anyOf("\"").removeFrom(dirty); diff --git a/CryptoAnalysis/src/main/java/crypto/cryslhandler/StateMachineGraphBuilder.java b/CryptoAnalysis/src/main/java/crypto/cryslhandler/StateMachineGraphBuilder.java index e0a671939..b5e06d510 100644 --- a/CryptoAnalysis/src/main/java/crypto/cryslhandler/StateMachineGraphBuilder.java +++ b/CryptoAnalysis/src/main/java/crypto/cryslhandler/StateMachineGraphBuilder.java @@ -205,27 +205,8 @@ private SubStateMachine buildSubSMG(final Order order, final Set star StateNode node = this.result.createNewNode(); List label = CrySLReaderUtils.resolveEventToCryslMethods(event); - /** - * In some scenarios, xtext is not able to resolve the JVMExecutable 'getEncoded()' from the - * class java.security.Key or its subclasses. In these cases, xtext defaults to the constructor. - * However, these classes have no constructors, since they are interfaces. To deal with the problem, - * we manually change the constructor call to the 'getEncoded()' call. - */ - List updatedLabels = new ArrayList<>(label); - - for (CrySLMethod method : label) { - if (CrySLModelReader.getBuggedKeyRules().contains(method.getMethodName())) { - String updatedLabel = method.getMethodName() + ".getEncoded"; - CrySLMethod updatedMethod = new CrySLMethod(updatedLabel, method.getParameters(), method.getRetObject()); - - updatedLabels.add(updatedMethod); - } else { - updatedLabels.add(method); - } - } - for (StateNode startNode : startNodes) { - this.result.createNewEdge(updatedLabels, startNode, node); + this.result.createNewEdge(label, startNode, node); } return new SubStateMachine(node, node); diff --git a/CryptoAnalysis/src/main/java/crypto/rules/CrySLRuleReader.java b/CryptoAnalysis/src/main/java/crypto/rules/CrySLRuleReader.java index 31cda0373..c5d0ee350 100644 --- a/CryptoAnalysis/src/main/java/crypto/rules/CrySLRuleReader.java +++ b/CryptoAnalysis/src/main/java/crypto/rules/CrySLRuleReader.java @@ -23,14 +23,10 @@ public class CrySLRuleReader { private static CrySLModelReader csmr; private static CrySLModelReader getReader(){ - if (csmr == null) - { - try { - csmr = new CrySLModelReader(); - } - catch (MalformedURLException e){ - e.printStackTrace(); - } + try { + csmr = new CrySLModelReader(); + } catch (MalformedURLException e) { + e.printStackTrace(); } return csmr; } @@ -45,6 +41,17 @@ private static CrySLModelReader getReader(){ public static CrySLRule readFromSourceFile(File file) throws CryptoAnalysisException { return getReader().readRule(file); } + + /** + * Returns a list with {@link CrySLRule} objects from the files. + * + * @param files The files to read from + * @return The list with {@link CrySLRule} objects + * @throws CryptoAnalysisException If a file could not get processed to a {@link CrySLRule} + */ + public static List readFromSourceFiles(List files) throws CryptoAnalysisException { + return getReader().readRulesFromFiles(files); + } /** * Returns a {@link List} of {@link CrySLRule} objects read from a directory @@ -68,26 +75,14 @@ public static List readFromDirectory(File directory) throws CryptoAna * @throws CryptoAnalysisException Throws when a file could not get processed to a {@link CrySLRule} */ public static List readFromDirectory(File directory, boolean recursive) throws CryptoAnalysisException { - Map ruleMap = new HashMap(); - if (!directory.exists() || !directory.isDirectory()) throw new CryptoAnalysisException("The specified path is not a directory " + directory.getAbsolutePath()); - List cryptSLFiles = new ArrayList<>(); - findCryptSLFiles(directory, recursive, cryptSLFiles); + List crySLFiles = new ArrayList<>(); + findCrySLFiles(directory, recursive, crySLFiles); CrySLModelReader reader = getReader(); - for (File file : cryptSLFiles) { - CrySLRule rule = reader.readRule(file); - - if(rule != null) { - if(!ruleMap.containsKey(rule.getClassName())) { - ruleMap.put(rule.getClassName(), rule); - } - } - } - - return new ArrayList<>(ruleMap.values()); + return reader.readRulesFromFiles(crySLFiles); } /** @@ -122,19 +117,17 @@ public static List readFromZipFile(File file) throws CryptoAnalysisEx return new ArrayList<>(ruleMap.values()); } - private static void findCryptSLFiles(File directory, boolean recursive, Collection resultCollection) { - for (File file: directory.listFiles()) - { + private static void findCrySLFiles(File directory, boolean recursive, Collection resultCollection) { + for (File file: directory.listFiles()) { if (file.isFile() && file.getName().endsWith(CrySLModelReader.cryslFileEnding)) resultCollection.add(file); if (recursive && file.isDirectory()) - findCryptSLFiles(file, recursive, resultCollection); + findCrySLFiles(file, recursive, resultCollection); } } - private static CrySLRule getCrySLRuleFromZipEntry(ZipEntry entry, ZipFile zip, File zipFile) throws CryptoAnalysisException - { + private static CrySLRule getCrySLRuleFromZipEntry(ZipEntry entry, ZipFile zip, File zipFile) throws CryptoAnalysisException { if (entry.isDirectory() || !entry.getName().endsWith(CrySLModelReader.cryslFileEnding)) throw new CryptoAnalysisException("ZIP entry is a directory or not a CrySL file"); diff --git a/CryptoAnalysis/src/test/java/tests/crysl/ZipCrySLTest.java b/CryptoAnalysis/src/test/java/tests/crysl/ZipCrySLTest.java index 56df595e5..88e51c522 100644 --- a/CryptoAnalysis/src/test/java/tests/crysl/ZipCrySLTest.java +++ b/CryptoAnalysis/src/test/java/tests/crysl/ZipCrySLTest.java @@ -16,7 +16,7 @@ public class ZipCrySLTest { private static final String emptyZipFilePath = "src/test/resources/crySL/empty.zip"; - private static final String jcaRulesetZipFilePath = "src/test/resources/crySL/JavaCryptographicArchitecture-1.5.1-ruleset.zip"; + private static final String jcaRulesetZipFilePath = "src/test/resources/crySL/JavaCryptographicArchitecture-3.0.1-ruleset.zip"; private static final String multipleRulesetZipFilePath = "src/test/resources/crySL/Multiple-rulesets.zip"; private static final String junkRuleSet = "src/test/resources/crySL/rulesetWithJunk.zip"; @@ -61,7 +61,7 @@ public void TestFileNoCrypSLFiles() throws CryptoAnalysisException { public void TestFileContainsMultipleRulesets() throws CryptoAnalysisException { File zipFile = new File(multipleRulesetZipFilePath); Collection rules = CrySLRuleReader.readFromZipFile(zipFile); - Assert.assertEquals(107, rules.size()); + Assert.assertEquals(108, rules.size()); } @Test diff --git a/CryptoAnalysis/src/test/java/tests/headless/AbstractHeadlessTest.java b/CryptoAnalysis/src/test/java/tests/headless/AbstractHeadlessTest.java index d9e07d2e2..1f67da297 100644 --- a/CryptoAnalysis/src/test/java/tests/headless/AbstractHeadlessTest.java +++ b/CryptoAnalysis/src/test/java/tests/headless/AbstractHeadlessTest.java @@ -5,15 +5,16 @@ import java.util.HashSet; import java.util.List; import java.util.Set; + import org.junit.Before; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.HashBasedTable; -import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import com.google.common.collect.Table; import com.google.common.collect.Table.Cell; + import boomerang.BackwardQuery; import boomerang.Query; import boomerang.jimple.Statement; @@ -103,12 +104,11 @@ protected String sootClassPath() { @Override protected List getRules() { try { - List rules = Lists.newArrayList(); - rules = CrySLRulesetSelector.makeFromRuleset(IDEALCrossingTestingFramework.RULES_BASE_DIR, ruleFormat, ruleset); + List rules= CrySLRulesetSelector.makeFromRuleset(IDEALCrossingTestingFramework.RULES_BASE_DIR, ruleFormat, ruleset); HeadlessCryptoScanner.setRules(rules); return rules; } catch (CryptoAnalysisException e) { - LOGGER.error("Error happened when getting the CrySL rules from the specified directory: "+IDEALCrossingTestingFramework.RULES_BASE_DIR, e); + LOGGER.error("Error happened when getting the CrySL rules from the specified directory: " + IDEALCrossingTestingFramework.RULES_BASE_DIR, e); } return null; } @@ -172,14 +172,10 @@ public void onSeedFinished(IAnalysisSeed seed, ForwardBoomerangResults> existingPredicates, Table> expectedPredicates, - Table> missingPredicates) { - - } + Table> missingPredicates) {} @Override - public void discoveredSeed(IAnalysisSeed curr) { - - } + public void discoveredSeed(IAnalysisSeed curr) {} @Override public void collectedValues(AnalysisSeedWithSpecification seed, Multimap collectedValues) {} @@ -194,9 +190,7 @@ public void seedStarted(IAnalysisSeed analysisSeedWithSpecification) {} public void boomerangQueryStarted(Query seed, BackwardQuery q) {} @Override - public void boomerangQueryFinished(Query seed, BackwardQuery q) { - - } + public void boomerangQueryFinished(Query seed, BackwardQuery q) {} @Override public void beforePredicateCheck(AnalysisSeedWithSpecification analysisSeedWithSpecification) {} @@ -217,16 +211,10 @@ public void afterConstraintCheck(AnalysisSeedWithSpecification analysisSeedWithS public void afterAnalysis() {} @Override - public void onSecureObjectFound(IAnalysisSeed analysisObject) { - // TODO Auto-generated method stub - - } + public void onSecureObjectFound(IAnalysisSeed analysisObject) {} @Override - public void addProgress(int processedSeeds, int workListsize) { - // TODO Auto-generated method stub - - } + public void addProgress(int processedSeeds, int workListsize) {} }; } diff --git a/CryptoAnalysis/src/test/resources/crySL/JavaCryptographicArchitecture-1.5.1-ruleset.zip b/CryptoAnalysis/src/test/resources/crySL/JavaCryptographicArchitecture-1.5.1-ruleset.zip deleted file mode 100644 index ef56a677f..000000000 Binary files a/CryptoAnalysis/src/test/resources/crySL/JavaCryptographicArchitecture-1.5.1-ruleset.zip and /dev/null differ diff --git a/CryptoAnalysis/src/test/resources/crySL/Multiple-rulesets.zip b/CryptoAnalysis/src/test/resources/crySL/Multiple-rulesets.zip index 014f15a07..1eb076c36 100644 Binary files a/CryptoAnalysis/src/test/resources/crySL/Multiple-rulesets.zip and b/CryptoAnalysis/src/test/resources/crySL/Multiple-rulesets.zip differ