aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJ08nY2024-01-27 11:48:50 +0100
committerJ08nY2024-01-27 11:48:50 +0100
commit8f05c2a23462be44b8f22da17f36eaf07e8cf9c4 (patch)
tree1bf7b0228f7326521651ba85e7fe7139a6127ac2
parentc99905ad7e2e4dcc269669fb5ef92e787e5248d7 (diff)
downloadpyecsca-8f05c2a23462be44b8f22da17f36eaf07e8cf9c4.tar.gz
pyecsca-8f05c2a23462be44b8f22da17f36eaf07e8cf9c4.tar.zst
pyecsca-8f05c2a23462be44b8f22da17f36eaf07e8cf9c4.zip
Add EFD -> Code transformation.
-rw-r--r--pyecsca/ec/formula/base.py10
-rw-r--r--pyecsca/ec/formula/code.py34
-rw-r--r--pyecsca/ec/formula/efd.py10
-rw-r--r--pyecsca/ec/formula/fake.py1
-rw-r--r--test/ec/test_formula.py11
5 files changed, 50 insertions, 16 deletions
diff --git a/pyecsca/ec/formula/base.py b/pyecsca/ec/formula/base.py
index 429f4c1..5cfb425 100644
--- a/pyecsca/ec/formula/base.py
+++ b/pyecsca/ec/formula/base.py
@@ -16,7 +16,6 @@ from ..error import UnsatisfiedAssumptionError, raise_unsatisified_assumption
from ..mod import Mod, SymbolicMod
from ..op import CodeOp, OpType
from ...misc.cfg import getconfig
-from ...misc.utils import peval
from ...misc.cache import sympify, simplify
@@ -283,15 +282,6 @@ class Formula(ABC):
def __repr__(self):
return f"{self.__class__.__name__}({self.name} for {self.coordinate_model})"
- def __getstate__(self):
- state = self.__dict__.copy()
- state["assumptions"] = list(map(unparse, state["assumptions"]))
- return state
-
- def __setstate__(self, state):
- state["assumptions"] = list(map(peval, state["assumptions"]))
- self.__dict__.update(state)
-
@cached_property
def input_index(self):
"""Return the starting index where this formula reads its inputs."""
diff --git a/pyecsca/ec/formula/code.py b/pyecsca/ec/formula/code.py
index 9d36d94..307870f 100644
--- a/pyecsca/ec/formula/code.py
+++ b/pyecsca/ec/formula/code.py
@@ -1,4 +1,7 @@
"""Provides a concrete class of a formula that has a constructor."""
+from typing import List, Any
+from ast import Expression
+from astunparse import unparse
from .base import (
Formula,
@@ -10,17 +13,29 @@ from .base import (
ScalingFormula,
DifferentialAdditionFormula,
)
+from ..op import CodeOp
+from ...misc.utils import peval
class CodeFormula(Formula):
- def __init__(self, name, code, coordinate_model, parameters, assumptions):
+ """A basic formula class that can be directly initialized with the code and other attributes."""
+
+ def __init__(
+ self,
+ name: str,
+ code: List[CodeOp],
+ coordinate_model: Any,
+ parameters: List[str],
+ assumptions: List[Expression],
+ unified: bool = False,
+ ):
self.name = name
+ self.code = code
self.coordinate_model = coordinate_model
self.meta = {}
self.parameters = parameters
self.assumptions = assumptions
- self.code = code
- self.unified = False
+ self.unified = unified
def __hash__(self):
return hash(
@@ -30,6 +45,7 @@ class CodeFormula(Formula):
tuple(self.code),
tuple(self.parameters),
tuple(self.assumptions),
+ self.unified,
)
)
@@ -40,8 +56,20 @@ class CodeFormula(Formula):
self.name == other.name
and self.coordinate_model == other.coordinate_model
and self.code == other.code
+ and self.parameters == other.parameters
+ and self.assumptions_str == other.assumptions_str
+ and self.unified == other.unified
)
+ def __getstate__(self):
+ state = self.__dict__.copy()
+ state["assumptions"] = list(map(unparse, state["assumptions"]))
+ return state
+
+ def __setstate__(self, state):
+ state["assumptions"] = list(map(peval, state["assumptions"]))
+ self.__dict__.update(state)
+
class CodeAdditionFormula(AdditionFormula, CodeFormula):
pass
diff --git a/pyecsca/ec/formula/efd.py b/pyecsca/ec/formula/efd.py
index c2ec49a..edf64de 100644
--- a/pyecsca/ec/formula/efd.py
+++ b/pyecsca/ec/formula/efd.py
@@ -1,8 +1,12 @@
""""""
+from copy import copy
+
from public import public
from importlib_resources.abc import Traversable
from typing import Any
+
+from . import CodeFormula
from .base import (
Formula,
CodeOp,
@@ -66,6 +70,12 @@ class EFDFormula(Formula):
code_module = pexec(line.decode("ascii").replace("^", "**"))
self.code.append(CodeOp(code_module))
+ def to_code(self) -> CodeFormula:
+ for klass in CodeFormula.__subclasses__():
+ if self.shortname == klass.shortname:
+ return klass(self.name, copy(self.code), self.coordinate_model, copy(self.parameters), copy(self.assumptions), self.unified)
+ raise TypeError(f"CodeFormula not found for {self.__class__}.")
+
def __getnewargs__(self):
return None, None, self.name, self.coordinate_model
diff --git a/pyecsca/ec/formula/fake.py b/pyecsca/ec/formula/fake.py
index 837e2d8..cc52740 100644
--- a/pyecsca/ec/formula/fake.py
+++ b/pyecsca/ec/formula/fake.py
@@ -26,6 +26,7 @@ class FakeFormula(Formula, ABC):
and points (for example to get the addition chain via the MultipleContext).
"""
def __init__(self, coordinate_model):
+ # TODO: This is missing all of the other attributes
self.coordinate_model = coordinate_model
self.code = []
diff --git a/test/ec/test_formula.py b/test/ec/test_formula.py
index ed437a5..e0fd6fe 100644
--- a/test/ec/test_formula.py
+++ b/test/ec/test_formula.py
@@ -33,7 +33,12 @@ from pyecsca.ec.formula.efd import (
LadderEFDFormula,
EFDFormula,
)
-from pyecsca.ec.formula import AdditionFormula, DoublingFormula, LadderFormula
+from pyecsca.ec.formula import (
+ AdditionFormula,
+ DoublingFormula,
+ LadderFormula,
+ CodeFormula,
+)
@pytest.fixture()
@@ -390,14 +395,14 @@ LIBRARY_FORMULAS = [
@pytest.fixture(params=LIBRARY_FORMULAS, ids=list(map(itemgetter(0), LIBRARY_FORMULAS)))
-def library_formula_params(request) -> Tuple[EFDFormula, DomainParameters]:
+def library_formula_params(request) -> Tuple[CodeFormula, DomainParameters]:
name, model, coords_name, param_spec, formula_type = request.param
model = model()
coordinate_model = model.coordinates[coords_name]
with as_file(files(test.data.formulas).joinpath(name)) as meta_path, as_file(
files(test.data.formulas).joinpath(name + ".op3")
) as op3_path:
- formula = formula_type(meta_path, op3_path, name, coordinate_model)
+ formula = formula_type(meta_path, op3_path, name, coordinate_model).to_code()
params = get_params(*param_spec, coords_name)
return formula, params