aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2020-02-19 14:09:49 +0100
committerJ08nY2020-02-19 14:09:49 +0100
commitdacf1e8950031ed01e5d3da0ad0934a209de0a41 (patch)
tree64254ccf63e7efc7df26b3a6d2861e676648354f
parent3fc44b54ebe364a1c38cdc3e7f59b20b22fc2220 (diff)
downloadpyecsca-dacf1e8950031ed01e5d3da0ad0934a209de0a41.tar.gz
pyecsca-dacf1e8950031ed01e5d3da0ad0934a209de0a41.tar.bz2
pyecsca-dacf1e8950031ed01e5d3da0ad0934a209de0a41.zip
Enforce coordinate model assumptions when loading curves.
-rw-r--r--pyecsca/ec/coordinates.py4
-rw-r--r--pyecsca/ec/curves.py9
-rw-r--r--pyecsca/ec/model.py6
-rw-r--r--pyecsca/ec/mult.py82
-rw-r--r--pyecsca/ec/params.py2
-rw-r--r--pyecsca/sca/target/__init__.py1
-rw-r--r--test/ec/test_curves.py4
-rw-r--r--test/ec/test_mult.py12
8 files changed, 67 insertions, 53 deletions
diff --git a/pyecsca/ec/coordinates.py b/pyecsca/ec/coordinates.py
index 9043e76..1838659 100644
--- a/pyecsca/ec/coordinates.py
+++ b/pyecsca/ec/coordinates.py
@@ -20,7 +20,7 @@ class CoordinateModel(object):
variables: List[str]
satisfying: List[Module]
parameters: List[str]
- assumptions: List[Expression]
+ assumptions: List[Module]
formulas: MutableMapping[str, Formula]
def __repr__(self):
@@ -99,7 +99,7 @@ class EFDCoordinateModel(CoordinateModel):
self.parameters.append(line[10:])
elif line.startswith("assume"):
self.assumptions.append(
- parse(line[7:].replace("=", "==").replace("^", "**"), mode="eval"))
+ parse(line[7:].replace("^", "**"), mode="exec"))
line = f.readline().decode("ascii")
def __eq__(self, other):
diff --git a/pyecsca/ec/curves.py b/pyecsca/ec/curves.py
index 09964ea..e002a9c 100644
--- a/pyecsca/ec/curves.py
+++ b/pyecsca/ec/curves.py
@@ -60,7 +60,14 @@ def get_params(category: str, name: str, coords: str) -> DomainParameters:
if coords not in model.coordinates:
raise ValueError("Coordinate model not supported for curve.")
coord_model = model.coordinates[coords]
- params = {name: int(curve["params"][name], 16) for name in param_names}
+ params = {name: Mod(int(curve["params"][name], 16), field) for name in param_names}
+ for assumption in coord_model.assumptions:
+ locals = {}
+ compiled = compile(assumption, "", mode="exec")
+ exec(compiled, None, locals)
+ for param, value in locals.items():
+ if params[param] != value:
+ raise ValueError(f"Coordinate model {coord_model} has an unsatisifed assumption on the {param} parameter (= {value}).")
elliptic_curve = EllipticCurve(model, coord_model, field, params)
affine = Point(AffineCoordinateModel(model), x=Mod(int(curve["generator"]["x"], 16), field),
y=Mod(int(curve["generator"]["y"], 16), field))
diff --git a/pyecsca/ec/model.py b/pyecsca/ec/model.py
index 093a3cb..90c99a3 100644
--- a/pyecsca/ec/model.py
+++ b/pyecsca/ec/model.py
@@ -10,6 +10,7 @@ from .coordinates import EFDCoordinateModel, CoordinateModel
class CurveModel(object):
"""A model(form) of an elliptic curve."""
name: str
+ shortname: str
coordinates: MutableMapping[str, CoordinateModel]
parameter_names: List[str]
coordinate_names: List[str]
@@ -34,6 +35,7 @@ class EFDCurveModel(CurveModel):
def __init__(self, efd_name: str):
self._efd_name = efd_name
+ self.shortname = efd_name
if self._loaded:
return
self.__class__._loaded = True
@@ -91,6 +93,10 @@ class EFDCurveModel(CurveModel):
def __read_coordinate_dir(self, cls, dir_path, name):
cls.coordinates[name] = EFDCoordinateModel(dir_path, name, self)
+ @classmethod
+ def add(cls, one, other):
+ pass
+
def __eq__(self, other):
if not isinstance(other, EFDCurveModel):
return False
diff --git a/pyecsca/ec/mult.py b/pyecsca/ec/mult.py
index 35cb6fe..ae7155b 100644
--- a/pyecsca/ec/mult.py
+++ b/pyecsca/ec/mult.py
@@ -39,7 +39,7 @@ class ScalarMultiplier(ABC):
optionals: ClassVar[Set[Type[Formula]]]
short_circuit: bool
formulas: Mapping[str, Formula]
- _group: DomainParameters
+ _params: DomainParameters
_point: Point
_initialized: bool = False
@@ -54,56 +54,56 @@ class ScalarMultiplier(ABC):
if "add" not in self.formulas:
raise NotImplementedError
if self.short_circuit:
- if one == self._group.neutral:
+ if one == self._params.neutral:
return copy(other)
- if other == self._group.neutral:
+ if other == self._params.neutral:
return copy(one)
- return self.formulas["add"](one, other, **self._group.curve.parameters)[0]
+ return self.formulas["add"](one, other, **self._params.curve.parameters)[0]
def _dbl(self, point: Point) -> Point:
if "dbl" not in self.formulas:
raise NotImplementedError
if self.short_circuit:
- if point == self._group.neutral:
+ if point == self._params.neutral:
return copy(point)
- return self.formulas["dbl"](point, **self._group.curve.parameters)[0]
+ return self.formulas["dbl"](point, **self._params.curve.parameters)[0]
def _scl(self, point: Point) -> Point:
if "scl" not in self.formulas:
raise NotImplementedError
- return self.formulas["scl"](point, **self._group.curve.parameters)[0]
+ return self.formulas["scl"](point, **self._params.curve.parameters)[0]
def _ladd(self, start: Point, to_dbl: Point, to_add: Point) -> Tuple[Point, ...]:
if "ladd" not in self.formulas:
raise NotImplementedError
if self.short_circuit:
- if to_dbl == self._group.neutral:
+ if to_dbl == self._params.neutral:
return to_dbl, to_add
- if to_add == self._group.neutral:
+ if to_add == self._params.neutral:
return self._dbl(to_dbl), to_dbl
- return self.formulas["ladd"](start, to_dbl, to_add, **self._group.curve.parameters)
+ return self.formulas["ladd"](start, to_dbl, to_add, **self._params.curve.parameters)
def _dadd(self, start: Point, one: Point, other: Point) -> Point:
if "dadd" not in self.formulas:
raise NotImplementedError
if self.short_circuit:
- if one == self._group.neutral:
+ if one == self._params.neutral:
return copy(other)
- if other == self._group.neutral:
+ if other == self._params.neutral:
return copy(one)
- return self.formulas["dadd"](start, one, other, **self._group.curve.parameters)[0]
+ return self.formulas["dadd"](start, one, other, **self._params.curve.parameters)[0]
def _neg(self, point: Point) -> Point:
if "neg" not in self.formulas:
raise NotImplementedError
- return self.formulas["neg"](point, **self._group.curve.parameters)[0]
+ return self.formulas["neg"](point, **self._params.curve.parameters)[0]
- def init(self, group: DomainParameters, point: Point):
- """Initialize the scalar multiplier with a group and a point."""
+ def init(self, params: DomainParameters, point: Point):
+ """Initialize the scalar multiplier with params and a point."""
coord_model = set(self.formulas.values()).pop().coordinate_model
- if group.curve.coordinate_model != coord_model or point.coordinate_model != coord_model:
+ if params.curve.coordinate_model != coord_model or point.coordinate_model != coord_model:
raise ValueError
- self._group = group
+ self._params = params
self._point = point
self._initialized = True
@@ -137,11 +137,11 @@ class LTRMultiplier(ScalarMultiplier):
raise ValueError("ScalaMultiplier not initialized.")
with ScalarMultiplicationAction(self._point, scalar):
if scalar == 0:
- return copy(self._group.neutral)
+ return copy(self._params.neutral)
if self.complete:
q = self._point
- r = copy(self._group.neutral)
- top = self._group.order.bit_length() - 1
+ r = copy(self._params.neutral)
+ top = self._params.order.bit_length() - 1
else:
q = self._dbl(self._point)
r = copy(self._point)
@@ -178,9 +178,9 @@ class RTLMultiplier(ScalarMultiplier):
raise ValueError("ScalaMultiplier not initialized.")
with ScalarMultiplicationAction(self._point, scalar):
if scalar == 0:
- return copy(self._group.neutral)
+ return copy(self._params.neutral)
q = self._point
- r = copy(self._group.neutral)
+ r = copy(self._params.neutral)
while scalar > 0:
if scalar & 1 != 0:
r = self._add(r, q)
@@ -213,7 +213,7 @@ class CoronMultiplier(ScalarMultiplier):
raise ValueError("ScalaMultiplier not initialized.")
with ScalarMultiplicationAction(self._point, scalar):
if scalar == 0:
- return copy(self._group.neutral)
+ return copy(self._params.neutral)
q = self._point
p0 = copy(q)
for i in range(scalar.bit_length() - 2, -1, -1):
@@ -247,12 +247,12 @@ class LadderMultiplier(ScalarMultiplier):
raise ValueError("ScalaMultiplier not initialized.")
with ScalarMultiplicationAction(self._point, scalar):
if scalar == 0:
- return copy(self._group.neutral)
+ return copy(self._params.neutral)
q = self._point
if self.complete:
- p0 = copy(self._group.neutral)
+ p0 = copy(self._params.neutral)
p1 = self._point
- top = self._group.order.bit_length() - 1
+ top = self._params.order.bit_length() - 1
else:
p0 = copy(q)
p1 = self._dbl(q)
@@ -286,12 +286,12 @@ class SimpleLadderMultiplier(ScalarMultiplier):
raise ValueError("ScalaMultiplier not initialized.")
with ScalarMultiplicationAction(self._point, scalar):
if scalar == 0:
- return copy(self._group.neutral)
+ return copy(self._params.neutral)
if self.complete:
- top = self._group.order.bit_length() - 1
+ top = self._params.order.bit_length() - 1
else:
top = scalar.bit_length() - 1
- p0 = copy(self._group.neutral)
+ p0 = copy(self._params.neutral)
p1 = copy(self._point)
for i in range(top, -1, -1):
if scalar & (1 << i) == 0:
@@ -324,13 +324,13 @@ class DifferentialLadderMultiplier(ScalarMultiplier):
raise ValueError("ScalaMultiplier not initialized.")
with ScalarMultiplicationAction(self._point, scalar):
if scalar == 0:
- return copy(self._group.neutral)
+ return copy(self._params.neutral)
if self.complete:
- top = self._group.order.bit_length() - 1
+ top = self._params.order.bit_length() - 1
else:
top = scalar.bit_length() - 1
q = self._point
- p0 = copy(self._group.neutral)
+ p0 = copy(self._params.neutral)
p1 = copy(q)
for i in range(top, -1, -1):
if scalar & (1 << i) == 0:
@@ -355,8 +355,8 @@ class BinaryNAFMultiplier(ScalarMultiplier):
neg: NegationFormula, scl: ScalingFormula = None, short_circuit: bool = True):
super().__init__(short_circuit=short_circuit, add=add, dbl=dbl, neg=neg, scl=scl)
- def init(self, group: DomainParameters, point: Point):
- super().init(group, point)
+ def init(self, params: DomainParameters, point: Point):
+ super().init(params, point)
self._point_neg = self._neg(point)
def multiply(self, scalar: int) -> Point:
@@ -364,9 +364,9 @@ class BinaryNAFMultiplier(ScalarMultiplier):
raise ValueError("ScalaMultiplier not initialized.")
with ScalarMultiplicationAction(self._point, scalar):
if scalar == 0:
- return copy(self._group.neutral)
+ return copy(self._params.neutral)
bnaf = naf(scalar)
- q = copy(self._group.neutral)
+ q = copy(self._params.neutral)
for val in bnaf:
q = self._dbl(q)
if val == 1:
@@ -395,8 +395,8 @@ class WindowNAFMultiplier(ScalarMultiplier):
self.width = width
self.precompute_negation = precompute_negation
- def init(self, group: DomainParameters, point: Point):
- super().init(group, point)
+ def init(self, params: DomainParameters, point: Point):
+ super().init(params, point)
self._points = {}
self._points_neg = {}
current_point = point
@@ -412,9 +412,9 @@ class WindowNAFMultiplier(ScalarMultiplier):
raise ValueError("ScalaMultiplier not initialized.")
with ScalarMultiplicationAction(self._point, scalar):
if scalar == 0:
- return copy(self._group.neutral)
+ return copy(self._params.neutral)
naf = wnaf(scalar, self.width)
- q = copy(self._group.neutral)
+ q = copy(self._params.neutral)
for val in naf:
q = self._dbl(q)
if val > 0:
diff --git a/pyecsca/ec/params.py b/pyecsca/ec/params.py
index 7c2e504..41d8a78 100644
--- a/pyecsca/ec/params.py
+++ b/pyecsca/ec/params.py
@@ -8,7 +8,7 @@ from .point import Point
@public
class DomainParameters(object):
- """A (sub)group of an elliptic curve."""
+ """Domain parameters which specify a subgroup on an elliptic curve."""
curve: EllipticCurve
generator: Point
neutral: Point
diff --git a/pyecsca/sca/target/__init__.py b/pyecsca/sca/target/__init__.py
index e75526a..86317df 100644
--- a/pyecsca/sca/target/__init__.py
+++ b/pyecsca/sca/target/__init__.py
@@ -2,6 +2,7 @@
from .ISO7816 import *
from .base import *
+from .serial import *
has_chipwhisperer = False
has_pyscard = False
diff --git a/test/ec/test_curves.py b/test/ec/test_curves.py
index 1f6a117..173aaf2 100644
--- a/test/ec/test_curves.py
+++ b/test/ec/test_curves.py
@@ -17,9 +17,9 @@ class CurvesTests(TestCase):
("other/E-222", "projective")
])
def test_get_params(self, name, coords):
- group = get_params(*name.split("/"), coords)
+ params = get_params(*name.split("/"), coords)
try:
- assert group.curve.is_on_curve(group.generator)
+ assert params.curve.is_on_curve(params.generator)
except NotImplementedError:
pass
diff --git a/test/ec/test_mult.py b/test/ec/test_mult.py
index 2f4308e..6c89521 100644
--- a/test/ec/test_mult.py
+++ b/test/ec/test_mult.py
@@ -30,17 +30,17 @@ class ScalarMultiplierTests(TestCase):
else:
assert one.equals(other)
- def do_basic_test(self, mult_class, group, base, add, dbl, scale, neg=None, **kwargs):
- mult = mult_class(*self.get_formulas(group.curve.coordinate_model, add, dbl, neg, scale),
+ def do_basic_test(self, mult_class, params, base, add, dbl, scale, neg=None, **kwargs):
+ mult = mult_class(*self.get_formulas(params.curve.coordinate_model, add, dbl, neg, scale),
**kwargs)
- mult.init(group, base)
+ mult.init(params, base)
res = mult.multiply(314)
other = mult.multiply(157)
- mult.init(group, other)
+ mult.init(params, other)
other = mult.multiply(2)
self.assertPointEquality(res, other, scale)
- mult.init(group, base)
- self.assertEqual(InfinityPoint(group.curve.coordinate_model), mult.multiply(0))
+ mult.init(params, base)
+ self.assertEqual(InfinityPoint(params.curve.coordinate_model), mult.multiply(0))
@parameterized.expand([
("scaled", "add-1998-cmo", "dbl-1998-cmo", "z"),