diff --git a/capture/capture_kmac.py b/capture/capture_kmac.py index 60e4ccf4..1d68fb61 100755 --- a/capture/capture_kmac.py +++ b/capture/capture_kmac.py @@ -23,7 +23,8 @@ from Crypto.Hash import KMAC128 from lib.ot_communication import OTKMAC from project_library.project import ProjectConfig, SCAProject -from scopes.scope import Scope, ScopeConfig +from scopes.cycle_converter import convert_num_cycles, convert_offset_cycles +from scopes.scope import Scope, ScopeConfig, determine_sampling_rate from tqdm import tqdm sys.path.append("../") @@ -72,6 +73,11 @@ def setup(cfg: dict, project: Path): Returns: The target, scope, and project. """ + # Calculate pll_frequency of the target. + # target_freq = pll_frequency * target_clk_mult + # target_clk_mult is a hardcoded constant in the FPGA bitstream. + cfg["target"]["pll_frequency"] = cfg["target"]["target_freq"] / cfg["target"]["target_clk_mult"] + # Init target. logger.info(f"Initializing target {cfg['target']['target_type']} ...") target = CWFPGA( @@ -85,13 +91,24 @@ def setup(cfg: dict, project: Path): # Init scope. scope_type = cfg["capture"]["scope_select"] - logger.info(f"Initializing scope {scope_type} ...") + + # Determine sampling rate, if necessary. + cfg[scope_type]["sampling_rate"] = determine_sampling_rate(cfg, scope_type) + # Convert number of cycles into number of samples, if necessary. + cfg[scope_type]["num_samples"] = convert_num_cycles(cfg, scope_type) + # Convert offset in cycles into offset in samples, if necessary. + cfg[scope_type]["offset_samples"] = convert_offset_cycles(cfg, scope_type) + + logger.info(f"Initializing scope {scope_type} with a sampling rate of {cfg[scope_type]['sampling_rate']}...") # noqa: E501 + + # Create scope config & setup scope. scope_cfg = ScopeConfig( scope_type = scope_type, acqu_channel = cfg[scope_type].get("channel"), ip = cfg[scope_type].get("waverunner_ip"), - num_samples = cfg[scope_type].get("num_samples"), - offset_samples = cfg[scope_type].get("offset_samples"), + num_samples = cfg[scope_type]["num_samples"], + offset_samples = cfg[scope_type]["offset_samples"], + sampling_rate = cfg[scope_type].get("sampling_rate"), num_segments = cfg[scope_type]["num_segments"], sparsing = cfg[scope_type].get("sparsing"), scope_gain = cfg[scope_type].get("scope_gain"), @@ -230,7 +247,6 @@ def capture(scope: Scope, ot_kmac: OTKMAC, capture_cfg: CaptureConfig, Supports four different capture types: * kmac_random: Fixed key, random plaintext. - * kmac_random_batch: Fixed key, random plaintext in batch mode. * kmac_fvsr: Fixed vs. random key. * kmac_fvsr_batch: Fixed vs. random key batch. @@ -270,6 +286,7 @@ def capture(scope: Scope, ot_kmac: OTKMAC, capture_cfg: CaptureConfig, while remaining_num_traces > 0: # Arm the scope. scope.arm() + # Trigger encryption. if capture_cfg.batch_mode: # Batch mode. Is always kmac_fvsr_key @@ -340,7 +357,7 @@ def capture(scope: Scope, ot_kmac: OTKMAC, capture_cfg: CaptureConfig, pbar.update(capture_cfg.num_segments) -def print_plot(project: SCAProject, config: dict) -> None: +def print_plot(project: SCAProject, config: dict, file: Path) -> None: """ Print plot of traces. Printing the plot helps to adjust the scope gain and check for clipping. @@ -348,15 +365,16 @@ def print_plot(project: SCAProject, config: dict) -> None: Args: project: The project containing the traces. config: The capture configuration. + file: The output file path. """ if config["capture"]["show_plot"]: plot.save_plot_to_file(project.get_waves(0, config["capture"]["plot_traces"]), set_indices = None, num_traces = config["capture"]["plot_traces"], - outfile = config["capture"]["trace_image_filename"], + outfile = file, add_mean_stddev=True) print(f'Created plot with {config["capture"]["plot_traces"]} traces: ' - f'{Path(config["capture"]["trace_image_filename"]).resolve()}') + f'{Path(str(file) + ".html").resolve()}') def main(argv=None): @@ -409,7 +427,7 @@ def main(argv=None): capture(scope, ot_kmac, capture_cfg, project, target) # Print plot. - print_plot(project, cfg) + print_plot(project, cfg, args.project) # Save metadata. metadata = {} diff --git a/capture/configs/capture_kmac_cw310.yaml b/capture/configs/kmac_cw310.yaml similarity index 94% rename from capture/configs/capture_kmac_cw310.yaml rename to capture/configs/kmac_cw310.yaml index 8467ab60..67f369ed 100644 --- a/capture/configs/capture_kmac_cw310.yaml +++ b/capture/configs/kmac_cw310.yaml @@ -3,12 +3,12 @@ target: fpga_bitstream: ../objs/lowrisc_systems_chip_earlgrey_cw310_0.1_kmac_dom.bit force_program_bitstream: False fw_bin: ../objs/kmac_serial_fpga_cw310.bin - pll_frequency: 100000000 + target_clk_mult: 0.24 + target_freq: 24000000 baudrate: 115200 output_len_bytes: 32 husky: - pll_frequency: 100000000 - target_clk_mult: 0.24 + sampling_rate: 200000000 num_segments: 20 # Number of target clock cycles per trace - KMAC is doing 24 or 96 cycles # for the key absorb w/o or w/ DOM, respectively, as well as 23 cycles for @@ -17,7 +17,6 @@ husky: #num_cycles: 80 # w/ DOM num_cycles: 160 - num_samples: 10 #fixme # Offset in target clock cycles - During the first activity block, KMAC # just absorbs the fixed prefix (23 cycles XORing + 24 or 96 cycles # absorbing w/o or w/ DOM, respectively). This first activity block can be @@ -26,7 +25,6 @@ husky: #offset_cyles: 43 # w/ DOM offset_cycles: 115 - offset_samples: 1 #fixme scope_gain: 26 capture: scope_select: husky