Search in sources :

Example 6 with ResultsInstance

use of com.ge.verdict.vdm.synthesis.ResultsInstance in project VERDICT by ge-high-assurance.

the class VerdictSynthesis method performSynthesisMultiple.

/**
 * Performs synthesis on multiple cyber requirements. This is the only version of synthesis that
 * should be used.
 *
 * @param tree the defense tree
 * @param factory the dleaf factory used to construct the defense tree
 * @param costModel the cost model
 * @param partialSolution whether we are using partial solutions
 * @param inputSat whether the input tree is satisfied
 * @param meritAssignment whether to perform merit assignment if the input is satisfied
 * @param dumpSmtLib whether to output the intermediate SMT-LIB file for debugging
 * @return the result, if successful
 */
public static Optional<ResultsInstance> performSynthesisMultiple(DTree tree, DLeaf.Factory factory, CostModel costModel, boolean partialSolution, boolean inputSat, boolean meritAssignment, boolean dumpSmtLib) {
    Context context = new Context();
    Optimize optimizer = context.mkOptimize();
    System.out.println("performSynthesisMultiple, configuration: partialSolution=" + partialSolution + ", inputSat=" + inputSat + ", meritAssignment=" + meritAssignment);
    Collection<ComponentDefense> compDefPairs = factory.allComponentDefensePairs();
    // Encode the logical structure of defense tree in MaxSMT
    // Encode cost(impl_defense_dal) >= the target cost (based on the severity of cyber req)
    // With merit assignment off and partial solution on, you will
    // subtract the cost of each DAL by the impl DAL cost, and use 0 if the result is negative.
    optimizer.Assert(tree.toZ3Multi(context));
    if (meritAssignment) {
        // set upper bounds at the current values, so that no upgrades are reported
        // Encode component_defense_var <= the the implemented DAL cost
        optimizer.Assert(context.mkAnd(compDefPairs.stream().map(pair -> context.mkLe(pair.toZ3Multi(context), DLeaf.fractionToZ3(pair.dalToRawCost(pair.implDal), context))).collect(Collectors.toList()).toArray(new BoolExpr[] {})));
    }
    // Make all component-defense var >= Cost(DAL(0));
    optimizer.Assert(// to DAL, then this can be changed to the minimum of all costs.
    context.mkAnd(compDefPairs.stream().map(pair -> context.mkGe(pair.toZ3Multi(context), DLeaf.fractionToZ3(pair.dalToRawCost(0), context))).collect(Collectors.toList()).toArray(new BoolExpr[] {})));
    // Encode objective function: the sum of all component-defense vars
    if (compDefPairs.isEmpty()) {
        optimizer.MkMinimize(context.mkInt(0));
    } else {
        optimizer.MkMinimize(context.mkAdd(compDefPairs.stream().map(pair -> pair.toZ3Multi(context)).collect(Collectors.toList()).toArray(new ArithExpr[] {})));
    }
    if (dumpSmtLib) {
        try {
            // this dumps the file in the working directory, i.e. where the process was started
            // from
            PrintWriter writer = new PrintWriter("verdict-synthesis-dump.smtlib", "UTF-8");
            writer.println(optimizer.toString());
            writer.flush();
            writer.close();
        } catch (FileNotFoundException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
    if (optimizer.Check().equals(Status.SATISFIABLE)) {
        List<ResultsInstance.Item> items = new ArrayList<>();
        Fraction totalInputCost = new Fraction(0), totalOutputCost = new Fraction(0);
        Model model = optimizer.getModel();
        for (ComponentDefense pair : compDefPairs) {
            // get the value in the model
            RatNum expr = (RatNum) model.eval(pair.toZ3Multi(context), true);
            Fraction rawCost = new Fraction(expr.getNumerator().getInt(), expr.getDenominator().getInt());
            // convert back to DAL (the value in the model is cost rather than DAL)
            int dal = pair.rawCostToDal(rawCost);
            // but we don't trust the cost obtained directly from the model.
            // instead, we re-calculate using the cost model because it is less prone to failure
            // The cost of implemented DAL
            Fraction inputCost = costModel.cost(pair.defenseProperty, pair.component, pair.implDal);
            // The cost of output DAL from SMT
            Fraction outputCost = costModel.cost(pair.defenseProperty, pair.component, dal);
            // keep track of total cost
            totalInputCost = totalInputCost.add(inputCost);
            totalOutputCost = totalOutputCost.add(outputCost);
            items.add(new ResultsInstance.Item(pair.component, pair.defenseProperty, pair.implDal, dal, inputCost, outputCost));
        }
        return Optional.of(new ResultsInstance(partialSolution, meritAssignment, inputSat, totalInputCost, totalOutputCost, items));
    } else {
        System.err.println("Synthesis: SMT not satisfiable, perhaps there are unmitigatable attacks");
        return Optional.empty();
    }
}
Also used : Context(com.microsoft.z3.Context) FileNotFoundException(java.io.FileNotFoundException) ArrayList(java.util.ArrayList) UnsupportedEncodingException(java.io.UnsupportedEncodingException) Fraction(org.apache.commons.math3.fraction.Fraction) ResultsInstance(com.ge.verdict.vdm.synthesis.ResultsInstance) ComponentDefense(com.ge.verdict.synthesis.dtree.DLeaf.ComponentDefense) Model(com.microsoft.z3.Model) RatNum(com.microsoft.z3.RatNum) Optimize(com.microsoft.z3.Optimize) PrintWriter(java.io.PrintWriter)

Example 7 with ResultsInstance

use of com.ge.verdict.vdm.synthesis.ResultsInstance in project VERDICT by ge-high-assurance.

the class MBASSynthesisReport method report.

public static void report(IProject project, File projectDir, File xmlFile, IWorkbenchWindow window) {
    try {
        ResultsInstance results = ResultsInstance.fromFile(xmlFile);
        window.getShell().getDisplay().asyncExec(() -> {
            try {
                ResultsPageUtil.closePages();
                MBASSynthesisResultsView.results = results;
                MBASSynthesisResultsView.applyToProject = () -> SynthesisAadlWriter.perform(project, projectDir, results);
                window.getActivePage().showView(MBASSynthesisResultsView.ID);
            } catch (PartInitException e) {
                e.printStackTrace();
            }
        });
    } catch (SAXException | IOException | ParserConfigurationException e) {
        e.printStackTrace();
    }
}
Also used : PartInitException(org.eclipse.ui.PartInitException) IOException(java.io.IOException) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) ResultsInstance(com.ge.verdict.vdm.synthesis.ResultsInstance) SAXException(org.xml.sax.SAXException)

Example 8 with ResultsInstance

use of com.ge.verdict.vdm.synthesis.ResultsInstance in project VERDICT by ge-high-assurance.

the class App method runMbasSynthesis.

/**
 * Run MBAS Synthesis with CSV input files
 *
 * @param vdmPath VDM input file for synthesis
 * @param modelName Name of model
 * @param stemDir output directory for STEM input files
 * @param soteriaDir output directory for Soteria++ input files
 * @throws VerdictRunException
 */
public static void runMbasSynthesis(String vdmPath, String modelName, String stemProjectDir, String debugDir, String soteriaPpBin, boolean cyberInference, boolean safetyInference, boolean partialSolution, String costModelPath, String outputPath) throws VerdictRunException {
    String stemCsvDir = (new File(stemProjectDir, "CSVData")).getAbsolutePath();
    String stemOutputDir = (new File(stemProjectDir, "Output")).getAbsolutePath();
    String stemGraphsDir = (new File(stemProjectDir, "Graphs")).getAbsolutePath();
    String stemSadlFile = (new File(stemProjectDir, "Run.sadl")).getAbsolutePath();
    File soteriaOutputDir = new File(stemOutputDir, "Soteria_Output");
    soteriaOutputDir.mkdirs();
    String soteriaPpOutputDir = soteriaOutputDir.getAbsolutePath();
    checkFile(stemCsvDir, true, true, true, false, null);
    checkFile(stemOutputDir, true, true, true, false, null);
    checkFile(stemGraphsDir, true, true, true, false, null);
    checkFile(stemSadlFile, true, false, false, false, null);
    checkFile(soteriaPpOutputDir, true, true, true, false, null);
    checkFile(soteriaPpBin, true, false, false, true, null);
    checkFile(vdmPath, true, false, false, false, "xml");
    checkFile(costModelPath, true, false, false, false, "xml");
    checkFile(outputPath, false, false, true, false, "xml");
    deleteDirectoryContents(stemGraphsDir);
    deleteDirectoryContents(soteriaPpOutputDir);
    if (debugDir != null) {
        logHeader("DEBUGGING XML OUTPUT");
    }
    try {
        // Copy Soteria++ pngs
        for (String soteria_png : soteria_pngs) {
            Binary.copyResource("soteria_pngs/" + soteria_png + ".png", new File(soteriaPpOutputDir, soteria_png + ".png"), false);
        }
    } catch (Binary.ExecutionException e) {
        throw new VerdictRunException("Failed to copy Soteria++ pngs", e);
    }
    logHeader("STEM");
    log("STEM project directory: " + stemProjectDir);
    log("STEM output directory: " + stemOutputDir);
    log("STEM graphs directory: " + stemGraphsDir);
    log("STEM is running. Please be patient...");
    VerdictStem stemRunner = new VerdictStem();
    Metrics.timer("Timer.mbas.stem", "model", modelName).record(() -> stemRunner.runStem(new File(stemProjectDir), new File(stemOutputDir), new File(stemGraphsDir)));
    log("STEM finished!");
    logHeader("Synthesis");
    try {
        Timer.Sample sample = Timer.start(Metrics.globalRegistry);
        CostModel costModel = new CostModel(new File(costModelPath));
        AttackDefenseCollector collector = new AttackDefenseCollector(new File(vdmPath), new File(stemOutputDir), cyberInference);
        List<AttackDefenseCollector.Result> results = collector.perform();
        boolean sat = results.stream().allMatch(result -> Prob.lte(result.prob, result.cyberReq.getSeverity()));
        boolean performMeritAssignment = partialSolution && sat;
        DLeaf.Factory factory = new DLeaf.Factory();
        DTree dtree = DTreeConstructor.construct(results, costModel, partialSolution, performMeritAssignment, factory);
        Optional<ResultsInstance> selected = VerdictSynthesis.performSynthesisMultiple(dtree, factory, costModel, partialSolution, sat, performMeritAssignment, false);
        if (selected.isPresent()) {
            if (performMeritAssignment) {
                ResultsInstance withExtraDefProps = VerdictSynthesis.addExtraImplDefenses(selected.get(), collector.getImplDal(), costModel);
                withExtraDefProps.toFileXml(new File(outputPath));
            } else {
                selected.get().toFileXml(new File(outputPath));
            }
            log("Synthesis results output to " + outputPath);
        } else {
            logError("Synthesis failed");
        }
        sample.stop(Metrics.timer("Timer.mbas.synthesis", "model", modelName));
    } catch (IOException | MalformedInputException e) {
        throw new VerdictRunException("Failed to execute synthesis", e);
    }
    logHeader("Finished");
}
Also used : DLeaf(com.ge.verdict.synthesis.dtree.DLeaf) DTree(com.ge.verdict.synthesis.dtree.DTree) VerdictStem(com.ge.verdict.stem.VerdictStem) CostModel(com.ge.verdict.synthesis.CostModel) AttackDefenseCollector(com.ge.verdict.attackdefensecollector.AttackDefenseCollector) IOException(java.io.IOException) ResultsInstance(com.ge.verdict.vdm.synthesis.ResultsInstance) Timer(io.micrometer.core.instrument.Timer) MalformedInputException(com.ge.verdict.attackdefensecollector.CSVFile.MalformedInputException) File(java.io.File)

Example 9 with ResultsInstance

use of com.ge.verdict.vdm.synthesis.ResultsInstance in project VERDICT by ge-high-assurance.

the class VerdictSynthesisTest method biggerMeritAssignmentTest.

@Test
public void biggerMeritAssignmentTest() {
    CostModel costModel = new CostModel(new File(getClass().getResource("meritCosts.xml").getPath()));
    SystemModel system = new SystemModel("C1");
    Attack attack1 = new Attack(system.getAttackable(), "A1", "An attack", Prob.certain(), CIA.I);
    Defense defense1 = new Defense(attack1);
    defense1.addDefenseClause(Collections.singletonList(new Defense.DefenseLeaf("D1", Optional.of(new com.ge.verdict.attackdefensecollector.Pair<>("D1", 1)))));
    Attack attack2 = new Attack(system.getAttackable(), "A2", "An attack", Prob.certain(), CIA.I);
    Defense defense2 = new Defense(attack2);
    defense2.addDefenseClause(Collections.singletonList(new Defense.DefenseLeaf("D2", Optional.of(new com.ge.verdict.attackdefensecollector.Pair<>("D2", 1)))));
    ADTree adtree = new ADAnd(new ADOr(new ADAnd(new ADNot(defense1), attack1)), new ADOr(new ADAnd(new ADNot(defense2), attack2)));
    DLeaf.Factory factory = new DLeaf.Factory();
    List<AttackDefenseCollector.Result> results = Arrays.asList(new AttackDefenseCollector.Result(system, new CyberReq("req1", "mission1", 1, "port1", CIA.I), adtree, Prob.certain()));
    Optional<ResultsInstance> result = VerdictSynthesis.performSynthesisMultiple(DTreeConstructor.construct(results, costModel, true, true, factory), factory, costModel, true, true, true, false);
    Assertions.assertThat(result.isPresent());
    Assertions.assertThat(result.get().items.size()).isEqualTo(2);
    Assertions.assertThat(result.get().outputCost).isEqualTo(new Fraction(1));
}
Also used : DLeaf(com.ge.verdict.synthesis.dtree.DLeaf) ADNot(com.ge.verdict.attackdefensecollector.adtree.ADNot) CyberReq(com.ge.verdict.attackdefensecollector.model.CyberReq) ADAnd(com.ge.verdict.attackdefensecollector.adtree.ADAnd) AttackDefenseCollector(com.ge.verdict.attackdefensecollector.AttackDefenseCollector) Fraction(org.apache.commons.math3.fraction.Fraction) Attack(com.ge.verdict.attackdefensecollector.adtree.Attack) ResultsInstance(com.ge.verdict.vdm.synthesis.ResultsInstance) Defense(com.ge.verdict.attackdefensecollector.adtree.Defense) ComponentDefense(com.ge.verdict.synthesis.dtree.DLeaf.ComponentDefense) ADTree(com.ge.verdict.attackdefensecollector.adtree.ADTree) SystemModel(com.ge.verdict.attackdefensecollector.model.SystemModel) ADOr(com.ge.verdict.attackdefensecollector.adtree.ADOr) File(java.io.File) Pair(com.ge.verdict.synthesis.util.Pair) Test(org.junit.Test)

Aggregations

ResultsInstance (com.ge.verdict.vdm.synthesis.ResultsInstance)9 DLeaf (com.ge.verdict.synthesis.dtree.DLeaf)6 Fraction (org.apache.commons.math3.fraction.Fraction)6 DTree (com.ge.verdict.synthesis.dtree.DTree)5 ADTree (com.ge.verdict.attackdefensecollector.adtree.ADTree)4 Test (org.junit.Test)4 ComponentDefense (com.ge.verdict.synthesis.dtree.DLeaf.ComponentDefense)3 File (java.io.File)3 IOException (java.io.IOException)3 ArrayList (java.util.ArrayList)3 AttackDefenseCollector (com.ge.verdict.attackdefensecollector.AttackDefenseCollector)2 ADAnd (com.ge.verdict.attackdefensecollector.adtree.ADAnd)2 ADOr (com.ge.verdict.attackdefensecollector.adtree.ADOr)2 Pair (com.ge.verdict.synthesis.util.Pair)2 Context (com.microsoft.z3.Context)2 Model (com.microsoft.z3.Model)2 Optimize (com.microsoft.z3.Optimize)2 RatNum (com.microsoft.z3.RatNum)2 FileNotFoundException (java.io.FileNotFoundException)2 PrintWriter (java.io.PrintWriter)2