aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2020-03-03 13:32:14 +0100
committerJ08nY2020-03-03 13:32:14 +0100
commit9ed79b918009580a04649c7acdce63247d2314ed (patch)
tree1f26c579818583cbdc763ee8aa6b7da33d3e8921
parentc5d813d80c5314b3609ee88a21bac625a9ae5d60 (diff)
downloadpyecsca-9ed79b918009580a04649c7acdce63247d2314ed.tar.gz
pyecsca-9ed79b918009580a04649c7acdce63247d2314ed.tar.bz2
pyecsca-9ed79b918009580a04649c7acdce63247d2314ed.zip
Add support for getting neutral points in coordinate systems.
-rw-r--r--Makefile2
-rw-r--r--pyecsca/ec/coordinates.py10
-rw-r--r--pyecsca/ec/curves.py19
-rw-r--r--pyecsca/ec/efd/shortw/jacobian-0/variables3
-rw-r--r--pyecsca/ec/efd/shortw/jacobian-3/variables3
-rw-r--r--pyecsca/ec/efd/shortw/jacobian/variables3
-rw-r--r--pyecsca/ec/efd/shortw/projective-1/variables3
-rw-r--r--pyecsca/ec/efd/shortw/projective-3/variables3
-rw-r--r--pyecsca/ec/efd/shortw/projective/variables3
-rw-r--r--pyecsca/sca/target/binary.py12
-rw-r--r--pyecsca/sca/target/chipwhisperer.py1
-rw-r--r--test/data/target.py17
-rw-r--r--test/ec/test_curves.py5
-rw-r--r--test/sca/test_target.py20
14 files changed, 95 insertions, 9 deletions
diff --git a/Makefile b/Makefile
index 0f52507..0e43a25 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ ec.test_params ec.test_key_agreement ec.test_key_generation ec.test_mod ec.test_
ec.test_mult ec.test_naf ec.test_op ec.test_point ec.test_signature
SCA_TESTS = sca.test_align sca.test_combine sca.test_edit sca.test_filter sca.test_match sca.test_process \
-sca.test_sampling sca.test_test sca.test_trace sca.test_traceset
+sca.test_sampling sca.test_target sca.test_test sca.test_trace sca.test_traceset
TESTS = ${EC_TESTS} ${SCA_TESTS}
diff --git a/pyecsca/ec/coordinates.py b/pyecsca/ec/coordinates.py
index 1838659..f8642cf 100644
--- a/pyecsca/ec/coordinates.py
+++ b/pyecsca/ec/coordinates.py
@@ -21,6 +21,7 @@ class CoordinateModel(object):
satisfying: List[Module]
parameters: List[str]
assumptions: List[Module]
+ neutral: List[Module]
formulas: MutableMapping[str, Formula]
def __repr__(self):
@@ -38,6 +39,7 @@ class AffineCoordinateModel(CoordinateModel):
self.satisfying = []
self.parameters = []
self.assumptions = []
+ self.neutral = []
self.formulas = {}
def __eq__(self, other):
@@ -55,6 +57,7 @@ class EFDCoordinateModel(CoordinateModel):
self.satisfying = []
self.parameters = []
self.assumptions = []
+ self.neutral = []
self.formulas = {}
for fname in resource_listdir(__name__, dir_path):
file_path = join(dir_path, fname)
@@ -88,12 +91,17 @@ class EFDCoordinateModel(CoordinateModel):
self.full_name = line[5:]
elif line.startswith("variable"):
self.variables.append(line[9:])
+ elif line.startswith("neutral"):
+ try:
+ code = parse(line[8:].replace("^", "**"), mode="exec")
+ self.neutral.append(code)
+ except SyntaxError:
+ pass
elif line.startswith("satisfying"):
try:
code = parse(line[11:].replace("^", "**"), mode="exec")
self.satisfying.append(code)
except SyntaxError:
- # code = parse(line[11:].replace("=", "==").replace("^", "**"), mode="eval")
pass
elif line.startswith("parameter"):
self.parameters.append(line[10:])
diff --git a/pyecsca/ec/curves.py b/pyecsca/ec/curves.py
index 9240be2..bc8329f 100644
--- a/pyecsca/ec/curves.py
+++ b/pyecsca/ec/curves.py
@@ -14,7 +14,7 @@ from .point import Point, InfinityPoint
@public
-def get_params(category: str, name: str, coords: str) -> DomainParameters:
+def get_params(category: str, name: str, coords: str, infty: bool = True) -> DomainParameters:
"""
Retrieve a curve from a set of stored parameters. Uses the std-curves database at
https://github.com/J08nY/std-curves.
@@ -22,6 +22,8 @@ def get_params(category: str, name: str, coords: str) -> DomainParameters:
:param category: The category of the curve.
:param name: The name of the curve.
:param coords: The name of the coordinate system to use.
+ :param infty: Whether to use the special :py:class:InfinityPoint (`True`) or try to use the
+ point at infinity of the coordinate system.
:return: The curve.
"""
listing = resource_listdir(__name__, "std")
@@ -68,7 +70,20 @@ def get_params(category: str, name: str, coords: str) -> DomainParameters:
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, InfinityPoint(coord_model), params)
+ if infty:
+ infinity = InfinityPoint(coord_model)
+ else:
+ locals = {**params}
+ for line in coord_model.neutral:
+ compiled = compile(line, "", mode="exec")
+ exec(compiled, None, locals)
+ infinity_coords = {}
+ for coordinate in coord_model.variables:
+ if coordinate not in locals:
+ raise ValueError(f"Coordinate model {coord_model} requires infty option.")
+ infinity_coords[coordinate] = Mod(locals[coordinate], field)
+ infinity = Point(coord_model, **infinity_coords)
+ elliptic_curve = EllipticCurve(model, coord_model, field, infinity, params)
affine = Point(AffineCoordinateModel(model), x=Mod(int(curve["generator"]["x"], 16), field),
y=Mod(int(curve["generator"]["y"], 16), field))
generator = Point.from_affine(coord_model, affine)
diff --git a/pyecsca/ec/efd/shortw/jacobian-0/variables b/pyecsca/ec/efd/shortw/jacobian-0/variables
index 5e84b72..6ea9908 100644
--- a/pyecsca/ec/efd/shortw/jacobian-0/variables
+++ b/pyecsca/ec/efd/shortw/jacobian-0/variables
@@ -3,5 +3,8 @@ assume a = 0
variable X
variable Y
variable Z
+neutral X = 1
+neutral Y = 1
+neutral Z = 0
satisfying x = X/Z^2
satisfying y = Y/Z^3
diff --git a/pyecsca/ec/efd/shortw/jacobian-3/variables b/pyecsca/ec/efd/shortw/jacobian-3/variables
index cddb049..a4d2b49 100644
--- a/pyecsca/ec/efd/shortw/jacobian-3/variables
+++ b/pyecsca/ec/efd/shortw/jacobian-3/variables
@@ -3,5 +3,8 @@ assume a = -3
variable X
variable Y
variable Z
+neutral X = 1
+neutral Y = 1
+neutral Z = 0
satisfying x = X/Z^2
satisfying y = Y/Z^3
diff --git a/pyecsca/ec/efd/shortw/jacobian/variables b/pyecsca/ec/efd/shortw/jacobian/variables
index 7258c13..ddfbff6 100644
--- a/pyecsca/ec/efd/shortw/jacobian/variables
+++ b/pyecsca/ec/efd/shortw/jacobian/variables
@@ -2,5 +2,8 @@ name Jacobian coordinates
variable X
variable Y
variable Z
+neutral X = 1
+neutral Y = 1
+neutral Z = 0
satisfying x = X/Z^2
satisfying y = Y/Z^3
diff --git a/pyecsca/ec/efd/shortw/projective-1/variables b/pyecsca/ec/efd/shortw/projective-1/variables
index 49b8f7a..f807365 100644
--- a/pyecsca/ec/efd/shortw/projective-1/variables
+++ b/pyecsca/ec/efd/shortw/projective-1/variables
@@ -3,5 +3,8 @@ assume a = -1
variable X
variable Y
variable Z
+neutral X = 0
+neutral Y = 1
+neutral Z = 0
satisfying x = X/Z
satisfying y = Y/Z
diff --git a/pyecsca/ec/efd/shortw/projective-3/variables b/pyecsca/ec/efd/shortw/projective-3/variables
index 1de70b5..2458576 100644
--- a/pyecsca/ec/efd/shortw/projective-3/variables
+++ b/pyecsca/ec/efd/shortw/projective-3/variables
@@ -3,5 +3,8 @@ assume a = -3
variable X
variable Y
variable Z
+neutral X = 0
+neutral Y = 1
+neutral Z = 0
satisfying x = X/Z
satisfying y = Y/Z
diff --git a/pyecsca/ec/efd/shortw/projective/variables b/pyecsca/ec/efd/shortw/projective/variables
index 9c6045b..4ba1c7b 100644
--- a/pyecsca/ec/efd/shortw/projective/variables
+++ b/pyecsca/ec/efd/shortw/projective/variables
@@ -2,5 +2,8 @@ name projective coordinates
variable X
variable Y
variable Z
+neutral X = 0
+neutral Y = 1
+neutral Z = 0
satisfying x = X/Z
satisfying y = Y/Z
diff --git a/pyecsca/sca/target/binary.py b/pyecsca/sca/target/binary.py
index 62d1102..9a469b6 100644
--- a/pyecsca/sca/target/binary.py
+++ b/pyecsca/sca/target/binary.py
@@ -1,6 +1,6 @@
import subprocess
from subprocess import Popen
-from typing import Optional
+from typing import Optional, Union, List
from public import public
@@ -9,17 +9,21 @@ from .serial import SerialTarget
@public
class BinaryTarget(SerialTarget):
- binary: str
+ binary: List[str]
process: Optional[Popen]
debug_output: bool
- def __init__(self, binary: str, debug_output: bool = False, **kwargs):
+ def __init__(self, binary: Union[str, List[str]], debug_output: bool = False, **kwargs):
super().__init__(**kwargs)
+ if not isinstance(binary, (str, list)):
+ raise TypeError
+ if isinstance(binary, str):
+ binary = [binary]
self.binary = binary
self.debug_output = debug_output
def connect(self):
- self.process = Popen([self.binary], stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ self.process = Popen(self.binary, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
text=True, bufsize=1)
def write(self, data: bytes):
diff --git a/pyecsca/sca/target/chipwhisperer.py b/pyecsca/sca/target/chipwhisperer.py
index 0528618..1dcdbe3 100644
--- a/pyecsca/sca/target/chipwhisperer.py
+++ b/pyecsca/sca/target/chipwhisperer.py
@@ -1,4 +1,3 @@
-from binascii import unhexlify
from typing import Optional
from time import sleep
diff --git a/test/data/target.py b/test/data/target.py
new file mode 100644
index 0000000..1583597
--- /dev/null
+++ b/test/data/target.py
@@ -0,0 +1,17 @@
+from sys import stdout
+
+if __name__ == "__main__":
+
+ while True:
+ line = input()
+ char = line[0]
+ content = line[1:]
+ if char == "d":
+ for c in "r01020304":
+ stdout.write(c)
+ stdout.write("\n")
+ for c in "z00":
+ stdout.write(c)
+ stdout.write("\n")
+ elif char == "x":
+ break \ No newline at end of file
diff --git a/test/ec/test_curves.py b/test/ec/test_curves.py
index 11861c4..fba932a 100644
--- a/test/ec/test_curves.py
+++ b/test/ec/test_curves.py
@@ -37,6 +37,11 @@ class CurvesTests(TestCase):
get_params("secg", "secp128r1", "projective-1")
self.assertIsNotNone(get_params("secg", "secp128r1", "projective-3"))
+ def test_infty(self):
+ with self.assertRaises(ValueError):
+ get_params("secg", "secp128r1", "modified", False)
+ self.assertIsNotNone(get_params("secg", "secp128r1", "projective", False))
+
def test_no_binary(self):
with self.assertRaises(ValueError):
get_params("secg", "sect163r1", "something") \ No newline at end of file
diff --git a/test/sca/test_target.py b/test/sca/test_target.py
new file mode 100644
index 0000000..25d506a
--- /dev/null
+++ b/test/sca/test_target.py
@@ -0,0 +1,20 @@
+from unittest import TestCase
+from os.path import realpath, dirname, join
+
+
+from pyecsca.sca.target import BinaryTarget, SimpleSerialTarget, SimpleSerialMessage
+
+class TestTarget(SimpleSerialTarget, BinaryTarget):
+ pass
+
+class BinaryTargetTests(TestCase):
+
+ def test_basic_target(self):
+ target_path = join(dirname(realpath(__file__)), "..", "data", "target.py")
+ target = TestTarget(["python", target_path])
+ target.connect()
+ resp = target.send_cmd(SimpleSerialMessage("d", ""), 500)
+ self.assertIn("r", resp)
+ self.assertIn("z", resp)
+ self.assertEqual(resp["r"].data, "01020304")
+ target.disconnect() \ No newline at end of file