aboutsummaryrefslogtreecommitdiffhomepage
path: root/pyecsca
diff options
context:
space:
mode:
Diffstat (limited to 'pyecsca')
-rw-r--r--pyecsca/ec/formula.py35
-rw-r--r--pyecsca/ec/op.py34
2 files changed, 63 insertions, 6 deletions
diff --git a/pyecsca/ec/formula.py b/pyecsca/ec/formula.py
index f80e9fa..5f4c7cb 100644
--- a/pyecsca/ec/formula.py
+++ b/pyecsca/ec/formula.py
@@ -1,5 +1,6 @@
from ast import parse, Expression
-from typing import List, Any, ClassVar, MutableMapping
+from typing import List, Set, Any, ClassVar, MutableMapping
+from itertools import product
from pkg_resources import resource_stream
from public import public
@@ -22,10 +23,22 @@ class Formula(object):
return f"{self.__class__.__name__}({self.name} for {self.coordinate_model})"
@property
- def output_index(cls):
+ def input_index(self):
+ raise NotImplementedError
+
+ @property
+ def output_index(self) -> int:
"""The starting index where this formula stores its outputs."""
raise NotImplementedError
+ @property
+ def inputs(self) -> Set[str]:
+ raise NotImplementedError
+
+ @property
+ def outputs(self) -> Set[str]:
+ raise NotImplementedError
+
class EFDFormula(Formula):
@@ -60,8 +73,22 @@ class EFDFormula(Formula):
self.code.append(CodeOp(code_module))
@property
- def output_index(cls):
- return max(cls.num_inputs + 1, 3)
+ def input_index(self):
+ return 1
+
+ @property
+ def output_index(self):
+ return max(self.num_inputs + 1, 3)
+
+ @property
+ def inputs(self):
+ return set(var + str(i) for var, i in product(self.coordinate_model.variables,
+ range(1, 1 + self.num_inputs)))
+
+ @property
+ def outputs(self):
+ return set(var + str(i) for var, i in product(self.coordinate_model.variables,
+ range(self.output_index, self.output_index + self.num_outputs)))
def __eq__(self, other):
if not isinstance(other, EFDFormula):
diff --git a/pyecsca/ec/op.py b/pyecsca/ec/op.py
index 169f3bb..11c3079 100644
--- a/pyecsca/ec/op.py
+++ b/pyecsca/ec/op.py
@@ -1,4 +1,4 @@
-from ast import Module, walk, Name, BinOp, operator
+from ast import Module, walk, Name, BinOp, Constant, operator, Mult, Div, Add, Sub, Pow
from types import CodeType
from typing import FrozenSet, Optional
@@ -26,6 +26,7 @@ class CodeOp(Op):
self.result = assign.targets[0].id
params = set()
variables = set()
+ constants = set()
op = None
for node in walk(assign.value):
if isinstance(node, Name):
@@ -34,15 +35,44 @@ class CodeOp(Op):
variables.add(name)
else:
params.add(name)
+ elif isinstance(node, Constant):
+ constants.add(node.value)
elif isinstance(node, BinOp):
op = node.op
+ self.left = self.__to_name(node.left)
+ self.right = self.__to_name(node.right)
self.operator = op
self.parameters = frozenset(params)
self.variables = frozenset(variables)
+ self.constants = frozenset(constants)
self.compiled = compile(self.code, "", mode="exec")
+ def __to_name(self, node):
+ if isinstance(node, Name):
+ return node.id
+ elif isinstance(node, Constant):
+ return node.value
+ else:
+ return None
+
+ def __to_opsymbol(self, op):
+ if isinstance(op, Mult):
+ return "*"
+ elif isinstance(op, Div):
+ return "/"
+ elif isinstance(op, Add):
+ return "+"
+ elif isinstance(op, Sub):
+ return "-"
+ elif isinstance(op, Pow):
+ return "^"
+ return ""
+
+ def __str__(self):
+ return f"{self.result} = {self.left}{self.__to_opsymbol(self.operator)}{self.right}"
+
def __repr__(self):
- return f"CodeOp({self.result} = f(params={self.parameters}, vars={self.variables}))"
+ return f"CodeOp({self.result} = f(params={self.parameters}, vars={self.variables}, consts={self.constants}))"
def __call__(self, *args, **kwargs: Mod) -> Mod:
loc = dict(kwargs)