From b187a92f77a354039054a2f107565f69f4aff21f Mon Sep 17 00:00:00 2001 From: Andrej Bátora Date: Mon, 27 Nov 2023 15:49:14 +0100 Subject: renamed file and target class --- pyecsca/codegen/client.py | 74 +++++++-------- test/test_emulator.py | 233 ++++++++++++++++++++++++++++++++++++++++++++++ test/test_simulator.py | 233 ---------------------------------------------- 3 files changed, 270 insertions(+), 270 deletions(-) create mode 100644 test/test_emulator.py delete mode 100644 test/test_simulator.py diff --git a/pyecsca/codegen/client.py b/pyecsca/codegen/client.py index 740cb57..989b47b 100644 --- a/pyecsca/codegen/client.py +++ b/pyecsca/codegen/client.py @@ -189,9 +189,9 @@ def cmd_debug() -> str: return "d" -class SimulatorTarget(Target): +class EmulatorTarget(Target): - simulator: rainbow_stm32f215 + emulator: rainbow_stm32f215 result: list model: CurveModel coords: CoordinateModel @@ -204,7 +204,7 @@ class SimulatorTarget(Target): def __init__(self, model: CurveModel, coords: CoordinateModel, print_config: Print = Print(0), trace_config: TraceConfig = TraceConfig(), allow_breakpoints: bool = False): super().__init__() - self.simulator = rainbow_stm32f215(print_config=print_config, trace_config=trace_config, + self.emulator = rainbow_stm32f215(print_config=print_config, trace_config=trace_config, allow_stubs=True, allow_breakpoints=allow_breakpoints) self.result = [] self.trace = [] @@ -215,59 +215,59 @@ class SimulatorTarget(Target): self.privkey = None self.pubkey = None - def __simulate(self, command: str, function: str) -> None: + def __emulate(self, command: str, function: str) -> None: data = unhexlify(command[1:]) length = len(data) data_adress = 0xDEAD0000 - self.simulator[data_adress] = data - self.simulator['r0'] = data_adress - self.simulator['r1'] = length - self.simulator.start(self.simulator.functions[function] | 1, 0) - self.trace.extend(self.simulator.trace) - self.simulator.reset() + self.emulator[data_adress] = data + self.emulator['r0'] = data_adress + self.emulator['r1'] = length + self.emulator.start(self.emulator.functions[function] | 1, 0) + self.trace.extend(self.emulator.trace) + self.emulator.reset() def connect(self, **kwargs) -> None: - self.simulator.load(kwargs["binary"]) - self.simulator.setup() - self.simulator.start(self.simulator.functions['init_implementation'] | 1, 0) - self.simulator.reset() + self.emulator.load(kwargs["binary"]) + self.emulator.setup() + self.emulator.start(self.emulator.functions['init_implementation'] | 1, 0) + self.emulator.reset() def set_params(self, params: DomainParameters) -> None: command = cmd_set_params(params) - self.__simulate(command, 'cmd_set_params') + self.__emulate(command, 'cmd_set_params') self.params = params - def __scalar_mult_hook(self, simulator) -> None: - point_length = simulator['r1'] // len(self.coords.variables) - res_adress = simulator['r2'] - self.result.append({var: Mod(int.from_bytes(simulator[res_adress + i * point_length: + def __scalar_mult_hook(self, emulator) -> None: + point_length = emulator['r1'] // len(self.coords.variables) + res_adress = emulator['r2'] + self.result.append({var: Mod(int.from_bytes(emulator[res_adress + i * point_length: res_adress + (i + 1) * point_length], 'big'), self.params.curve.prime) for i, var in enumerate(self.coords.variables)}) def scalar_mult(self, scalar: int, point: Point) -> Point: self.result = [] - self.simulator.hook_bypass("simpleserial_put", self.__scalar_mult_hook) + self.emulator.hook_bypass("simpleserial_put", self.__scalar_mult_hook) command = cmd_scalar_mult(scalar, point) - self.__simulate(command, 'cmd_scalar_mult') + self.__emulate(command, 'cmd_scalar_mult') return Point(self.coords, **self.result[0]) def init_prng(self, seed: bytes) -> None: command = cmd_init_prng(seed) - self.__simulate(command, 'cmd_init_prng') + self.__emulate(command, 'cmd_init_prng') self.seed = seed - def __generate_hook(self, simulator) -> None: - key_length = simulator['r1'] - key_bytes = simulator[simulator['r2']: simulator['r2'] + key_length] + def __generate_hook(self, emulator) -> None: + key_length = emulator['r1'] + key_bytes = emulator[emulator['r2']: emulator['r2'] + key_length] self.result.append(key_length) self.result.append(key_bytes) def generate(self) -> Tuple[int, Point]: self.result = [] - self.simulator.hook_bypass("simpleserial_put", self.__generate_hook) + self.emulator.hook_bypass("simpleserial_put", self.__generate_hook) command = cmd_generate() - self.__simulate(command, 'cmd_generate') + self.__emulate(command, 'cmd_generate') priv = int.from_bytes(self.result[1], 'big') pub_x = int.from_bytes(self.result[3][0:self.result[2] // 2], 'big') pub_y = int.from_bytes(self.result[3][self.result[2] // 2:self.result[2]] ,'big') @@ -276,12 +276,12 @@ class SimulatorTarget(Target): def set_privkey(self, privkey: int) -> None: command = cmd_set_privkey(privkey) - self.__simulate(command, 'cmd_set_privkey') + self.__emulate(command, 'cmd_set_privkey') self.privkey = privkey def set_pubkey(self, pubkey: Point) -> None: command = cmd_set_pubkey(pubkey) - self.__simulate(command, 'cmd_set_pubkey') + self.__emulate(command, 'cmd_set_pubkey') self.pubkey = pubkey def __ec_hook(self, simulator) -> None: @@ -289,25 +289,25 @@ class SimulatorTarget(Target): def ecdh(self, other_pubkey: Point) -> bytes: self.result = [] - self.simulator.hook_bypass("simpleserial_put", self.__ec_hook) + self.emulator.hook_bypass("simpleserial_put", self.__ec_hook) command = cmd_ecdh(other_pubkey) - self.__simulate(command, 'cmd_ecdh') + self.__emulate(command, 'cmd_ecdh') shared_secret = self.result[0] return shared_secret def ecdsa_sign(self, data: bytes) -> bytes: self.result = [] - self.simulator.hook_bypass("simpleserial_put", self.__ec_hook) + self.emulator.hook_bypass("simpleserial_put", self.__ec_hook) command = cmd_ecdsa_sign(data) - self.__simulate(command, 'cmd_ecdsa_sign') + self.__emulate(command, 'cmd_ecdsa_sign') signature = self.result[0] return signature def ecdsa_verify(self, data: bytes, signature: bytes) -> bool: self.result = [] - self.simulator.hook_bypass("simpleserial_put", self.__ec_hook) + self.emulator.hook_bypass("simpleserial_put", self.__ec_hook) command = cmd_ecdsa_verify(data, signature) - self.__simulate(command, 'cmd_ecdsa_verify') + self.__emulate(command, 'cmd_ecdsa_verify') return bool(int.from_bytes(self.result[0], 'big')) def set_strigger(self): @@ -320,8 +320,8 @@ class SimulatorTarget(Target): pass def disconnect(self): - self.simulator.start(self.simulator.functions['deinit'] | 1, 0) - self.simulator.reset() + self.emulator.start(self.emulator.functions['deinit'] | 1, 0) + self.emulator.reset() diff --git a/test/test_emulator.py b/test/test_emulator.py new file mode 100644 index 0000000..93ca074 --- /dev/null +++ b/test/test_emulator.py @@ -0,0 +1,233 @@ +from copy import copy +from os.path import join +import pytest + +from pyecsca.ec.key_agreement import ECDH_SHA1 +from pyecsca.ec.mult import LTRMultiplier, RTLMultiplier +from pyecsca.ec.signature import ECDSA_SHA1, SignatureResult +from rainbow import TraceConfig, HammingWeight + +from pyecsca.codegen.builder import build_impl +from pyecsca.codegen.client import EmulatorTarget + +from pyecsca.ec.curve import EllipticCurve +from pyecsca.ec.mod import Mod +from pyecsca.ec.model import ShortWeierstrassModel +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.point import InfinityPoint, Point +import gc + + +@pytest.fixture(scope="module") +def curve32(): + model = ShortWeierstrassModel() + coords = model.coordinates["projective"] + p = 0xD7D1247F + a = Mod(0xA4A44016, p) + b = Mod(0x73F76716, p) + n = 0xD7D2A475 + h = 1 + gx, gy, gz = Mod(0x54EED6D7, p), Mod(0x6F1E55AC, p), Mod(1, p) + generator = Point(coords, X=gx, Y=gy, Z=gz) + neutral = InfinityPoint(coords) + + curve = EllipticCurve(model, coords, p, neutral, {"a": a, "b": b}) + params = DomainParameters(curve, generator, n, h) + return params + + +def do_basic_test( + callback, runner, params, mult_class, formulas, mult_name, ecdsa, ecdh +): + with runner.isolated_filesystem() as tmpdir: + runner.invoke( + build_impl, + [ + "--platform", + "STM32F3", + "--ecdsa" if ecdsa else "--no-ecdsa", + "--ecdh" if ecdh else "--no-ecdh", + "--red", + "MONTGOMERY", + "-D", + "BN_NON_CONST", + params.curve.model.shortname, + params.curve.coordinate_model.name, + *formulas, + f"{mult_name}()", + ".", + ], + ) + target = EmulatorTarget(params.curve.model, params.curve.coordinate_model) + target.connect(binary=join(tmpdir, "pyecsca-codegen-CW308_STM32F3.elf")) + target.set_params(params) + formula_instances = [ + params.curve.coordinate_model.formulas[formula] for formula in formulas + ] + mult = mult_class(*formula_instances) + mult.init(params, params.generator) + callback(target, mult, params) + target.disconnect() + del target + gc.collect() + + +def test_init(cli_runner, curve32): + def callback(target, mult, params): + target.init_prng(bytes([0x12, 0x34, 0x56, 0x78])) + + do_basic_test( + callback, + cli_runner, + curve32, + LTRMultiplier, + ["add-1998-cmo", "dbl-1998-cmo"], + "ltr", + False, + False, + ) + + +def test_setup(cli_runner, curve32): + def callback(target, mult, params): + priv = 57 + pub = mult.multiply(priv).to_affine() + target.set_privkey(priv) + target.set_pubkey(pub) + + do_basic_test( + callback, + cli_runner, + curve32, + LTRMultiplier, + ["add-1998-cmo", "dbl-1998-cmo"], + "ltr", + False, + False, + ) + + +def test_debug(cli_runner, curve32): + def callback(target, mult, params): + model, coords = target.debug() + assert model == params.curve.model.shortname + assert coords == params.curve.coordinate_model.name + + do_basic_test( + callback, + cli_runner, + curve32, + LTRMultiplier, + ["add-1998-cmo", "dbl-1998-cmo"], + "ltr", + False, + False, + ) + + +@pytest.mark.parametrize( + "mult_name,mult_class", [("ltr", LTRMultiplier), ("rtl", RTLMultiplier)] +) +def test_keygen(mult_name, mult_class, cli_runner, curve32): + def callback(target, mult, params): + priv, pub = target.generate() + assert params.curve.is_on_curve(pub) + expected = mult.multiply(priv).to_affine() + assert pub == expected + + do_basic_test( + callback, + cli_runner, + curve32, + mult_class, + ["add-1998-cmo", "dbl-1998-cmo"], + mult_name, + False, + False, + ) + + +@pytest.mark.parametrize( + "mult_name,mult_class", [("ltr", LTRMultiplier), ("rtl", RTLMultiplier)] +) +def test_scalarmult(mult_name, mult_class, cli_runner, curve32): + values = [2355498743] + + def callback(target, mult, params): + for value in values: + result = target.scalar_mult(value, params.generator) + expected = mult.multiply(value) + assert result == expected + + do_basic_test( + callback, + cli_runner, + curve32, + mult_class, + ["add-1998-cmo", "dbl-1998-cmo"], + mult_name, + False, + False, + ) + + +@pytest.mark.parametrize( + "mult_name,mult_class", [("ltr", LTRMultiplier), ("rtl", RTLMultiplier)] +) +def test_ecdh(mult_name, mult_class, cli_runner, curve32): + other_privs = [2355498743] + + def callback(target, mult, params): + for other_priv in other_privs: + priv, pub = target.generate() + other_pub = mult.multiply(other_priv) + ecdh = ECDH_SHA1(copy(mult), params, other_pub, priv) + result = target.ecdh(other_pub) + expected = ecdh.perform() + assert result == expected + + do_basic_test( + callback, + cli_runner, + curve32, + mult_class, + ["add-1998-cmo", "dbl-1998-cmo"], + mult_name, + False, + True, + ) + + +@pytest.mark.parametrize( + "mult_name,mult_class", [("ltr", LTRMultiplier), ("rtl", RTLMultiplier)] +) +def test_ecdsa(mult_name, mult_class, cli_runner, curve32): + data = b"something" + + def callback(target, mult, params): + priv, pub = target.generate() + ecdsa = ECDSA_SHA1( + copy(mult), + params, + mult.formulas["add"], + pub.to_model(params.curve.coordinate_model, params.curve), + priv, + ) + + signature_data = target.ecdsa_sign(data) + result = SignatureResult.from_DER(bytes(signature_data)) + assert ecdsa.verify_data(result, data) + + expected = ecdsa.sign_data(data).to_DER() + assert target.ecdsa_verify(data, expected) + + do_basic_test( + callback, + cli_runner, + curve32, + mult_class, + ["add-1998-cmo", "dbl-1998-cmo"], + mult_name, + True, + False, + ) diff --git a/test/test_simulator.py b/test/test_simulator.py deleted file mode 100644 index 8ce38e4..0000000 --- a/test/test_simulator.py +++ /dev/null @@ -1,233 +0,0 @@ -from copy import copy -from os.path import join -import pytest - -from pyecsca.ec.key_agreement import ECDH_SHA1 -from pyecsca.ec.mult import LTRMultiplier, RTLMultiplier -from pyecsca.ec.signature import ECDSA_SHA1, SignatureResult -from rainbow import TraceConfig, HammingWeight - -from pyecsca.codegen.builder import build_impl -from pyecsca.codegen.client import SimulatorTarget - -from pyecsca.ec.curve import EllipticCurve -from pyecsca.ec.mod import Mod -from pyecsca.ec.model import ShortWeierstrassModel -from pyecsca.ec.params import DomainParameters -from pyecsca.ec.point import InfinityPoint, Point -import gc - - -@pytest.fixture(scope="module") -def curve32(): - model = ShortWeierstrassModel() - coords = model.coordinates["projective"] - p = 0xD7D1247F - a = Mod(0xA4A44016, p) - b = Mod(0x73F76716, p) - n = 0xD7D2A475 - h = 1 - gx, gy, gz = Mod(0x54EED6D7, p), Mod(0x6F1E55AC, p), Mod(1, p) - generator = Point(coords, X=gx, Y=gy, Z=gz) - neutral = InfinityPoint(coords) - - curve = EllipticCurve(model, coords, p, neutral, {"a": a, "b": b}) - params = DomainParameters(curve, generator, n, h) - return params - - -def do_basic_test( - callback, runner, params, mult_class, formulas, mult_name, ecdsa, ecdh -): - with runner.isolated_filesystem() as tmpdir: - runner.invoke( - build_impl, - [ - "--platform", - "STM32F3", - "--ecdsa" if ecdsa else "--no-ecdsa", - "--ecdh" if ecdh else "--no-ecdh", - "--red", - "MONTGOMERY", - "-D", - "BN_NON_CONST", - params.curve.model.shortname, - params.curve.coordinate_model.name, - *formulas, - f"{mult_name}()", - ".", - ], - ) - target = SimulatorTarget(params.curve.model, params.curve.coordinate_model) - target.connect(binary=join(tmpdir, "pyecsca-codegen-CW308_STM32F3.elf")) - target.set_params(params) - formula_instances = [ - params.curve.coordinate_model.formulas[formula] for formula in formulas - ] - mult = mult_class(*formula_instances) - mult.init(params, params.generator) - callback(target, mult, params) - target.disconnect() - del target - gc.collect() - - -def test_init(cli_runner, curve32): - def callback(target, mult, params): - target.init_prng(bytes([0x12, 0x34, 0x56, 0x78])) - - do_basic_test( - callback, - cli_runner, - curve32, - LTRMultiplier, - ["add-1998-cmo", "dbl-1998-cmo"], - "ltr", - False, - False, - ) - - -def test_setup(cli_runner, curve32): - def callback(target, mult, params): - priv = 57 - pub = mult.multiply(priv).to_affine() - target.set_privkey(priv) - target.set_pubkey(pub) - - do_basic_test( - callback, - cli_runner, - curve32, - LTRMultiplier, - ["add-1998-cmo", "dbl-1998-cmo"], - "ltr", - False, - False, - ) - - -def test_debug(cli_runner, curve32): - def callback(target, mult, params): - model, coords = target.debug() - assert model == params.curve.model.shortname - assert coords == params.curve.coordinate_model.name - - do_basic_test( - callback, - cli_runner, - curve32, - LTRMultiplier, - ["add-1998-cmo", "dbl-1998-cmo"], - "ltr", - False, - False, - ) - - -@pytest.mark.parametrize( - "mult_name,mult_class", [("ltr", LTRMultiplier), ("rtl", RTLMultiplier)] -) -def test_keygen(mult_name, mult_class, cli_runner, curve32): - def callback(target, mult, params): - priv, pub = target.generate() - assert params.curve.is_on_curve(pub) - expected = mult.multiply(priv).to_affine() - assert pub == expected - - do_basic_test( - callback, - cli_runner, - curve32, - mult_class, - ["add-1998-cmo", "dbl-1998-cmo"], - mult_name, - False, - False, - ) - - -@pytest.mark.parametrize( - "mult_name,mult_class", [("ltr", LTRMultiplier), ("rtl", RTLMultiplier)] -) -def test_scalarmult(mult_name, mult_class, cli_runner, curve32): - values = [2355498743] - - def callback(target, mult, params): - for value in values: - result = target.scalar_mult(value, params.generator) - expected = mult.multiply(value) - assert result == expected - - do_basic_test( - callback, - cli_runner, - curve32, - mult_class, - ["add-1998-cmo", "dbl-1998-cmo"], - mult_name, - False, - False, - ) - - -@pytest.mark.parametrize( - "mult_name,mult_class", [("ltr", LTRMultiplier), ("rtl", RTLMultiplier)] -) -def test_ecdh(mult_name, mult_class, cli_runner, curve32): - other_privs = [2355498743] - - def callback(target, mult, params): - for other_priv in other_privs: - priv, pub = target.generate() - other_pub = mult.multiply(other_priv) - ecdh = ECDH_SHA1(copy(mult), params, other_pub, priv) - result = target.ecdh(other_pub) - expected = ecdh.perform() - assert result == expected - - do_basic_test( - callback, - cli_runner, - curve32, - mult_class, - ["add-1998-cmo", "dbl-1998-cmo"], - mult_name, - False, - True, - ) - - -@pytest.mark.parametrize( - "mult_name,mult_class", [("ltr", LTRMultiplier), ("rtl", RTLMultiplier)] -) -def test_ecdsa(mult_name, mult_class, cli_runner, curve32): - data = b"something" - - def callback(target, mult, params): - priv, pub = target.generate() - ecdsa = ECDSA_SHA1( - copy(mult), - params, - mult.formulas["add"], - pub.to_model(params.curve.coordinate_model, params.curve), - priv, - ) - - signature_data = target.ecdsa_sign(data) - result = SignatureResult.from_DER(bytes(signature_data)) - assert ecdsa.verify_data(result, data) - - expected = ecdsa.sign_data(data).to_DER() - assert target.ecdsa_verify(data, expected) - - do_basic_test( - callback, - cli_runner, - curve32, - mult_class, - ["add-1998-cmo", "dbl-1998-cmo"], - mult_name, - True, - False, - ) -- cgit v1.3.1 From b32cb5cb6105a165b8ddd0aa987019eafade5fec Mon Sep 17 00:00:00 2001 From: Andrej Bátora Date: Thu, 7 Dec 2023 17:25:23 +0100 Subject: added method for transforming trace to EmulatorTarget --- pyecsca/codegen/client.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pyecsca/codegen/client.py b/pyecsca/codegen/client.py index 989b47b..ae42277 100644 --- a/pyecsca/codegen/client.py +++ b/pyecsca/codegen/client.py @@ -8,6 +8,7 @@ from typing import Mapping, Union, Optional, Tuple import chipwhisperer as cw import click +import numpy as np from chipwhisperer.capture.api.programmers import STM32FProgrammer, XMEGAProgrammer from chipwhisperer.capture.targets import SimpleSerial from public import public @@ -18,6 +19,7 @@ from pyecsca.ec.params import DomainParameters, get_params from pyecsca.ec.point import Point, InfinityPoint from pyecsca.sca.target import (Target, SimpleSerialTarget, ChipWhispererTarget, BinaryTarget, Flashable, SimpleSerialMessage as SMessage) +from pyecsca.sca.trace import Trace from .common import wrap_enum, Platform, get_model, get_coords @@ -25,6 +27,7 @@ from rainbow.devices import rainbow_stm32f215 from rainbow import TraceConfig, Print + class Triggers(IntFlag): """ Actions that the implementation can trigger on. @@ -310,6 +313,12 @@ class EmulatorTarget(Target): self.__emulate(command, 'cmd_ecdsa_verify') return bool(int.from_bytes(self.result[0], 'big')) + def transform_trace(self) -> Trace: + temp_tr = [] + for sample in self.trace: + temp_tr.append(sample['register']) + return Trace(np.array(temp_tr)) + def set_strigger(self): pass -- cgit v1.3.1