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.
- samva/__init__.py +15 -0
- samva/__main__.py +7 -0
- samva/cli.py +167 -0
- samva/commands/__init__.py +6 -0
- samva/commands/commands_common.py +107 -0
- samva/commands/commands_evals.py +92 -0
- samva/commands/commands_plot.py +68 -0
- samva/commands/commands_stm32.py +385 -0
- samva/commands/cv32e40p.py +24 -0
- samva/commands/debugger.py +37 -0
- samva/commands/evaluate.py +186 -0
- samva/commands/measure_cycles.py +43 -0
- samva/commands/stm32.py +18 -0
- samva/commands/test_dynprog.py +103 -0
- samva/commands/traitor.py +281 -0
- samva/core/__init__.py +20 -0
- samva/core/common/__init__.py +41 -0
- samva/core/common/analyse_configuration.py +71 -0
- samva/core/common/analysis_utils.py +56 -0
- samva/core/common/attack_path.py +175 -0
- samva/core/common/configuration.py +163 -0
- samva/core/common/instruction_typing.py +149 -0
- samva/core/common/log_utils.py +199 -0
- samva/core/common/timeout.py +28 -0
- samva/core/common/try_import.py +12 -0
- samva/core/fault_positioning/__init__.py +22 -0
- samva/core/fault_positioning/base_pass.py +75 -0
- samva/core/fault_positioning/essential_pass/__init__.py +24 -0
- samva/core/fault_positioning/essential_pass/postvalidation_trim.py +51 -0
- samva/core/fault_positioning/essential_pass/prevalidation_common.py +132 -0
- samva/core/fault_positioning/essential_pass/validation_dynprog.py +1623 -0
- samva/core/fault_positioning/essential_pass/validation_true_nop.py +31 -0
- samva/core/fault_positioning/extra_pass/__init__.py +14 -0
- samva/core/fault_positioning/extra_pass/replay_passes.py +120 -0
- samva/core/fault_positioning/fault_positioner.py +166 -0
- samva/core/model/__init__.py +19 -0
- samva/core/model/db/__init__.py +35 -0
- samva/core/model/db/arch.py +348 -0
- samva/core/model/db/basic_block.py +48 -0
- samva/core/model/db/flow_type.py +37 -0
- samva/core/model/db/function.py +68 -0
- samva/core/model/db/instruction.py +137 -0
- samva/core/model/db/pcode.py +232 -0
- samva/core/model/db/section.py +65 -0
- samva/core/model/db/symbol.py +42 -0
- samva/core/model/essential_pass/__init__.py +23 -0
- samva/core/model/essential_pass/dead_code_elimination.py +51 -0
- samva/core/model/essential_pass/find_first_last_nodes.py +54 -0
- samva/core/model/essential_pass/fix_isolated_nodes.py +51 -0
- samva/core/model/essential_pass/forced_types.py +59 -0
- samva/core/model/essential_pass/prune_cfg.py +47 -0
- samva/core/model/essential_pass/remove_edges_by_type.py +55 -0
- samva/core/model/essential_pass/remove_nodes_by_addr.py +42 -0
- samva/core/model/extra_pass/__init__.py +17 -0
- samva/core/model/extra_pass/aligned_words.py +41 -0
- samva/core/model/extra_pass/convert_type.py +62 -0
- samva/core/model/extra_pass/execute_sp_instruction.py +37 -0
- samva/core/model/extra_pass/replayable_instruction.py +61 -0
- samva/core/model/fault_modeling_pass/__init__.py +12 -0
- samva/core/model/fault_modeling_pass/add_annotation.py +82 -0
- samva/core/model/fault_modeling_pass/add_cost.py +41 -0
- samva/core/model/fault_modeling_pass/skip_jump.py +55 -0
- samva/core/model/ghidra_frontend.py +388 -0
- samva/core/model/samva_model.py +533 -0
- samva/core/model/samva_model_pass_base.py +22 -0
- samva/core/samva.py +868 -0
- samva/core/samva_dataflow.py +853 -0
- samva/core/samva_strategies.py +146 -0
- samva/evaluator/__init__.py +30 -0
- samva/evaluator/evaluator_base.py +119 -0
- samva/evaluator/evaluator_gem5.py +127 -0
- samva/evaluator/evaluator_log_verifypin.py +206 -0
- samva/evaluator/evaluator_openocd.py +134 -0
- samva/evaluator/evaluator_simulation.py +413 -0
- samva/evaluator/evaluator_unicorn.py +231 -0
- samva/evaluator/evaluator_unicorn2.py +562 -0
- samva/experimentation/__init__.py +18 -0
- samva/experimentation/benchmark.py +119 -0
- samva/experimentation/patcher.py +53 -0
- samva/physical/__init__.py +6 -0
- samva/physical/analysis/__init__.py +25 -0
- samva/physical/analysis/campaign.py +199 -0
- samva/physical/analysis/campaign_target.py +11 -0
- samva/physical/analysis/emulator.py +429 -0
- samva/physical/analysis/samva_file_line.py +22 -0
- samva/physical/analysis/simulation_branch_characterisation.py +255 -0
- samva/physical/analysis/simulation_characterisation.py +332 -0
- samva/physical/attacks/__init__.py +14 -0
- samva/physical/attacks/campaign_stm32flash_verifypin.py +105 -0
- samva/physical/boards/__init__.py +14 -0
- samva/physical/boards/base/__init__.py +20 -0
- samva/physical/boards/base/openocd.py +532 -0
- samva/physical/boards/base/serial_communication.py +133 -0
- samva/physical/boards/base/target.py +217 -0
- samva/physical/boards/injectors/__init__.py +16 -0
- samva/physical/boards/injectors/injector.py +30 -0
- samva/physical/boards/injectors/traitor.py +356 -0
- samva/physical/boards/targets/__init__.py +18 -0
- samva/physical/boards/targets/cv32e40p_litex.py +190 -0
- samva/physical/boards/targets/misc/ek-tm4c123gxl.cfg +13 -0
- samva/physical/boards/targets/misc/samva-hs2.cfg +42 -0
- samva/physical/boards/targets/misc/st_nucleo_f3.cfg +10 -0
- samva/physical/boards/targets/stm32.py +119 -0
- samva/physical/boards/targets/stm32flash.py +66 -0
- samva/physical/boards/targets/stm32ram.py +123 -0
- samva/physical/compil/__init__.py +18 -0
- samva/physical/compil/assembler_arm.py +51 -0
- samva/physical/compil/elf_file.py +45 -0
- samva/physical/compil/gcc.py +143 -0
- samva/physical/compil/program_arm.py +183 -0
- samva/plot/__init__.py +21 -0
- samva/plot/faulting_delays.py +35 -0
- samva/plot/histo_amp_delay.py +41 -0
- samva/plot/histo_classification.py +28 -0
- samva/plot/histo_classification2.py +138 -0
- samva/plot/histo_classification3.py +110 -0
- samva/plot/number_difference.py +57 -0
- samva/plot/plot_common.py +29 -0
- samva/plot/test_classification.ipynb +716 -0
- samva-2.0.5.dist-info/METADATA +211 -0
- samva-2.0.5.dist-info/RECORD +124 -0
- samva-2.0.5.dist-info/WHEEL +4 -0
- samva-2.0.5.dist-info/entry_points.txt +3 -0
- samva-2.0.5.dist-info/licenses/LICENSE +661 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
# # SAMVA, initial software
|
|
2
|
+
# # Copyright © INRIA, Affero GPL v3, 2022, v 1.0
|
|
3
|
+
#
|
|
4
|
+
# import csv
|
|
5
|
+
# import json
|
|
6
|
+
# import logging
|
|
7
|
+
# import os
|
|
8
|
+
# import sys
|
|
9
|
+
# import time
|
|
10
|
+
# from pathlib import Path
|
|
11
|
+
#
|
|
12
|
+
# import click
|
|
13
|
+
# from tqdm import tqdm
|
|
14
|
+
# from tqdm.contrib.logging import logging_redirect_tqdm
|
|
15
|
+
#
|
|
16
|
+
# from samva.physical.analysis.samva_file_line import convert_attack_path
|
|
17
|
+
# from samva.physical.boards.targets.cv32e40p_litex import CV32E40P_Litex
|
|
18
|
+
# from samva.core.common import setup_logging
|
|
19
|
+
# from samva.core import Samva
|
|
20
|
+
# from samva.core.model.db import Instruction
|
|
21
|
+
# from samva.commands.commands_common import PythonLiteralOption, BASED_INT
|
|
22
|
+
# from samva.core.common.attack_path import FaultModel, FaultParameters
|
|
23
|
+
# from samva.experimentation.patcher import Patcher
|
|
24
|
+
# from samva.physical.analysis.campaign import CampaignTarget
|
|
25
|
+
# from samva.physical.analysis.simulation_branch_characterisation import SimulationBranchCharacterisation
|
|
26
|
+
# from samva.physical.analysis.simulation_characterisation import SimulationCharacterisation, default_register_value, \
|
|
27
|
+
# dict_register_value
|
|
28
|
+
# from samva.physical.attacks.campaign_stm32flash_verifypin import Campaign_STM32Flash_Verifypin
|
|
29
|
+
# from samva.physical.boards.targets.stm32flash import STM32Flash
|
|
30
|
+
# from samva.physical.boards.injectors.traitor import Traitor
|
|
31
|
+
#
|
|
32
|
+
# log = logging.getLogger(name=f"samva-{__name__}")
|
|
33
|
+
# log.setLevel(logging.DEBUG)
|
|
34
|
+
#
|
|
35
|
+
# samva_config_characterization = """
|
|
36
|
+
# {
|
|
37
|
+
# "starting_point": "characterization",
|
|
38
|
+
# "attack_points": [
|
|
39
|
+
# {
|
|
40
|
+
# "target": "instruction",
|
|
41
|
+
# "address": "characterization"
|
|
42
|
+
# }
|
|
43
|
+
# ],
|
|
44
|
+
# "global_avoid": [],
|
|
45
|
+
# "forced_types": []
|
|
46
|
+
# }
|
|
47
|
+
# """
|
|
48
|
+
#
|
|
49
|
+
# @click.command()
|
|
50
|
+
# @click.argument('samva_results_dir', required=1, type=click.Path(exists=True, file_okay=False, writable=True))
|
|
51
|
+
# @click.argument('verifypin_dir', required=1, type=click.Path(exists=True, file_okay=False))
|
|
52
|
+
# @click.argument('traitor_port', required=1, type=str)
|
|
53
|
+
# # @click.argument('stm32_port', required=1, type=str)
|
|
54
|
+
# @click.option('--attacked_versions', cls=PythonLiteralOption, default=None,
|
|
55
|
+
# help="Limit the attack to selected verifypin versions.")
|
|
56
|
+
# @click.option('--attacks_per_version', required=False, type=int, default=5,
|
|
57
|
+
# help="Number of attacks for each verifypin version.")
|
|
58
|
+
# @click.option('--verbose/--no-verbose', default=False)
|
|
59
|
+
# def stm32_benchmark_traitor_verifypin(samva_results_dir, verifypin_dir, traitor_port, attacked_versions, # stm32_port
|
|
60
|
+
# attacks_per_version, verbose):
|
|
61
|
+
# setup_logging(logging.DEBUG if verbose else -1)
|
|
62
|
+
# targets = prepare_campaign(samva_results_dir, verifypin_dir, attacks_per_version, attacked_versions)
|
|
63
|
+
# # launch_campaign(samva_results_dir, traitor_port, stm32_port, targets)
|
|
64
|
+
# launch_campaign(samva_results_dir, traitor_port, None, targets)
|
|
65
|
+
#
|
|
66
|
+
# @click.command()
|
|
67
|
+
# @click.argument('program_file', required=1, type=str)
|
|
68
|
+
# @click.argument('samva_file', required=1, type=str)
|
|
69
|
+
# def test_riscv(program_file, samva_file):
|
|
70
|
+
# setup_logging(logging.DEBUG)
|
|
71
|
+
# samva = Samva(program_file, config_file=samva_file, fault_model=FaultModel.TrueNOP, strategy="stack_safe")
|
|
72
|
+
# fault_parameters = FaultParameters(2, 10, 2, 3600)
|
|
73
|
+
# attack_result = samva.find_attack_paths(fault_parameters, 100, None)
|
|
74
|
+
# if attack_result.attack_paths is None:
|
|
75
|
+
# log.error("No attack path found.")
|
|
76
|
+
# return
|
|
77
|
+
# binary_file = program_file.replace(".elf", ".bin")
|
|
78
|
+
# with CV32E40P_Litex(samva, "/dev/ttyUSB2", binary_file) as cv32_board:
|
|
79
|
+
# log.warning(f"Run 1 = {cv32_board.run() = }")
|
|
80
|
+
# log.warning(f"Run 2 = {cv32_board.run() = }")
|
|
81
|
+
# log.warning(f"Run 3 = {cv32_board.run() = }")
|
|
82
|
+
#
|
|
83
|
+
# iter_max = min(100, len(attack_result.attack_paths))
|
|
84
|
+
# time_total = 0
|
|
85
|
+
# for i, attack_path in enumerate(attack_result.attack_paths[:iter_max]):
|
|
86
|
+
# samva_lines = convert_attack_path(attack_path)
|
|
87
|
+
# expected_values = []
|
|
88
|
+
# for state in samva.samva_model.attack_options.simulation_final_state:
|
|
89
|
+
# symbol, symbol_size, expected_value = state.symbol, state.size, state.value
|
|
90
|
+
# symbol_addr = samva.samva_model.find_symbol_by_name(symbol).address
|
|
91
|
+
# expected_values.append((symbol_addr, symbol_size, expected_value))
|
|
92
|
+
# time_t0 = time.time()
|
|
93
|
+
# validated = cv32_board.validate_instruction_skip_attack(samva_lines, expected_results=expected_values)
|
|
94
|
+
# time_t1 = time.time()
|
|
95
|
+
# time_total += time_t1 - time_t0
|
|
96
|
+
# log.debug(f"{i = } - {validated = }")
|
|
97
|
+
# log.debug(f"Validated {iter_max} attack paths, in {time_total:.2f} seconds,"
|
|
98
|
+
# f"mean of {time_total/iter_max:.2f} seconds per attack path.")
|
|
99
|
+
#
|
|
100
|
+
#
|
|
101
|
+
# @click.command()
|
|
102
|
+
# @click.argument('samva_results_dir', required=1, type=click.Path(exists=True, file_okay=False, writable=True))
|
|
103
|
+
# @click.argument('verifypin_dir', required=1, type=click.Path(exists=True, file_okay=False))
|
|
104
|
+
# @click.argument('traitor_port', required=1, type=str)
|
|
105
|
+
# # @click.argument('stm32_port', required=1, type=str)
|
|
106
|
+
# @click.argument('version', required=1, type=str)
|
|
107
|
+
# @click.argument('extension', required=1, type=str)
|
|
108
|
+
# @click.argument('attack_number', required=1, type=str)
|
|
109
|
+
# @click.option('--verbose/--no-verbose', default=False)
|
|
110
|
+
# def stm32_traitor_attack_verifypin(samva_results_dir, verifypin_dir, traitor_port, version, extension, # stm32_port
|
|
111
|
+
# attack_number, verbose):
|
|
112
|
+
# setup_logging(logging.INFO if verbose else -1)
|
|
113
|
+
# target = create_target(samva_results_dir, verifypin_dir, version, extension, attack_number)
|
|
114
|
+
# if target is None:
|
|
115
|
+
# log.error("Impossible to create target!")
|
|
116
|
+
# else:
|
|
117
|
+
# launch_campaign(samva_results_dir, traitor_port, None, [target])
|
|
118
|
+
#
|
|
119
|
+
#
|
|
120
|
+
#
|
|
121
|
+
# @click.command()
|
|
122
|
+
# @click.argument('program_file', required=1, type=str)
|
|
123
|
+
# @click.argument('output_file', required=1, type=str)
|
|
124
|
+
# @click.argument('code_addr', required=1, type=BASED_INT)
|
|
125
|
+
# @click.argument('nb_word', required=1, type=int)
|
|
126
|
+
# @click.option('--regs_value', type=(BASED_INT, BASED_INT, BASED_INT, BASED_INT, BASED_INT, BASED_INT,
|
|
127
|
+
# BASED_INT, BASED_INT, BASED_INT, BASED_INT), required=0, default=None)
|
|
128
|
+
# @click.option('--max_repeat', required=False, type=int, default=None)
|
|
129
|
+
# @click.option('--config_file', default=None, type=str)
|
|
130
|
+
# @click.option('--map', default="", type=str)
|
|
131
|
+
# # @click.option('--inst', type=(int, int, int, int, int, int, int, int), required=0, default=None)
|
|
132
|
+
# def simulate(program_file, output_file, code_addr, nb_word, regs_value, max_repeat, config_file, map):
|
|
133
|
+
# parent_dir = os.path.dirname(output_file)
|
|
134
|
+
# if not os.path.exists(parent_dir):
|
|
135
|
+
# log.error(f"Output directory '{parent_dir}' does not exist!")
|
|
136
|
+
# sys.exit(-1)
|
|
137
|
+
#
|
|
138
|
+
# config_text = samva_config_characterization if config_file is None else None
|
|
139
|
+
# samva = Samva(program_file, config_file=config_file, config_text=config_text, fault_model=FaultModel.Replay,
|
|
140
|
+
# strategy="debug")
|
|
141
|
+
#
|
|
142
|
+
# patcher = Patcher(samva.samva_model)
|
|
143
|
+
#
|
|
144
|
+
# filter_regs = ['r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9']
|
|
145
|
+
# file_offset = patcher.convert_virtual_to_offset(code_addr)
|
|
146
|
+
#
|
|
147
|
+
# with open(program_file, "rb") as file:
|
|
148
|
+
# file.seek(file_offset)
|
|
149
|
+
# nb_byte = nb_word * 4
|
|
150
|
+
# code = file.read(nb_byte)
|
|
151
|
+
#
|
|
152
|
+
# if regs_value is None:
|
|
153
|
+
# registers_value = default_register_value(0)
|
|
154
|
+
# else:
|
|
155
|
+
# registers_value = dict_register_value(*regs_value)
|
|
156
|
+
#
|
|
157
|
+
#
|
|
158
|
+
# simu = SimulationCharacterisation()
|
|
159
|
+
# if map == "ram":
|
|
160
|
+
# simu.simulate_faults_ram(code,
|
|
161
|
+
# registers_value=registers_value,
|
|
162
|
+
# filter_regs=filter_regs,
|
|
163
|
+
# save_file=output_file,
|
|
164
|
+
# max_repetition=max_repeat,
|
|
165
|
+
# extra_sim=1)
|
|
166
|
+
#
|
|
167
|
+
# else:
|
|
168
|
+
# simu.simulate_faults(code,
|
|
169
|
+
# registers_value=registers_value,
|
|
170
|
+
# filter_regs=filter_regs,
|
|
171
|
+
# save_file=output_file,
|
|
172
|
+
# max_repetition=max_repeat,
|
|
173
|
+
# extra_sim=1)
|
|
174
|
+
#
|
|
175
|
+
# @click.command()
|
|
176
|
+
# @click.argument('program_file', required=1, type=str)
|
|
177
|
+
# @click.argument('output_file', required=1, type=str)
|
|
178
|
+
# @click.option('--regs_value', type=(BASED_INT, BASED_INT, BASED_INT, BASED_INT, BASED_INT, BASED_INT,
|
|
179
|
+
# BASED_INT, BASED_INT, BASED_INT, BASED_INT), required=0, default=None)
|
|
180
|
+
# @click.option('--max_repeat', required=False, type=int, default=None)
|
|
181
|
+
# @click.option('--config_file', default=None, type=str)
|
|
182
|
+
# def simulate_branch(program_file, output_file, regs_value, max_repeat, config_file):
|
|
183
|
+
# parent_dir = os.path.dirname(output_file)
|
|
184
|
+
# if not os.path.exists(parent_dir):
|
|
185
|
+
# log.error(f"Output directory '{parent_dir}' does not exist!")
|
|
186
|
+
# sys.exit(-1)
|
|
187
|
+
#
|
|
188
|
+
# config_text = samva_config_characterization if config_file is None else None
|
|
189
|
+
# samva = Samva(program_file, config_file=config_file, config_text=config_text, fault_model=FaultModel.Replay,
|
|
190
|
+
# strategy="debug")
|
|
191
|
+
#
|
|
192
|
+
# simu = SimulationBranchCharacterisation()
|
|
193
|
+
# simu.simulate_faults(samva, regs_value, max_repeat)
|
|
194
|
+
#
|
|
195
|
+
#
|
|
196
|
+
# def characterization_impl(traitor_port, stm32_port, program_file, simulation_file, output_file,
|
|
197
|
+
# amplitudes, delays, durations, repetition, stlink):
|
|
198
|
+
# filter_regs = ['r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9']
|
|
199
|
+
#
|
|
200
|
+
# with open(simulation_file) as simu_json:
|
|
201
|
+
# simu = json.load(simu_json)
|
|
202
|
+
#
|
|
203
|
+
# if output_file is not None and not os.path.exists(output_file):
|
|
204
|
+
# with open(output_file, "w") as out:
|
|
205
|
+
# out.write("delay,duration,amplitude,test_number,classification,r0,r1,r2,r3,r4,r5,r6,r7,r8,r9\n")
|
|
206
|
+
#
|
|
207
|
+
# params = [(amp, delay, duration, test_number) for amp in range(amplitudes[0], amplitudes[1] - 1, -1)
|
|
208
|
+
# for delay in range(delays[0], delays[1] + 1)
|
|
209
|
+
# for duration in range(durations[0], durations[1] + 1)
|
|
210
|
+
# for test_number in range(repetition)]
|
|
211
|
+
#
|
|
212
|
+
# with Traitor(traitor_port) as traitor, STM32Flash(stm32_port, hla_serial=stlink) as stm32_flash:
|
|
213
|
+
# traitor.clear()
|
|
214
|
+
# stm32_flash.program(program_file)
|
|
215
|
+
#
|
|
216
|
+
# traitor.execute_attack(stm32_flash)
|
|
217
|
+
# regs_normal = stm32_flash.ocd.read_all_registers()
|
|
218
|
+
# log.debug(f"{regs_normal = }")
|
|
219
|
+
# pc_normal = regs_normal["pc"]
|
|
220
|
+
#
|
|
221
|
+
# with logging_redirect_tqdm():
|
|
222
|
+
# for param in tqdm(params):
|
|
223
|
+
# amp, delay, duration, test_number = param
|
|
224
|
+
# faults = [(delay, duration)]
|
|
225
|
+
#
|
|
226
|
+
# try:
|
|
227
|
+
# traitor.execute_attack(stm32_flash, amp, faults)
|
|
228
|
+
#
|
|
229
|
+
# regs2 = stm32_flash.ocd.read_all_registers()
|
|
230
|
+
# pc = regs2["pc"]
|
|
231
|
+
# res = {reg: regs2[reg] for reg in filter_regs}
|
|
232
|
+
#
|
|
233
|
+
# if pc != pc_normal:
|
|
234
|
+
# classification = "crash"
|
|
235
|
+
# else:
|
|
236
|
+
# classification = []
|
|
237
|
+
# for exec_name, regs in simu["simulations"].items():
|
|
238
|
+
# if res == regs:
|
|
239
|
+
# classification.append(exec_name)
|
|
240
|
+
#
|
|
241
|
+
# if len(classification) == 0:
|
|
242
|
+
# classification = "undefined"
|
|
243
|
+
# elif len(classification) == 1:
|
|
244
|
+
# classification = classification[0]
|
|
245
|
+
# else:
|
|
246
|
+
# classification = f"\"{str(classification).replace(',', ';')}\""
|
|
247
|
+
# except KeyboardInterrupt:
|
|
248
|
+
# log.warning("Characterization canceled.")
|
|
249
|
+
# sys.exit(0)
|
|
250
|
+
# except:
|
|
251
|
+
# classification = "crash"
|
|
252
|
+
# res = {reg: -1 for reg in filter_regs}
|
|
253
|
+
# finally:
|
|
254
|
+
# if classification == "undefined":
|
|
255
|
+
# log.warning(f"({delay}, {duration}) / {amp} | {classification} - {res}")
|
|
256
|
+
# else:
|
|
257
|
+
# log.info(f"({delay}, {duration}) / {amp} | {classification} - {res}")
|
|
258
|
+
#
|
|
259
|
+
# if output_file is not None:
|
|
260
|
+
# with open(output_file, "a") as out:
|
|
261
|
+
# out_text = f"{delay},{duration},{amp},{test_number},{classification},"
|
|
262
|
+
# out_text += f"{res['r0']},{res['r1']},{res['r2']},{res['r3']},"
|
|
263
|
+
# out_text += f"{res['r4']},{res['r5']},{res['r6']},{res['r7']}"
|
|
264
|
+
# out_text += f"{res['r8']},{res['r9']}\n"
|
|
265
|
+
# out.write(out_text)
|
|
266
|
+
|
|
267
|
+
#
|
|
268
|
+
# @click.command()
|
|
269
|
+
# @click.argument('test_case_directory', required=1)
|
|
270
|
+
# @click.argument('traitor_port', required=1, type=str)
|
|
271
|
+
# @click.option('--stlink', default=None, type=str)
|
|
272
|
+
# def test_bkpt(test_case_directory, traitor_port, stlink):
|
|
273
|
+
# test_case_name = os.path.basename(os.path.normpath(test_case_directory))
|
|
274
|
+
# log.debug(f"Test case name: {test_case_name}")
|
|
275
|
+
# binary_file = os.path.join(os.path.abspath(test_case_directory), f"bin/{test_case_name}.elf")
|
|
276
|
+
#
|
|
277
|
+
# with Traitor(traitor_port) as traitor, STM32Flash(None, hla_serial=stlink) as stm32_flash:
|
|
278
|
+
# traitor.clear()
|
|
279
|
+
# stm32_flash.program(binary_file)
|
|
280
|
+
#
|
|
281
|
+
# bkpt_p1 = 0x80002b0
|
|
282
|
+
# # bkpt_p2 = 0x8000294
|
|
283
|
+
# bkpt_p2 = 0x800029c
|
|
284
|
+
#
|
|
285
|
+
# stm32_flash.reset()
|
|
286
|
+
# stm32_flash.halt()
|
|
287
|
+
# # stm32_flash.ocd.set_soft_breakpoint(bkpt_p1)
|
|
288
|
+
# # stm32_flash.ocd.set_soft_breakpoint(bkpt_p2)
|
|
289
|
+
#
|
|
290
|
+
# # stm32_flash.reset()
|
|
291
|
+
# # stm32_flash.halt()
|
|
292
|
+
# # stm32_flash.ocd.__send_str("w 0x80002aa 2 r value " + hex(bkpt_p1) + " \n")
|
|
293
|
+
# # stm32_flash.ocd.__read_until(b"> ")
|
|
294
|
+
# # stm32_flash.ocd.set_soft_breakpoint(bkpt_p1)
|
|
295
|
+
#
|
|
296
|
+
# traitor.execute_attack(stm32_flash)
|
|
297
|
+
# regs_normal = stm32_flash.ocd.read_all_registers()
|
|
298
|
+
# pc_normal = regs_normal["pc"]
|
|
299
|
+
# # log.debug(f"{regs_normal = }")
|
|
300
|
+
# log.debug(f"PC before attack 0x{pc_normal:0x}")
|
|
301
|
+
#
|
|
302
|
+
# # for i in range(10):
|
|
303
|
+
# # for j in range(10):
|
|
304
|
+
# # amp, delay, duration = (490, 48, 3)
|
|
305
|
+
# # faults = [(delay, duration)]
|
|
306
|
+
#
|
|
307
|
+
# # for bkpt in range(0x80002a8, 0x8000280, -2):
|
|
308
|
+
# # stm32_flash.reset()
|
|
309
|
+
# # stm32_flash.halt()
|
|
310
|
+
# # stm32_flash.ocd.enable_hard_breakpoint(bkpt)
|
|
311
|
+
#
|
|
312
|
+
# for amp in range(491, 500):
|
|
313
|
+
# for delay in range(35, 55):
|
|
314
|
+
# for duration in range(3, 7):
|
|
315
|
+
# faults = [(delay, duration)]
|
|
316
|
+
#
|
|
317
|
+
# try:
|
|
318
|
+
# traitor.execute_attack(stm32_flash, amp, faults)
|
|
319
|
+
# time.sleep(0.1)
|
|
320
|
+
# regs = stm32_flash.ocd.read_all_registers()
|
|
321
|
+
# # log.debug(f"{regs = }")
|
|
322
|
+
# pc_attack = regs["pc"]
|
|
323
|
+
# # log.debug(f"BKPT = 0x{bkpt:0x} - PC = 0x{pc_attack:0x}")
|
|
324
|
+
# log.debug(f"{amp} - ({delay}, {duration}) PC = 0x{pc_attack:0x}")
|
|
325
|
+
# except KeyboardInterrupt:
|
|
326
|
+
# log.warning("canceled.")
|
|
327
|
+
# sys.exit(0)
|
|
328
|
+
# except:
|
|
329
|
+
# log.warning("crash")
|
|
330
|
+
#
|
|
331
|
+
# # stm32_flash.reset()
|
|
332
|
+
# # stm32_flash.halt()
|
|
333
|
+
# # stm32_flash.ocd.disable_soft_breakpoints()
|
|
334
|
+
#
|
|
335
|
+
#
|
|
336
|
+
# @click.command()
|
|
337
|
+
# @click.argument('traitor_port', required=1, type=str)
|
|
338
|
+
# @click.argument('stm32_port', required=1, type=str)
|
|
339
|
+
# @click.argument('program_file', required=1, type=str)
|
|
340
|
+
# @click.argument('simulation_file', required=1, type=str)
|
|
341
|
+
# @click.argument('output_file', required=1, type=str)
|
|
342
|
+
# @click.option('--amplitudes', type=(int, int), default=(530, 460))
|
|
343
|
+
# @click.option('--delays', type=(int, int), default=(10, 20))
|
|
344
|
+
# @click.option('--durations', type=(int, int), default=(1, 15))
|
|
345
|
+
# @click.option('--repetition', required=False, type=int, default=10)
|
|
346
|
+
# @click.option('--stlink', default=None, type=str)
|
|
347
|
+
# def characterization(traitor_port, stm32_port, program_file, simulation_file, output_file,
|
|
348
|
+
# amplitudes, delays, durations, repetition, stlink):
|
|
349
|
+
# characterization_impl(traitor_port, stm32_port, program_file, simulation_file, output_file,
|
|
350
|
+
# amplitudes, delays, durations, repetition, stlink)
|
|
351
|
+
#
|
|
352
|
+
#
|
|
353
|
+
# @click.command()
|
|
354
|
+
# @click.argument('test_case_directory', required=1)
|
|
355
|
+
# @click.argument('traitor_port', required=1, type=str)
|
|
356
|
+
# @click.option('--amplitudes', type=(int, int), default=(530, 460))
|
|
357
|
+
# @click.option('--delays', type=(int, int), default=(10, 20))
|
|
358
|
+
# @click.option('--durations', type=(int, int), default=(1, 15))
|
|
359
|
+
# @click.option('--repetition', required=False, type=int, default=10)
|
|
360
|
+
# @click.option('--stlink', default=None, type=str)
|
|
361
|
+
# def test_case(test_case_directory, traitor_port, amplitudes, delays, durations, repetition, stlink):
|
|
362
|
+
# if not os.path.exists(test_case_directory):
|
|
363
|
+
# log.error(f"Test case directory '{test_case_directory}' does not exist!")
|
|
364
|
+
# sys.exit(-1)
|
|
365
|
+
#
|
|
366
|
+
# test_case_name = os.path.basename(os.path.normpath(test_case_directory))
|
|
367
|
+
# log.debug(f"Test case name: {test_case_name}")
|
|
368
|
+
#
|
|
369
|
+
# binary_file = os.path.join(os.path.abspath(test_case_directory), f"bin/{test_case_name}.elf")
|
|
370
|
+
# if not os.path.exists(binary_file):
|
|
371
|
+
# log.error(f"Binary file '{binary_file}' does not exist!")
|
|
372
|
+
# sys.exit(-1)
|
|
373
|
+
#
|
|
374
|
+
# simu_file = os.path.join(os.path.abspath(test_case_directory), "simulations.json")
|
|
375
|
+
# if not os.path.exists(simu_file):
|
|
376
|
+
# log.error(f"Simulations file '{simu_file}' does not exist!")
|
|
377
|
+
# sys.exit(-1)
|
|
378
|
+
#
|
|
379
|
+
# timestamp = str(time.strftime("%m%d%H%M%S"))
|
|
380
|
+
# output_file = os.path.join(os.path.abspath(test_case_directory), f"traitor/test_{timestamp}.csv")
|
|
381
|
+
# Path(output_file).parent.mkdir(exist_ok=True, parents=True)
|
|
382
|
+
#
|
|
383
|
+
# characterization_impl(traitor_port, None, binary_file, simu_file, output_file, amplitudes, delays,
|
|
384
|
+
# durations, repetition, stlink)
|
|
385
|
+
#
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# SAMVA, initial software
|
|
2
|
+
# Copyright © INRIA, Affero GPL v3, 2022, v 1.0
|
|
3
|
+
import logging
|
|
4
|
+
import os
|
|
5
|
+
from functools import partial
|
|
6
|
+
|
|
7
|
+
from samva.commands.commands_common import check_logging, must_be_chained
|
|
8
|
+
from samva.physical.boards.targets.cv32e40p_litex import CV32E40P_Litex
|
|
9
|
+
|
|
10
|
+
log = logging.getLogger(name=f"samva-{__name__}")
|
|
11
|
+
log.setLevel(logging.DEBUG)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@check_logging
|
|
15
|
+
@must_be_chained(False)
|
|
16
|
+
def run_cv32e40p(previous, *, port, verbose):
|
|
17
|
+
for binary_name in previous.keys():
|
|
18
|
+
samva = previous[binary_name]["samva"]
|
|
19
|
+
binary_file = samva.binary_file.replace(".elf", ".bin")
|
|
20
|
+
if not os.path.isfile(binary_file):
|
|
21
|
+
log.error(f"Binary file '{binary_file}' does not exist. It should be placed in the same directory as the .elf file.")
|
|
22
|
+
else:
|
|
23
|
+
previous[binary_name]["create_target"] = partial(CV32E40P_Litex, samva, port, binary_file)
|
|
24
|
+
return previous
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# SAMVA, initial software
|
|
2
|
+
# Copyright © INRIA, Affero GPL v3, 2022, v 1.0
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from samva.commands.commands_common import check_logging, must_be_chained, hardware_attack
|
|
6
|
+
from samva.physical.analysis.samva_file_line import convert_attack_path
|
|
7
|
+
|
|
8
|
+
log = logging.getLogger(name=f"samva-{__name__}")
|
|
9
|
+
log.setLevel(logging.DEBUG)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@check_logging
|
|
13
|
+
@must_be_chained(True)
|
|
14
|
+
@hardware_attack
|
|
15
|
+
def run_debugger(previous, *, target, binary_name, verbose):
|
|
16
|
+
if "samva" not in previous[binary_name] or "attack_result" not in previous[binary_name]:
|
|
17
|
+
log.error(f"Cannot run debugger validation on {binary_name} if an analysis is not run before.")
|
|
18
|
+
return 0, 0
|
|
19
|
+
|
|
20
|
+
samva = previous[binary_name]["samva"]
|
|
21
|
+
attack_result = previous[binary_name]["attack_result"]
|
|
22
|
+
iter_max = len(attack_result.attack_paths)
|
|
23
|
+
validated_counter = 0
|
|
24
|
+
|
|
25
|
+
with target:
|
|
26
|
+
for i, attack_path in enumerate(attack_result.attack_paths[:iter_max]):
|
|
27
|
+
samva_lines = convert_attack_path(attack_path)
|
|
28
|
+
|
|
29
|
+
initial_values = samva.samva_model.convert_simulation_states(samva.samva_model.attack_options.simulation_initial_state)
|
|
30
|
+
final_values = samva.samva_model.convert_simulation_states(samva.samva_model.attack_options.simulation_final_state)
|
|
31
|
+
|
|
32
|
+
validated = target.validate_instruction_skip_attack(samva_lines, initial_values=initial_values,
|
|
33
|
+
final_values=final_values)
|
|
34
|
+
if validated:
|
|
35
|
+
validated_counter += 1
|
|
36
|
+
|
|
37
|
+
return iter_max, validated_counter
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# SAMVA, initial software
|
|
2
|
+
# Copyright © INRIA, Affero GPL v3, 2022, v 1.0
|
|
3
|
+
import logging
|
|
4
|
+
import os
|
|
5
|
+
import re
|
|
6
|
+
import time
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
|
|
10
|
+
from samva.commands.commands_common import check_logging, must_be_chained
|
|
11
|
+
from samva.core import Samva
|
|
12
|
+
from samva.core.common import FaultParameters, FaultModel
|
|
13
|
+
from samva.core.common.analysis_utils import Timing
|
|
14
|
+
from samva.evaluator import EvaluatorSimulationUnicorn2, EvaluatorSimulationGem5
|
|
15
|
+
|
|
16
|
+
log = logging.getLogger(name=f"samva-{__name__}")
|
|
17
|
+
log.setLevel(logging.DEBUG)
|
|
18
|
+
|
|
19
|
+
SAMVA_DEFAULT_RESULT_DIRECTORY = "samva_results"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def prepare_result_folder(result_folder, fault_model, strategy):
|
|
23
|
+
timestamp = str(time.strftime("%Y%m%d_%H%M%S"))
|
|
24
|
+
result_folder = os.path.join(click.format_filename(result_folder),
|
|
25
|
+
"bench_" + fault_model + "_" + strategy + "_" + timestamp + "/")
|
|
26
|
+
os.mkdir(result_folder)
|
|
27
|
+
return result_folder
|
|
28
|
+
|
|
29
|
+
def input_fault_model(fault_model: str) -> FaultModel:
|
|
30
|
+
if fault_model == "TrueNOP":
|
|
31
|
+
return FaultModel.TrueNOP
|
|
32
|
+
elif fault_model == "Replay":
|
|
33
|
+
return FaultModel.Replay
|
|
34
|
+
else:
|
|
35
|
+
return FaultModel.TrueNOP
|
|
36
|
+
|
|
37
|
+
def get_configuration_file_from_binary_name(binary_file: str) -> str:
|
|
38
|
+
f = os.path.splitext(os.path.basename(binary_file))[0]
|
|
39
|
+
conf_file_name = f"{f}.json"
|
|
40
|
+
if "_alig" in binary_file:
|
|
41
|
+
conf_file_name = re.sub(r"_alig\d?", "", conf_file_name)
|
|
42
|
+
pass
|
|
43
|
+
return conf_file_name
|
|
44
|
+
|
|
45
|
+
@check_logging
|
|
46
|
+
@must_be_chained(False)
|
|
47
|
+
def run_evaluate(previous, *, bin_path, samva_config_path, result_folder, fault_model, fault_parameters,
|
|
48
|
+
max_paths_per_segment, max_cost_per_segment, max_cost_for_simulation, max_attack_paths, evaluator,
|
|
49
|
+
unicorn_full_init, log_variable, timeout, stop_at_robustness, deprecated,
|
|
50
|
+
deprecated_exhaustive, deprecated_max_solutions, verbose) -> dict:
|
|
51
|
+
|
|
52
|
+
if not os.path.exists(bin_path):
|
|
53
|
+
raise FileNotFoundError(f"Binary path {bin_path} does not exist.")
|
|
54
|
+
if not os.path.exists(samva_config_path):
|
|
55
|
+
raise FileNotFoundError(f"Samva configuration path {samva_config_path} does not exist.")
|
|
56
|
+
|
|
57
|
+
bin_path_is_file = os.path.isfile(bin_path)
|
|
58
|
+
samva_config_path_is_file = os.path.isfile(samva_config_path)
|
|
59
|
+
if not bin_path_is_file and samva_config_path_is_file:
|
|
60
|
+
raise ValueError("Cannot use a binary folder and a single samva configuration file")
|
|
61
|
+
|
|
62
|
+
strategy = "default" # will be removed.
|
|
63
|
+
timeout = None if timeout <= 0 else timeout
|
|
64
|
+
fake_timeout = 999999
|
|
65
|
+
fault_parameters = FaultParameters(fault_parameters[0], fault_parameters[1], fault_parameters[2], fake_timeout)
|
|
66
|
+
if fault_model == "TrueNOP":
|
|
67
|
+
fault_model = FaultModel.TrueNOP
|
|
68
|
+
elif fault_model == "Replay":
|
|
69
|
+
fault_model = FaultModel.Replay
|
|
70
|
+
else:
|
|
71
|
+
raise ValueError("Provided fault model option is incorrect.")
|
|
72
|
+
|
|
73
|
+
samva_list: list[Samva] = []
|
|
74
|
+
if bin_path_is_file and samva_config_path_is_file:
|
|
75
|
+
samva_list.append(
|
|
76
|
+
Samva(
|
|
77
|
+
bin_path,
|
|
78
|
+
config_file=samva_config_path,
|
|
79
|
+
fault_model=fault_model,
|
|
80
|
+
strategy=strategy,
|
|
81
|
+
exhaustive=deprecated_exhaustive,
|
|
82
|
+
)
|
|
83
|
+
)
|
|
84
|
+
elif bin_path_is_file and not samva_config_path_is_file:
|
|
85
|
+
conf_file_name = get_configuration_file_from_binary_name(bin_path)
|
|
86
|
+
suggested_samva_config_path = os.path.abspath(os.path.join(samva_config_path, conf_file_name))
|
|
87
|
+
if not os.path.isfile(suggested_samva_config_path):
|
|
88
|
+
raise FileNotFoundError(f"Attack file does not exist: {suggested_samva_config_path}")
|
|
89
|
+
samva_list.append(
|
|
90
|
+
Samva(
|
|
91
|
+
bin_path,
|
|
92
|
+
config_file=suggested_samva_config_path,
|
|
93
|
+
fault_model=fault_model,
|
|
94
|
+
strategy=strategy,
|
|
95
|
+
exhaustive=deprecated_exhaustive,
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
else:
|
|
99
|
+
found_pairs = []
|
|
100
|
+
for f in os.listdir(bin_path):
|
|
101
|
+
if not f.endswith(".elf"):
|
|
102
|
+
continue
|
|
103
|
+
conf_file_name = get_configuration_file_from_binary_name(f)
|
|
104
|
+
suggested_samva_config_path = os.path.abspath(os.path.join(samva_config_path, conf_file_name))
|
|
105
|
+
if not os.path.isfile(suggested_samva_config_path):
|
|
106
|
+
continue
|
|
107
|
+
log.info(f"Found the binary {f} and its corresponding configuration file {suggested_samva_config_path}.")
|
|
108
|
+
found_pairs.append((os.path.join(bin_path, f), suggested_samva_config_path))
|
|
109
|
+
for bin_file, conf_file in found_pairs:
|
|
110
|
+
samva_list.append(
|
|
111
|
+
Samva(
|
|
112
|
+
bin_file,
|
|
113
|
+
config_file=conf_file,
|
|
114
|
+
fault_model=fault_model,
|
|
115
|
+
strategy=strategy,
|
|
116
|
+
exhaustive=deprecated_exhaustive,
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
if len(found_pairs) == 0:
|
|
120
|
+
log.info("Unable to found pairs elf file / samva configuration file.")
|
|
121
|
+
|
|
122
|
+
if result_folder is None:
|
|
123
|
+
if not os.path.isdir(SAMVA_DEFAULT_RESULT_DIRECTORY):
|
|
124
|
+
os.mkdir(SAMVA_DEFAULT_RESULT_DIRECTORY)
|
|
125
|
+
result_folder = prepare_result_folder(SAMVA_DEFAULT_RESULT_DIRECTORY, fault_model.value, strategy)
|
|
126
|
+
|
|
127
|
+
match evaluator:
|
|
128
|
+
case "unicorn":
|
|
129
|
+
samva_evaluator = EvaluatorSimulationUnicorn2(
|
|
130
|
+
fault_model=fault_model,
|
|
131
|
+
result_folder=result_folder,
|
|
132
|
+
enable_log=True,
|
|
133
|
+
write_nop_files=True,
|
|
134
|
+
log_variables=log_variable,
|
|
135
|
+
disable_full_init=not unicorn_full_init,
|
|
136
|
+
)
|
|
137
|
+
case "gem5":
|
|
138
|
+
samva_evaluator = EvaluatorSimulationGem5(
|
|
139
|
+
result_folder=result_folder, enable_log=True, write_nop_files=True, log_variables=log_variable
|
|
140
|
+
)
|
|
141
|
+
case _:
|
|
142
|
+
samva_evaluator = None
|
|
143
|
+
|
|
144
|
+
result = {}
|
|
145
|
+
for samva in samva_list:
|
|
146
|
+
with Timing() as t_analysis:
|
|
147
|
+
if deprecated:
|
|
148
|
+
attack_result = samva.find_attack_paths(fault_parameters, deprecated_max_solutions, samva_evaluator)
|
|
149
|
+
else:
|
|
150
|
+
attack_result = samva.find_data_aware_attack_paths(
|
|
151
|
+
fault_parameters,
|
|
152
|
+
samva_evaluator,
|
|
153
|
+
max_paths_per_segment=max_paths_per_segment,
|
|
154
|
+
max_cost_per_segment=max_cost_per_segment,
|
|
155
|
+
max_cost_for_simulation=max_cost_for_simulation,
|
|
156
|
+
max_attack_paths=max_attack_paths,
|
|
157
|
+
stop_when_robustness_found=stop_at_robustness,
|
|
158
|
+
timeout=timeout,
|
|
159
|
+
)
|
|
160
|
+
if max_attack_paths is not None:
|
|
161
|
+
attack_result.attack_paths = attack_result.attack_paths[:max_attack_paths]
|
|
162
|
+
|
|
163
|
+
txt = []
|
|
164
|
+
binary_name = samva.samva_model.binary_name
|
|
165
|
+
if attack_result.attack_paths is None:
|
|
166
|
+
txt.append(f"{binary_name} - Specified fault parameters are not suited for this binary.")
|
|
167
|
+
elif len(attack_result.attack_paths) == 0:
|
|
168
|
+
txt.append(f"{binary_name} - No attack path found.")
|
|
169
|
+
else:
|
|
170
|
+
txt.append(f"{binary_name} - {len(attack_result.attack_paths)} attack paths found.")
|
|
171
|
+
if attack_result.robustness is not None:
|
|
172
|
+
txt.append(" " * len(binary_name) + f" Robustness level is {attack_result.robustness}.")
|
|
173
|
+
txt.append(" " * len(binary_name) + f" Analysis concluded in {t_analysis}")
|
|
174
|
+
if verbose and not deprecated:
|
|
175
|
+
txt.append(" " * len(binary_name) + f" Candidate stats: {samva.cstats}")
|
|
176
|
+
txt.append(" " * len(binary_name) + f" Evaluation stats: {samva.estats}")
|
|
177
|
+
|
|
178
|
+
for lign in txt:
|
|
179
|
+
log.info(lign)
|
|
180
|
+
|
|
181
|
+
result[binary_name] = {}
|
|
182
|
+
result[binary_name]["samva"] = samva
|
|
183
|
+
result[binary_name]["attack_result"] = attack_result
|
|
184
|
+
result[binary_name]["log"] = txt
|
|
185
|
+
|
|
186
|
+
return result
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# SAMVA, initial software
|
|
2
|
+
# Copyright © INRIA, Affero GPL v3, 2022, v 1.0
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from samva.commands.commands_common import check_logging, must_be_chained
|
|
6
|
+
from samva.core.common import AttackPointTarget
|
|
7
|
+
|
|
8
|
+
log = logging.getLogger(name=f"samva-{__name__}")
|
|
9
|
+
log.setLevel(logging.DEBUG)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@check_logging
|
|
13
|
+
@must_be_chained(True)
|
|
14
|
+
def run_measure_cycles(previous, *, addr1 , addr2, verbose):
|
|
15
|
+
log.info(f"Measure cycles between {addr1} and {addr2}")
|
|
16
|
+
|
|
17
|
+
for binary_name in previous.keys():
|
|
18
|
+
if "create_target" not in previous[binary_name]:
|
|
19
|
+
log.warning(f"Cannot find target for binary {binary_name}")
|
|
20
|
+
continue
|
|
21
|
+
|
|
22
|
+
if "samva" not in previous[binary_name]:
|
|
23
|
+
log.warning(f"Cannot find samva for binary {binary_name}")
|
|
24
|
+
continue
|
|
25
|
+
|
|
26
|
+
samva = previous[binary_name]["samva"]
|
|
27
|
+
addr1 = samva.samva_model.retrieve_address_from_string(addr1, AttackPointTarget.INSTR)
|
|
28
|
+
addr2 = samva.samva_model.retrieve_address_from_string(addr2, AttackPointTarget.INSTR)
|
|
29
|
+
|
|
30
|
+
create_target = previous[binary_name]["create_target"]
|
|
31
|
+
target = create_target()
|
|
32
|
+
|
|
33
|
+
with target:
|
|
34
|
+
measures = target.measure_cycles(addr1, addr2, must_reset=True)
|
|
35
|
+
|
|
36
|
+
if measures is not None:
|
|
37
|
+
sum_cycles = sum(i[1] for i in measures)
|
|
38
|
+
log.info(f"Measured number of cycles: {sum_cycles}")
|
|
39
|
+
previous[binary_name]["measure_cycle"] = sum_cycles
|
|
40
|
+
else:
|
|
41
|
+
log.warning(f"Cannot measure cycles for binary {binary_name}")
|
|
42
|
+
|
|
43
|
+
return previous
|