diff options
| author | J08nY | 2024-07-17 15:30:25 +0200 |
|---|---|---|
| committer | J08nY | 2024-07-17 15:30:25 +0200 |
| commit | 33027a201236e6e4aad2d7d637aed85a4f762021 (patch) | |
| tree | 791faec5053905cdd1b5f473560eaea3c9215f5d | |
| parent | d429a996d64e8f8df552ae4a34a04189dc9b82c4 (diff) | |
| download | pyecsca-codegen-33027a201236e6e4aad2d7d637aed85a4f762021.tar.gz pyecsca-codegen-33027a201236e6e4aad2d7d637aed85a4f762021.tar.zst pyecsca-codegen-33027a201236e6e4aad2d7d637aed85a4f762021.zip | |
Document the scripts.
| -rw-r--r-- | .github/workflows/test.yml | 2 | ||||
| -rw-r--r-- | LICENSE | 2 | ||||
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | pyecsca/codegen/builder.py | 83 | ||||
| -rw-r--r-- | pyecsca/codegen/client.py | 199 | ||||
| -rw-r--r-- | pyecsca/codegen/common.py | 10 | ||||
| -rw-r--r-- | pyecsca/codegen/render.py | 1 | ||||
| -rw-r--r-- | pyproject.toml | 14 | ||||
| -rw-r--r-- | test/test_emulator.py | 8 | ||||
| -rw-r--r-- | test/test_encoding.py | 4 | ||||
| -rw-r--r-- | test/test_impl.py | 6 |
11 files changed, 258 insertions, 73 deletions
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f748ff6..f2e480d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - python-version: ["3.9", "3.10", "3.11"] + python-version: ["3.9", "3.10", "3.11", "3.12"] env: PYTHON: ${{ matrix.python-version }} steps: @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018-2019 +Copyright (c) 2018-2024 Jan Jancar Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -12,7 +12,7 @@ See [INSTALL](docs/install.rst) for installation instructions. MIT License - Copyright (c) 2018-2023 Jan Jancar + Copyright (c) 2018-2024 Jan Jancar Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pyecsca/codegen/builder.py b/pyecsca/codegen/builder.py index e9a9144..63e7801 100644 --- a/pyecsca/codegen/builder.py +++ b/pyecsca/codegen/builder.py @@ -1,4 +1,45 @@ #!/usr/bin/env python3 +""" +Builder script. + +Use it to render and build ECC implementations. + +Examples +======== + +To list available implementation choices use the ``list`` subcommand. + +.. code-block:: shell + + builder list + +To go deeper and examine the coordinates for a given curve model, e.g. the Short-Weierstrass one, use: + +.. code-block:: shell + + builder list shortw + +To list formulas for a given coordinate system and curve model, e.g. projective on Short-Weierstrass curves, use: + +.. code-block:: shell + + builder list shortw projective + +The following example builds an implementation for the HOST architecture, +using the short-Weierstrass curve model, projective coordinates, ``add-2007-bl`` and ``dbl-2007-bl`` +formulas with the left-to-right double-and-add scalar multiplier. Furthermore, it uses Barrett modular +reduction. + +.. code-block:: shell + + builder build --platform HOST --red BARRETT -v shortw projective add-2007-bl dbl-2007-bl "ltr()" . + +The following uses different formulas with the comb multiplier and specifies its width. + +.. code-block:: shell + + builder build --platform HOST --red BARRETT -v shortw projective add-1998-cmo dbl-1998-cmo "comb(width=5)" . +""" import re import shutil import subprocess @@ -15,8 +56,8 @@ from pyecsca.ec.formula import Formula, AdditionFormula from pyecsca.ec.model import CurveModel from pyecsca.ec.mult import ScalarMultiplier, AccumulationOrder, ProcessingDirection -from .render import render -from .common import Platform, DeviceConfiguration, MULTIPLIERS, wrap_enum, get_model, get_coords +from pyecsca.codegen.render import render +from pyecsca.codegen.common import Platform, DeviceConfiguration, MULTIPLIERS, wrap_enum, get_model, get_coords def get_formula(ctx: click.Context, param, value: Optional[Tuple[str]]) -> List[Formula]: @@ -28,7 +69,7 @@ def get_formula(ctx: click.Context, param, value: Optional[Tuple[str]]) -> List[ for formula in value: if formula not in coords.formulas: raise click.BadParameter( - "Formula '{}' is not a formula in '{}'.".format(formula, coords)) + "Formula '{}' is not a formula in '{}'.".format(formula, coords)) result.append(coords.formulas[formula]) if len(set(formula.__class__ for formula in result)) != len(result): raise click.BadParameter("Duplicate formula types.") @@ -40,8 +81,8 @@ def get_multiplier(ctx: click.Context, param, value: Optional[str]) -> Optional[ if value is None: return None res = re.match( - "(?P<name>[a-zA-Z\-]+)\((?P<args>([a-zA-Z_]+ *= *[a-zA-Z0-9.]+, ?)*?([a-zA-Z_]+ *= *[a-zA-Z0-9.]+)*)\)", - value) + "(?P<name>[a-zA-Z\-]+)\((?P<args>([a-zA-Z_]+ *= *[a-zA-Z0-9.]+, ?)*?([a-zA-Z_]+ *= *[a-zA-Z0-9.]+)*)\)", + value) if not res: raise click.BadParameter("Couldn't parse multiplier spec: {}.".format(value)) name = res.group("name") @@ -59,18 +100,18 @@ def get_multiplier(ctx: click.Context, param, value: Optional[str]) -> Optional[ if not all( any(issubclass(cls, required) for cls in classes) for required in mult_class.requires): raise click.BadParameter( - "Multiplier {} requires formulas: {}, got {}.".format(mult_class.__name__, - mult_class.requires, classes)) + "Multiplier {} requires formulas: {}, got {}.".format(mult_class.__name__, + mult_class.requires, classes)) globs = dict(globals()) globs["AccumulationOrder"] = AccumulationOrder globs["ProcessingDirection"] = ProcessingDirection kwargs = eval("dict(" + args + ")", globs) required = set( - filter(lambda formula: any(isinstance(formula, cls) for cls in mult_class.requires), - formulas)) + filter(lambda formula: any(isinstance(formula, cls) for cls in mult_class.requires), + formulas)) optional = set( - filter(lambda formula: any(isinstance(formula, cls) for cls in mult_class.optionals), - formulas)) + filter(lambda formula: any(isinstance(formula, cls) for cls in mult_class.optionals), + formulas)) for formula in required.union(optional): kwargs[formula.shortname] = formula mult = mult_class(**kwargs) @@ -240,27 +281,29 @@ def list_impl(model: Optional[CurveModel], coords: Optional[CoordinateModel], click.echo(model) for coord in model.coordinates.values(): click.echo( - "{}: {}, [{}]".format(coord.name, coord.full_name, ",".join(coord.variables))) + "{}: {}, [{}]".format(coord.name, coord.full_name, ",".join(coord.variables))) return if not model: click.echo( - click.wrap_text("Platform:\n\t" + ", ".join(Platform.names()), - subsequent_indent="\t")) + click.wrap_text("Platform:\n\t" + ", ".join(Platform.names()), + subsequent_indent="\t")) click.echo( - click.wrap_text("Hash type:\n\t" + ", ".join(HashType.names()), - subsequent_indent="\t")) + click.wrap_text("Hash type:\n\t" + ", ".join(HashType.names()), + subsequent_indent="\t")) click.echo(click.wrap_text("Modular Random:\n\t" + ", ".join(RandomMod.names()), subsequent_indent="\t")) click.echo(click.wrap_text("Multiplication:\n\t" + ", ".join(Multiplication.names()), subsequent_indent="\t")) click.echo( - click.wrap_text("Squaring:\n\t" + ", ".join(Squaring.names()), - subsequent_indent="\t")) + click.wrap_text("Squaring:\n\t" + ", ".join(Squaring.names()), + subsequent_indent="\t")) click.echo(click.wrap_text("Modular Reduction:\n\t" + ", ".join(Reduction.names()), subsequent_indent="\t")) click.echo(click.wrap_text( - "Scalar multplier:\n\t" + ", ".join(map(lambda m: m["name"][-1], MULTIPLIERS)), - subsequent_indent="\t")) + "Scalar multplier:\n\t" + ", ".join(map(lambda m: m["name"][-1], MULTIPLIERS)), + subsequent_indent="\t")) + click.echo(click.wrap_text("Curve Model:\n\t" + ", ".join(["shortw", "montgom", "edwards", "twisted"]))) + if __name__ == "__main__": main(obj={}) diff --git a/pyecsca/codegen/client.py b/pyecsca/codegen/client.py index 6f0321e..228e888 100644 --- a/pyecsca/codegen/client.py +++ b/pyecsca/codegen/client.py @@ -1,4 +1,51 @@ #!/usr/bin/env python3 +""" +Client script. + +Use it to interact with the built implementations (and flash them if necessary). + +Examples +======== + +The following examples use the generated implementation in ``pyecsca-codegen-HOST.elf`` for the host +architecture, which is assumed to use the Short-Weierstrass curve model with projective coordinates. + +The first example generates a keypair and exports it. + +.. code-block:: shell-session + + $ client --platform HOST --fw ./pyecsca-codegen-HOST.elf shortw projective gen secg/secp128r1 + (162938999268550597445809790209592423458, Point([x=111810799217268384317536017529141796945, y=309320541414531923178173772704935971498] in shortw/affine)) + 0.01743340492248535 + +The following example does ECDH with the target, which first generates a keypair. + +.. code-block:: shell-session + + $ client --platform HOST --fw ./pyecsca-codegen-HOST.elf shortw projective ecdh secg/secp128r1 122835813094999453922649270086793500655,326514220558629293368386081113307347349 + Keypair: 162938999268550597445809790209592423458, [x=111810799217268384317536017529141796945, y=309320541414531923178173772704935971498] + ECDH result: 30567033074c9169e9355a7b348aa7511c3ae605 + +The following example signs a message ``"something"`` using the target, which first generates a keypair. + +.. code-block:: shell-session + + $ client --platform HOST --fw ./pyecsca-codegen-HOST.elf shortw projective ecdsa-sign secg/secp128r1 something + Keypair: 162938999268550597445809790209592423458, [x=111810799217268384317536017529141796945, y=309320541414531923178173772704935971498] + Signature: 30250211009dc6d5b03cffe0cbd5e829838ecb59e4021023496ba97cf1d816619fe626de2d07b6 + +The following example verifies a signature on the message ``"something"`` using the target and the provided public key. + +.. code-block:: shell-session + + $ client --platform HOST --fw ./pyecsca-codegen-HOST.elf shortw projective ecdsa-verify secg/secp128r1 111810799217268384317536017529141796945,309320541414531923178173772704935971498 something_else 30250211009dc6d5b03cffe0cbd5e829838ecb59e40210171c895d2d4f27850ff5f2a375ea22b7 + Result: True + +.. note:: + The implementation has a PRNG it uses to get randomness. This PRNG starts with a constant state. + You can use the ``--seed`` option to set a custom state. + +""" import bisect import re from binascii import hexlify, unhexlify @@ -12,23 +59,22 @@ import click import numpy as np from chipwhisperer.capture.api.programmers import STM32FProgrammer, XMEGAProgrammer from chipwhisperer.capture.targets import SimpleSerial +from rainbow.devices import rainbow_stm32f215 +from rainbow import TraceConfig, Print from public import public + from pyecsca.ec.coordinates import CoordinateModel, AffineCoordinateModel -from pyecsca.ec.mod import Mod +from pyecsca.ec.mod import mod, Mod from pyecsca.ec.model import CurveModel 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 - -from rainbow.devices import rainbow_stm32f215 -from rainbow import TraceConfig, Print - +from pyecsca.codegen.common import wrap_enum, Platform, get_model, get_coords +@public class Triggers(IntFlag): """ Actions that the implementation can trigger on. @@ -193,8 +239,8 @@ def cmd_debug() -> str: return "d" +@public class EmulatorTarget(Target): - emulator: rainbow_stm32f215 result: list model: CurveModel @@ -209,7 +255,7 @@ class EmulatorTarget(Target): trace_config: TraceConfig = TraceConfig(), allow_breakpoints: bool = False): super().__init__() self.emulator = rainbow_stm32f215(print_config=print_config, trace_config=trace_config, - allow_stubs=True, allow_breakpoints=allow_breakpoints) + allow_stubs=True, allow_breakpoints=allow_breakpoints) self.result = [] self.trace = [] self.model = model @@ -251,10 +297,10 @@ class EmulatorTarget(Target): 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)}) + 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 = [] @@ -281,9 +327,9 @@ class EmulatorTarget(Target): 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') - return priv, Point(AffineCoordinateModel(self.model), x = Mod(pub_x, self.params.curve.prime), - y = Mod(pub_y, self.params.curve.prime)) + pub_y = int.from_bytes(self.result[3][self.result[2] // 2:self.result[2]], 'big') + return priv, Point(AffineCoordinateModel(self.model), x=mod(pub_x, self.params.curve.prime), + y=mod(pub_y, self.params.curve.prime)) def set_privkey(self, privkey: int) -> None: command = cmd_set_privkey(privkey) @@ -364,7 +410,7 @@ class EmulatorTarget(Target): self.emulator.reset() - +@public class ImplTarget(SimpleSerialTarget): """ A target that is based on an implementation built by pyecsca-codegen. @@ -399,14 +445,26 @@ class ImplTarget(SimpleSerialTarget): self.trigger = None def init_prng(self, seed: bytes) -> None: + """ + Init the PRNG using the `seed`. + + """ self.send_cmd(SMessage.from_raw(cmd_init_prng(seed)), self.timeout) self.seed = seed def set_params(self, params: DomainParameters) -> None: + """ + Set the domain parameters on the target. + """ self.send_cmd(SMessage.from_raw(cmd_set_params(params)), self.timeout) self.params = params def generate(self) -> Tuple[int, Point]: + """ + Generate a keypair on the target and set it (and export it). + + Requires that domain parameters are set up. + """ resp = self.send_cmd(SMessage.from_raw(cmd_generate()), self.timeout) priv = resp["s"].data pub = resp["w"].data @@ -414,52 +472,96 @@ class ImplTarget(SimpleSerialTarget): pub_len = len(pub) x = int(pub[:pub_len // 2], 16) y = int(pub[pub_len // 2:], 16) - self.pubkey = Point(AffineCoordinateModel(self.model), x=Mod(x, self.params.curve.prime), - y=Mod(y, self.params.curve.prime)) + self.pubkey = Point(AffineCoordinateModel(self.model), x=mod(x, self.params.curve.prime), + y=mod(y, self.params.curve.prime)) return self.privkey, self.pubkey def set_privkey(self, privkey: int) -> None: + """ + Set the private key on the target. + """ self.send_cmd(SMessage.from_raw(cmd_set_privkey(privkey)), self.timeout) self.privkey = privkey def set_pubkey(self, pubkey: Point) -> None: + """ + Set the public key on the target. + """ self.send_cmd(SMessage.from_raw(cmd_set_pubkey(pubkey)), self.timeout) self.pubkey = pubkey def scalar_mult(self, scalar: int, point: Point) -> Point: + """ + Run scalar multiplication on the target and export the result. + + Requires that domain parameters are set up. + """ resp = self.send_cmd(SMessage.from_raw(cmd_scalar_mult(scalar, point)), self.timeout) result = resp["w"] plen = ((self.params.curve.prime.bit_length() + 7) // 8) * 2 - params = {var: Mod(int(result.data[i * plen:(i + 1) * plen], 16), self.params.curve.prime) + params = {var: mod(int(result.data[i * plen:(i + 1) * plen], 16), self.params.curve.prime) for i, var in enumerate(self.coords.variables)} return Point(self.coords, **params) def ecdh(self, other_pubkey: Point) -> bytes: + """ + Do ECDH with the target. + + Requires that domain parameters are set up, as well as a private key. + """ resp = self.send_cmd(SMessage.from_raw(cmd_ecdh(other_pubkey)), self.timeout) result = resp["r"] return unhexlify(result.data) def ecdsa_sign(self, data: bytes) -> bytes: + """ + Sign a message on the target. + + Requires that domain parameters are set up, as well as a private key. + """ resp = self.send_cmd(SMessage.from_raw(cmd_ecdsa_sign(data)), self.timeout) signature = resp["s"] return unhexlify(signature.data) def ecdsa_verify(self, data: bytes, signature: bytes) -> bool: + """ + Verify a signature on the target. + + Requires that domain parameters are set up, as well as a public key. + """ resp = self.send_cmd(SMessage.from_raw(cmd_ecdsa_verify(data, signature)), self.timeout) result = resp["v"] return unhexlify(result.data)[0] == 1 def debug(self) -> Tuple[str, str]: + """ + Run the debug command on the target. + + Returns the curve model and coordinate model names. + """ resp = self.send_cmd(SMessage.from_raw(cmd_debug()), self.timeout)["d"] model, coords = unhexlify(resp.data).decode().split(",") return model, coords def set_trigger(self, actions: Triggers) -> None: + """ + Setup the trigger on the target. + + .. note:: + + The triggers are not exclusive and you can set to trigger on multiple actions. + However, note that they toggle the trigger signal. For example, if you setup + triggers on scalar multiplication and addition (``Triggers.mult | Triggers.add``) + the trigger signal will go high once scalar multiplication starts, then go low + during each addition operation and finally go low for good after scalar multiplication + ends. + """ self.send_cmd(SMessage.from_raw(cmd_set_trigger(actions)), self.timeout) self.trigger = actions def quit(self): + """Turn off the target.""" self.write(b"x\n") def disconnect(self): @@ -505,6 +607,7 @@ class HostTarget(ImplTarget, BinaryTarget): help="The firmware. Either a .hex file for a device platform or .elf for HOST platform.", required=True) @click.option("--timeout", type=int, default=15000) +@click.option("--seed", type=str, help="Set the PRNG seed (hex string).") @click.argument("model", required=True, type=click.Choice(["shortw", "montgom", "edwards", "twisted"]), callback=get_model) @@ -513,12 +616,13 @@ class HostTarget(ImplTarget, BinaryTarget): @click.version_option() @click.pass_context @public -def main(ctx, platform, fw, timeout, model, coords): +def main(ctx, platform, fw, timeout, seed, model, coords): """ A tool for communicating with built and flashed ECC implementations. """ ctx.ensure_object(dict) ctx.obj["fw"] = fw + ctx.obj["seed"] = seed if platform != Platform.HOST: ctx.obj["target"] = DeviceTarget(model, coords, platform, timeout=timeout) else: @@ -549,6 +653,8 @@ def generate(ctx: click.Context, curve): if isinstance(target, Flashable): target.flash(ctx.obj["fw"]) target.connect() + if seed := ctx.obj["seed"]: + target.init_prng(bytes.fromhex(seed)) target.set_params(curve) start = time() click.echo(target.generate()) @@ -573,8 +679,8 @@ def get_pubkey(ctx: click.Context, param, value: Optional[str]) -> Point: y = int(ys) else: raise click.BadParameter("Couldn't parse pubkey: {}.".format(value)) - x = Mod(x, curve.curve.prime) - y = Mod(y, curve.curve.prime) + x = mod(x, curve.curve.prime) + y = mod(y, curve.curve.prime) return Point(AffineCoordinateModel(curve.curve.model), x=x, y=y) @@ -590,31 +696,62 @@ def ecdh(ctx: click.Context, curve, pubkey): if isinstance(target, Flashable): target.flash(ctx.obj["fw"]) target.connect() + if seed := ctx.obj["seed"]: + target.init_prng(bytes.fromhex(seed)) target.set_params(curve) - target.generate() - click.echo(hexlify(target.ecdh(pubkey))) + priv, pub = target.generate() + click.echo(f"Keypair: {priv}, {pub}") + click.echo(f"ECDH result: {hexlify(target.ecdh(pubkey)).decode()}") target.quit() target.disconnect() @main.command("ecdsa-sign") @click.argument("curve", required=True, callback=get_curve) +@click.argument("data", required=True, type=str) @click.pass_context @public -def ecdsa_sign(ctx: click.Context, curve): +def ecdsa_sign(ctx: click.Context, curve, data): + """Sign data using ECDSA.""" ctx.ensure_object(dict) - # TODO - click.echo("Not implemented.") + target: ImplTarget = ctx.obj["target"] + if isinstance(target, Flashable): + target.flash(ctx.obj["fw"]) + target.connect() + if seed := ctx.obj["seed"]: + target.init_prng(bytes.fromhex(seed)) + target.set_params(curve) + priv, pub = target.generate() + click.echo(f"Keypair: {priv}, {pub}") + click.echo(f"Signature: {hexlify(target.ecdsa_sign(data.encode())).decode()}") + target.quit() + target.disconnect() @main.command("ecdsa-verify") @click.argument("curve", required=True, callback=get_curve) +@click.argument("pubkey", required=True, callback=get_pubkey) +@click.argument("data", required=True, type=str) +@click.argument("signature", required=True, type=str) @click.pass_context @public -def ecdsa_verify(ctx: click.Context, curve): +def ecdsa_verify(ctx: click.Context, curve, pubkey, data, signature): + """ + Verify data using ECDSA. + """ ctx.ensure_object(dict) - # TODO - click.echo("Not implemented.") + target: ImplTarget = ctx.obj["target"] + if isinstance(target, Flashable): + target.flash(ctx.obj["fw"]) + target.connect() + if seed := ctx.obj["seed"]: + target.init_prng(bytes.fromhex(seed)) + target.set_params(curve) + target.set_pubkey(pubkey) + res = target.ecdsa_verify(data.encode(), unhexlify(signature)) + click.echo(f"Result: {res}") + target.quit() + target.disconnect() if __name__ == "__main__": diff --git a/pyecsca/codegen/common.py b/pyecsca/codegen/common.py index ffe4710..3ec91fc 100644 --- a/pyecsca/codegen/common.py +++ b/pyecsca/codegen/common.py @@ -1,3 +1,4 @@ +"""Common codegen utilities.""" from dataclasses import dataclass from typing import Type, Optional, MutableMapping, Any @@ -21,6 +22,7 @@ from pyecsca.ec.mult import ( FullPrecompMultiplier, BGMWMultiplier, CombMultiplier, + WindowBoothMultiplier, ) @@ -62,13 +64,13 @@ MULTIPLIERS = [ {"name": ("wnaf", "WindowNAFMultiplier"), "class": WindowNAFMultiplier}, {"name": ("sliding", "SlidingWindowMultiplier"), "class": SlidingWindowMultiplier}, {"name": ("fixed", "FixedWindowLTRMultiplier"), "class": FixedWindowLTRMultiplier}, + {"name": ("booth", "WindowBoothMultiplier"), "class": WindowBoothMultiplier}, {"name": ("precomp", "FullPrecompMultiplier"), "class": FullPrecompMultiplier}, {"name": ("bgmw", "BGMWMultiplier"), "class": BGMWMultiplier}, {"name": ("comb", "CombMultiplier"), "class": CombMultiplier}, ] -@public def wrap_enum(enum_class: Type[EnumDefine]): def callback(ctx, param, value): try: @@ -76,7 +78,7 @@ def wrap_enum(enum_class: Type[EnumDefine]): return res except Exception: raise click.BadParameter( - "Cannot create {} enum from {}.".format(enum_class.__name__, value)) + "Cannot create {} enum from {}.".format(enum_class.__name__, value)) return callback @@ -105,8 +107,8 @@ def get_coords(ctx: click.Context, param, value: Optional[str]) -> Optional[Coor model = ctx.obj["model"] if value not in model.coordinates: raise click.BadParameter( - "Coordinate model '{}' is not a model in '{}'.".format(value, - model.__class__.__name__)) + "Coordinate model '{}' is not a model in '{}'.".format(value, + model.__class__.__name__)) coords = model.coordinates[value] ctx.obj["coords"] = coords return coords diff --git a/pyecsca/codegen/render.py b/pyecsca/codegen/render.py index 241ee6a..692deab 100644 --- a/pyecsca/codegen/render.py +++ b/pyecsca/codegen/render.py @@ -1,3 +1,4 @@ +"""Rendering and building of implementation configurations.""" import os import shutil import subprocess diff --git a/pyproject.toml b/pyproject.toml index ff471c5..41585c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ "Intended Audience :: Developers", "Intended Audience :: Science/Research" ] - requires-python = ">=3.8" + requires-python = ">=3.9" dependencies = [ "pyecsca", "chipwhisperer", @@ -41,10 +41,10 @@ ] [project.urls] -"Homepage" = "https://https://neuromancer.sk/pyecsca/" -"Documentation" = "https://https://neuromancer.sk/pyecsca/" -"Bug Tracker" = "https://github.com/J08nY/pyecsca/issues" -"Repository" = "https://github.com/J08nY/pyecsca" +"Homepage" = "https://pyecsca.org" +"Documentation" = "https://pyecsca.org" +"Bug Tracker" = "https://github.com/J08nY/pyecsca-codegen/issues" +"Repository" = "https://github.com/J08nY/pyecsca-codegen" [project.scripts] builder="pyecsca.codegen.builder:main" @@ -66,5 +66,7 @@ markers = [ "slow: marks tests as slow (deselect with '-m \"not slow\"')", ] filterwarnings = [ - "ignore:Deprecated call to `pkg_resources.declare_namespace" + "ignore:(?s).*pkg_resources is deprecated as an API:DeprecationWarning:chipwhisperer.capture.trace.TraceWhisperer", # ChipWhisperer + "ignore:Deprecated call to `pkg_resources.declare_namespace", + "ignore:(?s).*path is deprecated. Use files() instead:DeprecationWarning:rainbow.devices.stm32" # Rainbow ] diff --git a/test/test_emulator.py b/test/test_emulator.py index ab8bf73..072af27 100644 --- a/test/test_emulator.py +++ b/test/test_emulator.py @@ -11,7 +11,7 @@ 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.mod import mod from pyecsca.ec.model import ShortWeierstrassModel from pyecsca.ec.params import DomainParameters from pyecsca.ec.point import InfinityPoint, Point @@ -23,11 +23,11 @@ def curve32(): model = ShortWeierstrassModel() coords = model.coordinates["projective"] p = 0xD7D1247F - a = Mod(0xA4A44016, p) - b = Mod(0x73F76716, p) + a = mod(0xA4A44016, p) + b = mod(0x73F76716, p) n = 0xD7D2A475 h = 1 - gx, gy, gz = Mod(0x54EED6D7, p), Mod(0x6F1E55AC, p), Mod(1, p) + gx, gy, gz = mod(0x54EED6D7, p), mod(0x6F1E55AC, p), mod(1, p) generator = Point(coords, X=gx, Y=gy, Z=gz) neutral = InfinityPoint(coords) diff --git a/test/test_encoding.py b/test/test_encoding.py index 0684945..f4fc7fa 100644 --- a/test/test_encoding.py +++ b/test/test_encoding.py @@ -1,11 +1,11 @@ -from pyecsca.ec.mod import Mod +from pyecsca.ec.mod import mod from pyecsca.codegen.client import encode_data, decode_data, encode_scalar def test_encode_decode(): data = { "a": encode_scalar(0xCAFEBABE), - "b": {"c": encode_scalar(Mod(1, 3)), "d": bytes([0x2])}, + "b": {"c": encode_scalar(mod(1, 3)), "d": bytes([0x2])}, } encoded = encode_data(None, data) result = decode_data(encoded) diff --git a/test/test_impl.py b/test/test_impl.py index da42c33..34f427b 100644 --- a/test/test_impl.py +++ b/test/test_impl.py @@ -4,7 +4,7 @@ import pytest from click.testing import CliRunner from pyecsca.ec.key_agreement import ECDH_SHA1 -from pyecsca.ec.mod import Mod +from pyecsca.ec.mod import mod from pyecsca.ec.mult import ( LTRMultiplier, RTLMultiplier, @@ -323,7 +323,7 @@ def test_ecdh(target, mult, secp128r1): for other_priv in other_privs: priv, pub = target.generate() other_pub = mult.multiply(other_priv) - ecdh = ECDH_SHA1(copy(mult), secp128r1, other_pub, Mod(priv, secp128r1.order)) + ecdh = ECDH_SHA1(copy(mult), secp128r1, other_pub, mod(priv, secp128r1.order)) result = target.ecdh(other_pub) expected = ecdh.perform() assert result == expected @@ -343,7 +343,7 @@ def test_ecdsa(target, mult, secp128r1): secp128r1, mult.formulas["add"], pub.to_model(secp128r1.curve.coordinate_model, secp128r1.curve), - Mod(priv, secp128r1.order), + mod(priv, secp128r1.order), ) signature_data = target.ecdsa_sign(message) |
