aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pyecsca/sca/re/epa.py14
-rw-r--r--test/sca/perf_epa.py38
2 files changed, 37 insertions, 15 deletions
diff --git a/pyecsca/sca/re/epa.py b/pyecsca/sca/re/epa.py
index 913a1ab..3a243fa 100644
--- a/pyecsca/sca/re/epa.py
+++ b/pyecsca/sca/re/epa.py
@@ -1,7 +1,7 @@
"""
Provides functionality inspired by the Exceptional Procedure Attack [EPA]_.
"""
-
+from operator import itemgetter
from typing import Callable, Literal, Union
from public import public
@@ -19,6 +19,7 @@ def graph_to_check_inputs(
precomp_to_affine: bool,
use_init: bool = True,
use_multiply: bool = True,
+ check_formulas: set[str] | None = None,
) -> dict[str, set[tuple[int, ...]]]:
"""
Compute the inputs for the checks based on the context and output point. This function traverses the graph of points
@@ -32,6 +33,7 @@ def graph_to_check_inputs(
:param precomp_to_affine: Whether to include the precomputed points in the to-affine checks.
:param use_init: Whether to consider the point multiples that happen in scalarmult initialization.
:param use_multiply: Whether to consider the point multiples that happen in scalarmult multiply (after initialization).
+ :param check_formulas: If provided, only formulas in this set will be considered for checks.
:return: A dictionary mapping formula names to sets of tuples of input multiples.
.. note::
@@ -83,12 +85,16 @@ def graph_to_check_inputs(
}
# This actually passes the multiple itself to the check, not the inputs(parents)
# Now handle the regular checks
+
+ def get_point(pt):
+ return full_ctx.points[pt]
+
for point in points:
formula = full_ctx.formulas[point]
- if not formula:
+ if not formula or (check_formulas is not None and formula not in check_formulas):
# Skip input point or infty point (they magically appear and do not have an origin formula)
continue
- inputs = tuple(map(lambda pt: full_ctx.points[pt], full_ctx.parents[point]))
+ inputs = tuple(map(get_point, full_ctx.parents[point]))
check_list = formula_checks.setdefault(formula, set())
check_list.add(inputs)
return formula_checks
@@ -127,7 +133,7 @@ def errors_out(
precomp_ctx: MultipleContext,
full_ctx: MultipleContext,
out: Point,
- check_funcs: dict[str, Callable[[int, int], bool]],
+ check_funcs: dict[str, Callable[[int, int], bool] | Callable[[int], bool]],
check_condition: Union[Literal["all"], Literal["necessary"]],
precomp_to_affine: bool,
use_init: bool = True,
diff --git a/test/sca/perf_epa.py b/test/sca/perf_epa.py
index 3f9a6fc..32648c9 100644
--- a/test/sca/perf_epa.py
+++ b/test/sca/perf_epa.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python
import click
+from pyecsca.ec.mod import Mod
from pyecsca.ec.mod.flint import has_flint
from pyecsca.ec.mod.gmp import has_gmp
from pyecsca.ec.params import get_params
@@ -26,7 +27,7 @@ from test.utils import Profiler
default="flint" if has_flint else "gmp" if has_gmp else "python",
envvar="MOD",
)
-@click.option("-o", "--operations", type=click.INT, default=1000)
+@click.option("-o", "--operations", type=click.INT, default=100)
@click.option(
"-d",
"--directory",
@@ -39,29 +40,44 @@ def main(profiler, mod, operations, directory):
cfg.ec.mod_implementation = mod
p128 = get_params("secg", "secp128r1", "projective")
- scalar = 123456789123456789123456789123456789
+ scalars = [int(Mod.random(p128.order)) for _ in range(operations)]
+ ops = [
+ multiple_graph(scalar, p128, LTRMultiplier, LTRMultiplier)
+ for scalar in scalars
+ ]
+
click.echo(
- f"Profiling {operations} {p128.curve.prime.bit_length()}-bit (k = {scalar}) multiples_computed computations..."
+ f"Profiling {operations} {p128.curve.prime.bit_length()}-bit graph_to_check_inputs + evaluate_checks computations..."
)
with Profiler(profiler, directory, f"epa_p128_ltr_{operations}_{mod}"):
- precomp_ctx, full_ctx, out = multiple_graph(
- scalar, p128, LTRMultiplier, LTRMultiplier
- )
- for _ in range(operations):
+ for precomp_ctx, full_ctx, out in ops:
check_inputs = graph_to_check_inputs(
precomp_ctx,
full_ctx,
out,
- check_condition="necessary",
+ check_condition="all",
precomp_to_affine=True,
use_init=True,
use_multiply=True,
+ check_formulas={"add"},
)
- for _ in range(32):
+ c = 0
+ for j in range(3220):
+ i = 0
+
+ def check_add(x, y):
+ nonlocal i, c
+ i += 1
+ c += 1
+ return (i % (30 * (j+1))) == 0
+
+ def check_affine(x):
+ return False
+
evaluate_checks(
check_funcs={
- "add": lambda x, y: False,
- "affine": lambda x: False,
+ "add": check_add,
+ "affine": check_affine,
},
check_inputs=check_inputs,
)