samva 2.0.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. samva/__init__.py +15 -0
  2. samva/__main__.py +7 -0
  3. samva/cli.py +167 -0
  4. samva/commands/__init__.py +6 -0
  5. samva/commands/commands_common.py +107 -0
  6. samva/commands/commands_evals.py +92 -0
  7. samva/commands/commands_plot.py +68 -0
  8. samva/commands/commands_stm32.py +385 -0
  9. samva/commands/cv32e40p.py +24 -0
  10. samva/commands/debugger.py +37 -0
  11. samva/commands/evaluate.py +186 -0
  12. samva/commands/measure_cycles.py +43 -0
  13. samva/commands/stm32.py +18 -0
  14. samva/commands/test_dynprog.py +103 -0
  15. samva/commands/traitor.py +281 -0
  16. samva/core/__init__.py +20 -0
  17. samva/core/common/__init__.py +41 -0
  18. samva/core/common/analyse_configuration.py +71 -0
  19. samva/core/common/analysis_utils.py +56 -0
  20. samva/core/common/attack_path.py +175 -0
  21. samva/core/common/configuration.py +163 -0
  22. samva/core/common/instruction_typing.py +149 -0
  23. samva/core/common/log_utils.py +199 -0
  24. samva/core/common/timeout.py +28 -0
  25. samva/core/common/try_import.py +12 -0
  26. samva/core/fault_positioning/__init__.py +22 -0
  27. samva/core/fault_positioning/base_pass.py +75 -0
  28. samva/core/fault_positioning/essential_pass/__init__.py +24 -0
  29. samva/core/fault_positioning/essential_pass/postvalidation_trim.py +51 -0
  30. samva/core/fault_positioning/essential_pass/prevalidation_common.py +132 -0
  31. samva/core/fault_positioning/essential_pass/validation_dynprog.py +1623 -0
  32. samva/core/fault_positioning/essential_pass/validation_true_nop.py +31 -0
  33. samva/core/fault_positioning/extra_pass/__init__.py +14 -0
  34. samva/core/fault_positioning/extra_pass/replay_passes.py +120 -0
  35. samva/core/fault_positioning/fault_positioner.py +166 -0
  36. samva/core/model/__init__.py +19 -0
  37. samva/core/model/db/__init__.py +35 -0
  38. samva/core/model/db/arch.py +348 -0
  39. samva/core/model/db/basic_block.py +48 -0
  40. samva/core/model/db/flow_type.py +37 -0
  41. samva/core/model/db/function.py +68 -0
  42. samva/core/model/db/instruction.py +137 -0
  43. samva/core/model/db/pcode.py +232 -0
  44. samva/core/model/db/section.py +65 -0
  45. samva/core/model/db/symbol.py +42 -0
  46. samva/core/model/essential_pass/__init__.py +23 -0
  47. samva/core/model/essential_pass/dead_code_elimination.py +51 -0
  48. samva/core/model/essential_pass/find_first_last_nodes.py +54 -0
  49. samva/core/model/essential_pass/fix_isolated_nodes.py +51 -0
  50. samva/core/model/essential_pass/forced_types.py +59 -0
  51. samva/core/model/essential_pass/prune_cfg.py +47 -0
  52. samva/core/model/essential_pass/remove_edges_by_type.py +55 -0
  53. samva/core/model/essential_pass/remove_nodes_by_addr.py +42 -0
  54. samva/core/model/extra_pass/__init__.py +17 -0
  55. samva/core/model/extra_pass/aligned_words.py +41 -0
  56. samva/core/model/extra_pass/convert_type.py +62 -0
  57. samva/core/model/extra_pass/execute_sp_instruction.py +37 -0
  58. samva/core/model/extra_pass/replayable_instruction.py +61 -0
  59. samva/core/model/fault_modeling_pass/__init__.py +12 -0
  60. samva/core/model/fault_modeling_pass/add_annotation.py +82 -0
  61. samva/core/model/fault_modeling_pass/add_cost.py +41 -0
  62. samva/core/model/fault_modeling_pass/skip_jump.py +55 -0
  63. samva/core/model/ghidra_frontend.py +388 -0
  64. samva/core/model/samva_model.py +533 -0
  65. samva/core/model/samva_model_pass_base.py +22 -0
  66. samva/core/samva.py +868 -0
  67. samva/core/samva_dataflow.py +853 -0
  68. samva/core/samva_strategies.py +146 -0
  69. samva/evaluator/__init__.py +30 -0
  70. samva/evaluator/evaluator_base.py +119 -0
  71. samva/evaluator/evaluator_gem5.py +127 -0
  72. samva/evaluator/evaluator_log_verifypin.py +206 -0
  73. samva/evaluator/evaluator_openocd.py +134 -0
  74. samva/evaluator/evaluator_simulation.py +413 -0
  75. samva/evaluator/evaluator_unicorn.py +231 -0
  76. samva/evaluator/evaluator_unicorn2.py +562 -0
  77. samva/experimentation/__init__.py +18 -0
  78. samva/experimentation/benchmark.py +119 -0
  79. samva/experimentation/patcher.py +53 -0
  80. samva/physical/__init__.py +6 -0
  81. samva/physical/analysis/__init__.py +25 -0
  82. samva/physical/analysis/campaign.py +199 -0
  83. samva/physical/analysis/campaign_target.py +11 -0
  84. samva/physical/analysis/emulator.py +429 -0
  85. samva/physical/analysis/samva_file_line.py +22 -0
  86. samva/physical/analysis/simulation_branch_characterisation.py +255 -0
  87. samva/physical/analysis/simulation_characterisation.py +332 -0
  88. samva/physical/attacks/__init__.py +14 -0
  89. samva/physical/attacks/campaign_stm32flash_verifypin.py +105 -0
  90. samva/physical/boards/__init__.py +14 -0
  91. samva/physical/boards/base/__init__.py +20 -0
  92. samva/physical/boards/base/openocd.py +532 -0
  93. samva/physical/boards/base/serial_communication.py +133 -0
  94. samva/physical/boards/base/target.py +217 -0
  95. samva/physical/boards/injectors/__init__.py +16 -0
  96. samva/physical/boards/injectors/injector.py +30 -0
  97. samva/physical/boards/injectors/traitor.py +356 -0
  98. samva/physical/boards/targets/__init__.py +18 -0
  99. samva/physical/boards/targets/cv32e40p_litex.py +190 -0
  100. samva/physical/boards/targets/misc/ek-tm4c123gxl.cfg +13 -0
  101. samva/physical/boards/targets/misc/samva-hs2.cfg +42 -0
  102. samva/physical/boards/targets/misc/st_nucleo_f3.cfg +10 -0
  103. samva/physical/boards/targets/stm32.py +119 -0
  104. samva/physical/boards/targets/stm32flash.py +66 -0
  105. samva/physical/boards/targets/stm32ram.py +123 -0
  106. samva/physical/compil/__init__.py +18 -0
  107. samva/physical/compil/assembler_arm.py +51 -0
  108. samva/physical/compil/elf_file.py +45 -0
  109. samva/physical/compil/gcc.py +143 -0
  110. samva/physical/compil/program_arm.py +183 -0
  111. samva/plot/__init__.py +21 -0
  112. samva/plot/faulting_delays.py +35 -0
  113. samva/plot/histo_amp_delay.py +41 -0
  114. samva/plot/histo_classification.py +28 -0
  115. samva/plot/histo_classification2.py +138 -0
  116. samva/plot/histo_classification3.py +110 -0
  117. samva/plot/number_difference.py +57 -0
  118. samva/plot/plot_common.py +29 -0
  119. samva/plot/test_classification.ipynb +716 -0
  120. samva-2.0.5.dist-info/METADATA +211 -0
  121. samva-2.0.5.dist-info/RECORD +124 -0
  122. samva-2.0.5.dist-info/WHEEL +4 -0
  123. samva-2.0.5.dist-info/entry_points.txt +3 -0
  124. samva-2.0.5.dist-info/licenses/LICENSE +661 -0
samva/__init__.py ADDED
@@ -0,0 +1,15 @@
1
+ # SAMVA, initial software
2
+ # Copyright © INRIA, Affero GPL v3, 2022, v 1.0
3
+
4
+ __all__ = [
5
+ "commands",
6
+ "core",
7
+ "evaluator",
8
+ "experimentation",
9
+ "physical",
10
+ "plot"
11
+ ]
12
+
13
+ """
14
+ .. include:: ../../README.md
15
+ """
samva/__main__.py ADDED
@@ -0,0 +1,7 @@
1
+ # SAMVA, initial software
2
+ # Copyright © INRIA, Affero GPL v3, 2022, v 1.0
3
+
4
+ from .cli import main
5
+
6
+ if __name__ == "__main__":
7
+ main()
samva/cli.py ADDED
@@ -0,0 +1,167 @@
1
+ # SAMVA, initial software
2
+ # Copyright © INRIA, Affero GPL v3, 2022, v 1.0
3
+ import pyghidra
4
+ import click
5
+
6
+ pyghidra.start()
7
+
8
+ import logging # noqa: E402
9
+ from functools import partial # noqa: E402
10
+ from samva.commands.evaluate import run_evaluate # noqa: E402
11
+ from samva.commands.cv32e40p import run_cv32e40p # noqa: E402
12
+ from samva.commands.debugger import run_debugger # noqa: E402
13
+ from samva.commands.traitor import run_traitor, run_traitor_characterization # noqa: E402
14
+ from samva.commands.stm32 import run_stm32 # noqa: E402
15
+ from samva.commands.measure_cycles import run_measure_cycles # noqa: E402
16
+ from samva.commands.test_dynprog import run_test_dynprog # noqa: E402
17
+
18
+ log = logging.getLogger(name=f"samva-{__name__}")
19
+ log.setLevel(logging.DEBUG)
20
+
21
+
22
+ # @click.group()
23
+ @click.group(chain=True)
24
+ def main():
25
+ pass
26
+
27
+ @main.command()
28
+ # Mandatory arguments
29
+ @click.argument("bin_path", required=True, type=click.Path(exists=True, file_okay=True, writable=False))
30
+ @click.argument("samva_config_path", required=True, type=click.Path(exists=True, file_okay=True, writable=False))
31
+ # Most common options, comes with reasonable default values
32
+ @click.option("--result_folder", required=False, type=click.Path(exists=True, file_okay=False, writable=True), help="Directory where the results are stored.")
33
+ @click.option("--fault_model", required=False, type=click.Choice(["TrueNOP", "Replay"], case_sensitive=False), default="TrueNOP")
34
+ @click.option("--fault_parameters", required=False, type=(int, int, int), default=(1, 10, 1), help="Specify the fault model as argument if not in configuration file.")
35
+ # Options related to new algorithms
36
+ @click.option("--max_paths_per_segment", required=False, type=int, default=None, help="Maximum number of paths to find for each attack segment.")
37
+ @click.option("--max_cost_per_segment", required=False, type=int, default=None, help="Maximum number of faults allowed in each attack segment.")
38
+ @click.option("--max_cost_for_simulation", required=False, type=int, default=None, help="Maximum number of faults considered for simulation.")
39
+ @click.option("--max_attack_paths", required=False, type=int, default=None, help="Maximum number of attack paths to find.")
40
+ # Options related to attack paths evaluation
41
+ @click.option("--evaluator", type=click.Choice(["unicorn", "gem5", "none"], case_sensitive=False), default="unicorn", help="Evaluator used to validate the attack paths.")
42
+ @click.option("--unicorn_full_init/--no-unicorn_full_init", default=True, help="Specific to unicorn emulation. PC is set to first attacked address, without running the full program init to avoid impossible loop due hardware interactions.")
43
+ @click.option("--log_variable", "-lv", multiple=True, help="Program symbols that will be logged during evaluation.")
44
+ # Options enabling early exit
45
+ @click.option("--timeout", required=False, type=float, default=-1.0, help="Analysis timeout.")
46
+ @click.option("--stop_at_robustness/--no_stop_at_robustness", default=True, help="Stop after finding the robustness factor.")
47
+ # Options that enable the previous algorithms, for compatibility purposes
48
+ @click.option("--deprecated/--no_deprecated", required=False, type=bool, default=False, help="Enable previous algorithms.")
49
+ @click.option("--deprecated_exhaustive/--no-deprecated_exhaustive", required=False, type=bool, default=False, help="Enable exhaustive search for backtracking fault positioning.")
50
+ @click.option("--deprecated_max_solutions", required=False, type=int, default=5, help="Maximum number of solutions found per attack path.")
51
+ # Verbose mode, useful for debug.
52
+ @click.option("--verbose/--no-verbose", default=False, help="Displays information during the analysis.")
53
+ def evaluate(bin_path, samva_config_path, result_folder, fault_model,
54
+ fault_parameters, max_paths_per_segment, max_cost_per_segment, max_cost_for_simulation,
55
+ max_attack_paths, evaluator, unicorn_full_init, log_variable, timeout, stop_at_robustness,
56
+ deprecated, deprecated_exhaustive, deprecated_max_solutions, verbose):
57
+ return partial(run_evaluate, bin_path=bin_path, samva_config_path=samva_config_path, result_folder=result_folder,
58
+ fault_model=fault_model, fault_parameters=fault_parameters,
59
+ max_paths_per_segment=max_paths_per_segment, max_cost_per_segment=max_cost_per_segment,
60
+ max_cost_for_simulation=max_cost_for_simulation, max_attack_paths=max_attack_paths,
61
+ evaluator=evaluator, unicorn_full_init=unicorn_full_init, log_variable=log_variable,
62
+ timeout=timeout, stop_at_robustness=stop_at_robustness, deprecated=deprecated,
63
+ deprecated_exhaustive=deprecated_exhaustive, deprecated_max_solutions=deprecated_max_solutions,
64
+ verbose=verbose)
65
+
66
+ @main.command()
67
+ @click.argument("port", required=True)
68
+ @click.option("--verbose/--no-verbose", default=False, help="Displays information during the analysis.")
69
+ def cv32e40p(port, verbose):
70
+ return partial(run_cv32e40p, port=port, verbose=verbose)
71
+
72
+ @main.command()
73
+ @click.option("--verbose/--no-verbose", default=False, help="Displays information during the analysis.")
74
+ def debugger(verbose):
75
+ return partial(run_debugger, verbose=verbose)
76
+
77
+ @main.command()
78
+ @click.argument("port", required=True)
79
+ @click.option("--traitor_amplitude", "-ta", type=int, multiple=True, help="Traitor amplitude used during the attacks.")
80
+ @click.option("--traitor_fault", "-tf", type=(int, int), multiple=True, help="Traitor fault <delay, duration> parameter.")
81
+ @click.option("--reset/--no-reset", default=False, help="Reset Traitor configuration.")
82
+ @click.option("--repetitions", required=False, type=int, default=5, help="Number of attack per configuration tested.")
83
+ @click.option("--campaign/--no-campaign", default=False, help="Launch a Traitor campaign.")
84
+ @click.option("--verbose/--no-verbose", default=False, help="Displays information during the analysis.")
85
+ def traitor(port, traitor_amplitude, traitor_fault, reset, repetitions, campaign, verbose):
86
+ return partial(run_traitor, port=port, amplitudes=traitor_amplitude, temporal_parameters=traitor_fault, reset=reset,
87
+ repetitions=repetitions, campaign=campaign, verbose=verbose)
88
+
89
+ @main.command()
90
+ @click.option('--custom_port', default=None, type=str)
91
+ @click.option('--stlink', default=None, type=str)
92
+ @click.option('--program', default=None, type=str)
93
+ @click.option("--verbose/--no-verbose", default=False, help="Displays information during the analysis.")
94
+ def stm32(custom_port, stlink, program, verbose):
95
+ return partial(run_stm32, custom_port=custom_port, stlink=stlink, program=program, verbose=verbose)
96
+
97
+ @main.command()
98
+ @click.argument("addr1", type=str)
99
+ @click.argument("addr2", type=str)
100
+ @click.option("--verbose/--no-verbose", default=False, help="Displays information during the analysis.")
101
+ def measure_cycles(addr1, addr2, verbose):
102
+ return partial(run_measure_cycles, addr1=addr1, addr2=addr2, verbose=verbose)
103
+
104
+ @main.command()
105
+ @click.option('--trace', type=str, help="Complete trace.")
106
+ @click.option('--seed', type=int, help="Random seed; if 0, unseeded.", default=0)
107
+ @click.option('--length', type=int, help="Length of the generated trace.")
108
+ @click.option('--repeats', type=int, help="Number of traces to generate.")
109
+ @click.option('--fault_parameters', type=(int, int, int), help="Specify the fault model as argument if not in "
110
+ "configuration file.")
111
+ @click.option('--max_solutions', required=False, type=int, default=100)
112
+ @click.option('--exhaustive/--no-exhaustive', required=False, type=bool, default=False)
113
+ @click.option('--verbose/--no-verbose', default=False, help="Displays information during the core.")
114
+ def test_dynprog(trace, seed, length, repeats, fault_parameters, max_solutions, exhaustive, verbose):
115
+ return partial(run_test_dynprog, trace=trace, seed=seed, length=length, repeats=repeats,
116
+ fault_parameters=fault_parameters, max_solutions=max_solutions, exhaustive=exhaustive,
117
+ verbose=verbose)
118
+
119
+ @main.command()
120
+ @click.argument("port", required=True)
121
+ @click.option('--amplitude_range', type=(int, int), required=True)
122
+ @click.option('--delay_range', type=(int, int), required=True)
123
+ @click.option('--duration_range', type=(int, int), required=True)
124
+ @click.option("--repetitions", required=False, type=int, default=50, help="Number of attack per configuration tested.")
125
+ @click.option("--amplitude_step", required=False, type=int, default=1)
126
+ @click.option("--delay_step", required=False, type=int, default=1)
127
+ @click.option("--duration_step", required=False, type=int, default=1)
128
+ @click.option('--verbose/--no-verbose', default=False, help="Displays information during the core.")
129
+ def traitor_characterization(port, amplitude_range, delay_range, duration_range, repetitions, amplitude_step,
130
+ delay_step, duration_step, verbose):
131
+ return partial (run_traitor_characterization, port=port, amplitude_range=amplitude_range, delay_range=delay_range,
132
+ duration_range=duration_range, repetitions=repetitions, amplitude_step=amplitude_step,
133
+ delay_step=delay_step, duration_step=duration_step, verbose=verbose)
134
+
135
+
136
+ # TODO: must integrate the other commands with the new chaining command system
137
+ # # STM32 commands
138
+ # main.add_command(stm32.simulate, "simulate")
139
+ #
140
+ # # Plotting commands
141
+ # main.add_command(plot.plot_faulting_delays, "plot_faulting_delays") # amplitude = f(burst_size)
142
+ # main.add_command(plot.plot_amp_delay, "plot_amp_delay") # amplitude = f(burst_size)
143
+ # main.add_command(plot.plot_histo_classification, "plot_histo_classification") # fault classification for each delay
144
+ # main.add_command(plot.plot_histo_classification2, "plot_histo_classification2") # for each delay histo(amplitude)
145
+ # main.add_command(plot.plot_number_difference, "plot_number_difference") # 3D plot amplitude = f(duration, delay)
146
+ #
147
+ # # Evaluation commands for SAMVA v2
148
+ # main.add_command(evals.eval_verifypin_truenop, "eval_verifypin_truenop")
149
+
150
+
151
+ @main.result_callback()
152
+ def process_pipeline(processors):
153
+ value = None
154
+ for processor in processors:
155
+ value = processor(value)
156
+
157
+ if value is not None and type(value) is dict:
158
+ for binary_name in value.keys():
159
+ if "log" in value[binary_name] and len(value[binary_name]["log"]) > 0:
160
+ log.info("")
161
+ log.info("")
162
+ log.info("--- SAMVA Log Summary ---")
163
+ for line in value[binary_name]["log"]:
164
+ log.info(line)
165
+
166
+ if __name__ == '__main__':
167
+ main()
@@ -0,0 +1,6 @@
1
+ # SAMVA, initial software
2
+ # Copyright © INRIA, Affero GPL v3, 2022, v 1.0
3
+
4
+ """
5
+ commands module contains the integrated commands shipped with SAMVA.
6
+ """
@@ -0,0 +1,107 @@
1
+ # SAMVA, initial software
2
+ # Copyright © INRIA, Affero GPL v3, 2022, v 1.0
3
+
4
+ import ast
5
+ import logging
6
+ from functools import wraps
7
+
8
+ import click
9
+
10
+ from samva.core.common import setup_logging
11
+ from samva.core.common.analysis_utils import Timing
12
+
13
+ log = logging.getLogger(name=f"samva-{__name__}")
14
+ log.setLevel(logging.DEBUG)
15
+
16
+
17
+ class BasedIntParamType(click.ParamType):
18
+ name = "integer"
19
+
20
+ def convert(self, value, param, ctx):
21
+ if isinstance(value, int):
22
+ return value
23
+
24
+ try:
25
+ if value[:2].lower() == "0x":
26
+ return int(value[2:], 16)
27
+ elif value[:1] == "0":
28
+ return int(value, 8)
29
+ return int(value, 10)
30
+ except ValueError:
31
+ self.fail(f"{value!r} is not a valid integer", param, ctx)
32
+
33
+ BASED_INT = BasedIntParamType()
34
+
35
+ class PythonLiteralOption(click.Option):
36
+
37
+ def type_cast_value(self, ctx, value):
38
+ if value is None:
39
+ return None
40
+ try:
41
+ return ast.literal_eval(value)
42
+ except:
43
+ raise click.BadParameter(value)
44
+
45
+ # Decorators
46
+
47
+ def check_logging(command):
48
+ @wraps(command)
49
+ def wrapper(*args, **kwargs):
50
+ verbose = kwargs.get("verbose", False)
51
+ setup_logging(logging.DEBUG if verbose else logging.INFO)
52
+ return command(*args, **kwargs)
53
+ return wrapper
54
+
55
+ def must_be_chained(required: bool):
56
+ def decorator(command):
57
+ @wraps(command)
58
+ def wrapper(previous, *args, **kwargs):
59
+ if required and previous is None:
60
+ command_name = command.__name__
61
+ if command_name.startswith("run_"):
62
+ command_name = command_name[4:]
63
+ raise RuntimeError(f"\"{command_name}\" command must be chained after another command.")
64
+ return command(previous if previous is not None else {}, *args, **kwargs)
65
+ return wrapper
66
+ return decorator
67
+
68
+ def hardware_attack(command):
69
+ @wraps(command)
70
+ def wrapper(previous, *args, **kwargs):
71
+ for binary_name, result in previous.items():
72
+ create_target = result.get("create_target")
73
+ if create_target is None:
74
+ log.error(f"No hardware target for {binary_name}")
75
+ continue
76
+
77
+ target = create_target()
78
+
79
+ with Timing() as t_attack:
80
+ attack_tested, attack_validated = command(
81
+ previous,
82
+ target=target,
83
+ binary_name=binary_name,
84
+ *args,
85
+ **kwargs,
86
+ )
87
+ duration = t_attack.time
88
+
89
+ result["hardware_result"] = {
90
+ "attack_path_tested": attack_tested,
91
+ "attack_path_validated": attack_validated,
92
+ "duration_sec": duration,
93
+ }
94
+
95
+ if attack_tested == 0:
96
+ txt = "No attack path tested due to previous error."
97
+ else:
98
+ txt = (
99
+ f"Hardware validation - Validated {attack_validated} / "
100
+ f"{attack_tested} in {duration:.2f} seconds "
101
+ f"(mean of {duration / attack_tested:.2f} secs)."
102
+ )
103
+
104
+ log.info(txt)
105
+ result["log"].append(txt)
106
+ return previous
107
+ return wrapper
@@ -0,0 +1,92 @@
1
+ import logging
2
+ import click
3
+ import os
4
+
5
+ from samva.experimentation import Benchmark, BenchmarkIterator
6
+ from samva.core import Samva
7
+ from samva.evaluator import EvaluatorBase
8
+ from samva.evaluator.evaluator_unicorn2 import EvaluatorSimulationUnicorn2
9
+ from samva.core.common.log_utils import setup_logging
10
+ from samva.core.common.attack_path import FaultParameters, FaultModel
11
+ from samva.core.common.analysis_utils import Timing
12
+
13
+
14
+ log = logging.getLogger(name=f"samva-{__name__}")
15
+ log.setLevel(logging.DEBUG)
16
+
17
+
18
+ # @click.option('--fault_parameters', type=(int, int, int))
19
+ # @click.option('--fault_model', type=click.Choice(['TrueNOP', 'Replay'], case_sensitive=False), default="TrueNOP")
20
+
21
+ def path_verifyPIN(benchmark_folder, n, flags=""):
22
+ flags = "_" + flags if flags else ""
23
+ elf = os.path.join(benchmark_folder, f"build/verifypin_v{n}_cv32e40p/verifypin_v{n}_cv32e40p{flags}.elf")
24
+ config = os.path.join(benchmark_folder, f"samva_files/verifypin_v{n}_cv32e40p.json")
25
+ return elf, config
26
+
27
+ @click.command()
28
+ @click.option("--benchmark_folder", default="../samva_benchmarks")
29
+ @click.option('--verbose/--no-verbose', default=False, help="Displays information during the core.")
30
+ def eval_verifypin_truenop(benchmark_folder, verbose):
31
+ setup_logging(logging_level=logging.DEBUG if verbose else logging.INFO)
32
+
33
+ # Fixed settings
34
+ fault_model = FaultModel.TrueNOP
35
+ strategy = "default"
36
+ # Won't apply to the new algorithms
37
+ exhaustive = False
38
+ fake_timeout = 999999
39
+
40
+ samvas = dict()
41
+ evaluators = dict()
42
+
43
+ verifypin_versions = [0, 1, 2, 3, 4, 5, 6, 7]
44
+ # verifypin_versions = [5]
45
+
46
+ #=== Load programs ===#
47
+
48
+ for n in verifypin_versions:
49
+ path_elf, path_config = path_verifyPIN(benchmark_folder, n)
50
+
51
+ samvas[n] = Samva(path_elf, config_file=path_config, fault_model=fault_model, strategy=strategy,
52
+ exhaustive=exhaustive)
53
+ evaluators[n] = EvaluatorSimulationUnicorn2(samvas[n].samva_model, fault_model)
54
+
55
+ #=== Run tests ===#
56
+
57
+ def attacks_within_time(n, timeout: float) -> int:
58
+ fault_parameters = FaultParameters(1, 4, 1, fake_timeout)
59
+ attack_result = samvas[n].find_data_aware_attack_paths(fault_parameters, evaluators[n],
60
+ max_paths_per_segment=None, max_cost_per_segment=None, max_cost_for_simulation=None,
61
+ stop_when_robustness_found=False, timeout=timeout)
62
+ attacks_found = len(attack_result.attack_paths or [])
63
+ print(f"Listed {attacks_found} attacks in {timeout} seconds")
64
+ return attacks_found
65
+
66
+ def robustness_map(fp, ns, low_width: int, high_width: int, min_distance: int, max_budget: int, timeout: floats) \
67
+ -> list[list[int]]:
68
+ fp.write(f"version,min_width,max_width,robustness,analysis_time\n")
69
+ fp.flush()
70
+ for n in ns:
71
+ for max_width in range(low_width, high_width + 1):
72
+ for min_width in range(low_width, max_width + 1):
73
+ fault_parameters = FaultParameters(min_width, max_width, min_distance, fake_timeout)
74
+ print(f"verifyPIN_v{n}: ({min_width}, {max_width}, {min_distance})...")
75
+ with Timing() as t_analysis:
76
+ attack_result = samvas[n].find_data_aware_attack_paths(fault_parameters, evaluators[n],
77
+ max_paths_per_segment=None, max_cost_per_segment=max_budget, max_cost_for_simulation=None,
78
+ stop_when_robustness_found=True, timeout=timeout)
79
+
80
+ if attack_result.robustness is not None:
81
+ robustness = str(attack_result.robustness)
82
+ elif samvas[n].bound_min_attacks is None:
83
+ robustness = "+inf"
84
+ else:
85
+ robustness = f">= {samvas[n].bound_min_attacks - 1}"
86
+
87
+ print(f"verifyPIN_v{n}: ({min_width}, {max_width}, {min_distance}) -> {robustness} in {t_analysis}")
88
+ fp.write(f"{n},{min_width},{max_width},{robustness},{t_analysis.time}\n")
89
+ fp.flush()
90
+
91
+ with open("verifypin_truenop_robustness.csv", "w") as fp:
92
+ robustness_map(fp, verifypin_versions, 1, 10, 1, max_budget=None, timeout=30.0)
@@ -0,0 +1,68 @@
1
+ # SAMVA, initial software
2
+ # Copyright © INRIA, Affero GPL v3, 2022, v 1.0
3
+
4
+ import os
5
+
6
+ import click
7
+
8
+ @click.command()
9
+ @click.argument('input_file', required=1, type=str)
10
+ @click.argument('output_file', required=0, type=str, default=None)
11
+ @click.option('--tex', default=False)
12
+ def plot_faulting_delays(input_file, output_file, tex):
13
+ from samva.plot.faulting_delays import faulting_delays
14
+ if output_file is None:
15
+ path_split = os.path.splitext(input_file)
16
+ output_file = path_split[0] + "_delays.pdf"
17
+ faulting_delays(input_file, output_file, tex)
18
+
19
+ @click.command()
20
+ @click.argument('input_file', required=1, type=str)
21
+ @click.argument('output_file', required=0, type=str, default=None)
22
+ @click.argument('fault', required=1, type=str)
23
+ @click.option('--tex', default=False)
24
+ def plot_amp_delay(input_file, output_file, fault, tex):
25
+ from samva.plot.histo_amp_delay import faulting_ampdelay
26
+ faulting_ampdelay(input_file, output_file, fault, tex)
27
+
28
+
29
+ @click.command()
30
+ @click.argument('input_file', required=1, type=str)
31
+ @click.argument('output_file', required=0, type=str, default=None)
32
+ @click.argument('delay_value', required=1, type=int)
33
+ @click.option('--tex', default=False)
34
+ def plot_histo_classification(input_file, output_file, delay_value, tex):
35
+ if output_file is None:
36
+ path_split = os.path.splitext(input_file)
37
+ output_file = path_split[0] + "_hist.pdf"
38
+ from samva.plot.histo_classification import histo_classification
39
+ histo_classification(input_file, output_file, delay_value, tex)
40
+
41
+
42
+ @click.command()
43
+ @click.argument('input_file', required=1, type=str)
44
+ @click.argument('output_file', required=0, type=str, default=None)
45
+ @click.option('--others_perc', type=int, default=5)
46
+ @click.option('--percentage', default=False)
47
+ @click.option('--duration_group', default=False)
48
+ @click.option('--duration_group_value', type=int, default=4)
49
+ @click.option('--tex', default=False)
50
+ def plot_histo_classification2(input_file, output_file, others_perc, percentage, duration_group,
51
+ duration_group_value, tex):
52
+ if output_file is None:
53
+ path_split = os.path.splitext(input_file)
54
+ output_file = path_split[0] + "_hist2.pdf"
55
+ from samva.plot.histo_classification2 import histo_classification2
56
+ histo_classification2(input_file, output_file, others_perc, percentage, duration_group, duration_group_value, tex)
57
+
58
+
59
+ @click.command()
60
+ @click.argument('input_file', required=1, type=str)
61
+ @click.argument('output_file', required=0, type=str, default=None)
62
+ @click.option('--tex', default=False)
63
+ def plot_number_difference(input_file, output_file, tex):
64
+ if output_file is None:
65
+ path_split = os.path.splitext(input_file)
66
+ output_file = path_split[0] + "_numbdiff.pdf"
67
+ from samva.plot.number_difference import number_difference
68
+ number_difference(input_file, output_file, tex)