aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJ08nY2020-02-20 20:41:29 +0100
committerJ08nY2020-02-20 20:41:29 +0100
commit3892d994470b181f950703fabf719a9c963d1c20 (patch)
treefc1c7e68fc6334a7f89fd69eab00a830fb58f275
parent92cb16e8103da998aa1bf226d24ef6771a92c5d5 (diff)
downloadpyecsca-codegen-3892d994470b181f950703fabf719a9c963d1c20.tar.gz
pyecsca-codegen-3892d994470b181f950703fabf719a9c963d1c20.tar.zst
pyecsca-codegen-3892d994470b181f950703fabf719a9c963d1c20.zip
Add full implementation tests.
-rw-r--r--.travis.yml1
-rw-r--r--docs/commands.rst10
-rw-r--r--pyecsca/codegen/asn1/asn1.c9
-rw-r--r--pyecsca/codegen/builder.py28
-rw-r--r--pyecsca/codegen/client.py32
-rw-r--r--pyecsca/codegen/templates/main.c7
-rw-r--r--pyecsca/codegen/templates/mult_ltr.c4
-rw-r--r--pyecsca/codegen/templates/mult_rtl.c4
-rw-r--r--test/test_impl.py228
9 files changed, 256 insertions, 67 deletions
diff --git a/.travis.yml b/.travis.yml
index 050f8a2..401fb62 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,6 +19,7 @@ install:
- cd ../
- git clone https://github.com/J08nY/pyecsca
- cd pyecsca
+ - git submodule update --init --recursive
- pip install -e .
- cd ../..
- pip install -e ".[test, typecheck]"
diff --git a/docs/commands.rst b/docs/commands.rst
index 9954832..c8bdfdc 100644
--- a/docs/commands.rst
+++ b/docs/commands.rst
@@ -153,7 +153,7 @@ Verify with ECDSA
Verify a message signature with ECDSA.
-- Character: :code:`v`
+- Character: :code:`r`
- Payload: Encoded.
- :code:`d` The message to verify.
@@ -174,5 +174,13 @@ Send back the implementation configuration (model and coordinate system).
- :code:`d` The model shortname and coordinate system name, ASCII, comma-separated.
+Check version
+-------------
+ChipWhisperer command.
+
+- Character: :code:`v`
+- Payload: none
+- Response: :code:`z00` always.
+
.. _ChipWhisperer: https://github.com/newaetech/chipwhisperer
.. _XKCP: https://github.com/XKCP/XKCP \ No newline at end of file
diff --git a/pyecsca/codegen/asn1/asn1.c b/pyecsca/codegen/asn1/asn1.c
index 3fd1f5f..13bfa5c 100644
--- a/pyecsca/codegen/asn1/asn1.c
+++ b/pyecsca/codegen/asn1/asn1.c
@@ -7,8 +7,8 @@ uint8_t *asn1_der_encode(const bn_t *r, const bn_t *s, size_t *result_len) {
uint8_t s_len = (uint8_t) bn_to_bin_size(s);
// Pad with one zero byte in case most-significant bit of top byte is one.
- uint8_t r_length = r_len + (bn_get_bit(r, r_len * 8) ? 1 : 0);
- uint8_t s_length = s_len + (bn_get_bit(s, s_len * 8) ? 1 : 0);
+ uint8_t r_length = r_len + (bn_get_bit(r, (r_len * 8) - 1) ? 1 : 0);
+ uint8_t s_length = s_len + (bn_get_bit(s, (s_len * 8) - 1) ? 1 : 0);
// R and S are < 128 bytes, so 1 byte tag + 1 byte len + len bytes value
size_t seq_value_len = 2 + r_length + 2 + s_length;
@@ -29,6 +29,7 @@ uint8_t *asn1_der_encode(const bn_t *r, const bn_t *s, size_t *result_len) {
whole_len += 1;
uint8_t *data = malloc(whole_len);
+ *result_len = whole_len;
size_t i = 0;
data[i++] = 0x30; // SEQUENCE
if (seq_value_len < 128) {
@@ -41,14 +42,14 @@ uint8_t *asn1_der_encode(const bn_t *r, const bn_t *s, size_t *result_len) {
}
data[i++] = 0x02; //INTEGER
data[i++] = r_length;
- if (bn_get_bit(r, r_len * 8)) {
+ if (bn_get_bit(r, (r_len * 8) - 1)) {
data[i++] = 0;
}
bn_to_bin(r, data + i);
i += r_len;
data[i++] = 0x02; //INTEGER
data[i++] = s_length;
- if (bn_get_bit(s, s_len * 8)) {
+ if (bn_get_bit(s, (s_len * 8) - 1)) {
data[i++] = 0;
}
bn_to_bin(s, data + i);
diff --git a/pyecsca/codegen/builder.py b/pyecsca/codegen/builder.py
index b9f9708..bf8e6be 100644
--- a/pyecsca/codegen/builder.py
+++ b/pyecsca/codegen/builder.py
@@ -73,16 +73,6 @@ def get_multiplier(ctx: click.Context, param, value: Optional[str]) -> Optional[
return mult
-def get_ecdsa(ctx: click.Context, param, value: bool) -> bool:
- if not value:
- return False
- ctx.ensure_object(dict)
- formulas = ctx.obj["formulas"]
- if not any(isinstance(formula, AdditionFormula) for formula in formulas):
- raise click.BadParameter("ECDSA needs an addition formula. None was supplied.")
- return value
-
-
@click.group(context_settings={"help_option_names": ["-h", "--help"]})
@click.version_option()
@public
@@ -118,12 +108,15 @@ def main():
type=click.Choice(Reduction.names()),
callback=wrap_enum(Reduction),
help="Modular reduction algorithm to use.")
-@click.option("--keygen/--no-keygen", help="Whether to enable keygen.", is_flag=True, default=True, show_default=True)
-@click.option("--ecdh/--no-ecdh", help="Whether to enable ECDH.", is_flag=True, default=True, show_default=True)
+@click.option("--keygen/--no-keygen", help="Whether to enable keygen.", is_flag=True, default=True,
+ show_default=True)
+@click.option("--ecdh/--no-ecdh", help="Whether to enable ECDH.", is_flag=True, default=True,
+ show_default=True)
@click.option("--ecdsa/--no-ecdsa", help="Whether to enable ECDSA.", is_flag=True, default=True,
- callback=get_ecdsa, show_default=True)
+ show_default=True)
@click.option("--strip", help="Whether to strip the binary or not.", is_flag=True)
-@click.option("--remove/--no-remove", help="Whether to remove the dir.", is_flag=True, default=True, show_default=True)
+@click.option("--remove/--no-remove", help="Whether to remove the dir.", is_flag=True, default=True,
+ show_default=True)
@click.option("-v", "--verbose", count=True)
@click.argument("model", required=True,
type=click.Choice(["shortw", "montgom", "edwards", "twisted"]),
@@ -135,8 +128,9 @@ def main():
@click.argument("scalarmult", required=True,
callback=get_multiplier)
@click.argument("outdir")
+@click.pass_context
@public
-def build_impl(platform, hash, rand, mul, sqr, red, keygen, ecdh, ecdsa, strip, remove,
+def build_impl(ctx, platform, hash, rand, mul, sqr, red, keygen, ecdh, ecdsa, strip, remove,
verbose, model, coords, formulas, scalarmult, outdir):
"""This command builds an ECC implementation.
@@ -147,6 +141,10 @@ def build_impl(platform, hash, rand, mul, sqr, red, keygen, ecdh, ecdsa, strip,
SCALARMULT: The scalar multiplication algorithm to use.
OUTDIR: The output directory for files with the built impl.
"""
+ ctx.ensure_object(dict)
+ formulas = ctx.obj["formulas"]
+ if ecdsa and not any(isinstance(formula, AdditionFormula) for formula in formulas):
+ raise click.BadParameter("ECDSA needs an addition formula. None was supplied.")
config = DeviceConfiguration(model, coords, formulas, scalarmult, hash, rand, mul, sqr, red,
platform, keygen, ecdh, ecdsa)
diff --git a/pyecsca/codegen/client.py b/pyecsca/codegen/client.py
index 197c703..cd4cff7 100644
--- a/pyecsca/codegen/client.py
+++ b/pyecsca/codegen/client.py
@@ -68,16 +68,16 @@ def cmd_init_prng(seed: bytes) -> str:
@public
-def cmd_set_params(group: DomainParameters) -> str:
+def cmd_set_params(params: DomainParameters) -> str:
data = {
- "p": encode_scalar(group.curve.prime),
- "n": encode_scalar(group.order),
- "h": encode_scalar(group.cofactor)
+ "p": encode_scalar(params.curve.prime),
+ "n": encode_scalar(params.order),
+ "h": encode_scalar(params.cofactor)
}
- for param, value in group.curve.parameters.items():
+ for param, value in params.curve.parameters.items():
data[param] = encode_scalar(value)
- data["g"] = encode_point(group.generator.to_affine())
- data["i"] = encode_point(group.neutral)
+ data["g"] = encode_point(params.generator.to_affine())
+ data["i"] = encode_point(params.curve.neutral)
return "c" + hexlify(encode_data(None, data)).decode()
@@ -113,7 +113,7 @@ def cmd_ecdsa_sign(data: bytes) -> str:
@public
def cmd_ecdsa_verify(data: bytes, sig: bytes) -> str:
- return "v" + hexlify(encode_data(None, {"d": data, "s": sig})).decode()
+ return "r" + hexlify(encode_data(None, {"d": data, "s": sig})).decode()
@public
@@ -173,7 +173,7 @@ class ImplTarget(SerialTarget):
def scalar_mult(self, scalar: int) -> Point:
self.write(cmd_scalar_mult(scalar).encode())
result = self.read(1)[1:-1]
- plen = (self.params.curve.prime + 7) // 8
+ plen = ((self.params.curve.prime.bit_length() + 7) // 8) * 2
self.read(1)
params = {var: Mod(int(result[i * plen:(i + 1) * plen], 16), self.params.curve.prime) for
i, var in enumerate(self.coords.variables)}
@@ -209,10 +209,12 @@ class ImplTarget(SerialTarget):
class BinaryTarget(ImplTarget):
binary: str
process: Optional[Popen]
+ debug_output: bool
- def __init__(self, binary: str, model: CurveModel, coords: CoordinateModel):
+ def __init__(self, binary: str, model: CurveModel, coords: CoordinateModel, debug_output: bool = False):
super().__init__(model, coords)
self.binary = binary
+ self.debug_output = debug_output
def connect(self):
self.process = Popen([self.binary], stdin=subprocess.PIPE, stdout=subprocess.PIPE,
@@ -221,20 +223,26 @@ class BinaryTarget(ImplTarget):
def write(self, data: bytes):
if self.process is None:
raise ValueError
+ if self.debug_output:
+ print(">>", data.decode())
self.process.stdin.write(data.decode() + "\n")
self.process.stdin.flush()
def read(self, timeout: int) -> bytes:
if self.process is None:
raise ValueError
- return self.process.stdout.readline().encode()
+ read = self.process.stdout.readline().encode()
+ if self.debug_output:
+ print("<<", read.decode(), end="")
+ return read
def disconnect(self):
if self.process is None:
return
self.process.stdin.close()
self.process.stdout.close()
- self.process.kill()
+ self.process.terminate()
+ self.process.wait()
@click.group(context_settings={"help_option_names": ["-h", "--help"]})
diff --git a/pyecsca/codegen/templates/main.c b/pyecsca/codegen/templates/main.c
index ae36bfd..b0f81f1 100644
--- a/pyecsca/codegen/templates/main.c
+++ b/pyecsca/codegen/templates/main.c
@@ -325,12 +325,17 @@ static uint8_t cmd_ecdsa_sign(uint8_t *data, uint16_t len) {
bn_t r; bn_init(&r);
point_to_affine(p, curve, &r, NULL);
bn_mod(&r, &curve->n, &r);
+ // r = ([k]G).x mod n
bn_t s; bn_init(&s);
bn_copy(&privkey, &s);
+ // s = x
bn_mod_mul(&s, &r, &curve->n, &s);
+ // s = rx mod n
bn_mod_add(&s, &h, &curve->n, &s);
+ // s = rx + H(m) mod n
bn_mod_div(&s, &k, &curve->n, &s);
+ // s = k^(-1)*(rx + H(m)) mod n
size_t result_len = 0;
uint8_t *result = asn1_der_encode(&r, &s, &result_len);
@@ -444,7 +449,7 @@ int main(void) {
{%- endif %}
{%- if ecdsa %}
simpleserial_addcmd('a', MAX_SS_LEN, cmd_ecdsa_sign);
- simpleserial_addcmd('v', MAX_SS_LEN, cmd_ecdsa_verify);
+ simpleserial_addcmd('r', MAX_SS_LEN, cmd_ecdsa_verify);
{%- endif %}
simpleserial_addcmd('d', MAX_SS_LEN, cmd_debug);
diff --git a/pyecsca/codegen/templates/mult_ltr.c b/pyecsca/codegen/templates/mult_ltr.c
index dbd4704..5b08b80 100644
--- a/pyecsca/codegen/templates/mult_ltr.c
+++ b/pyecsca/codegen/templates/mult_ltr.c
@@ -19,10 +19,10 @@ void scalar_mult(bn_t *scalar, point_t *point, curve_t *curve, point_t *out) {
for (int i = nbits; i >= 0; i--) {
point_dbl(r, curve, r);
if (bn_get_bit(scalar, i) == 1) {
- point_add(q, r, curve, r);
+ point_add(r, q, curve, r);
} else {
{%- if scalarmult.always %}
- point_add(q, r, curve, dummy);
+ point_add(r, q, curve, dummy);
{%- endif %}
}
}
diff --git a/pyecsca/codegen/templates/mult_rtl.c b/pyecsca/codegen/templates/mult_rtl.c
index 01d42a5..ba40a66 100644
--- a/pyecsca/codegen/templates/mult_rtl.c
+++ b/pyecsca/codegen/templates/mult_rtl.c
@@ -14,10 +14,10 @@ void scalar_mult(bn_t *scalar, point_t *point, curve_t *curve, point_t *out) {
while (!bn_is_0(&copy)) {
if (bn_get_bit(&copy, 0) == 1) {
- point_add(q, r, curve, r);
+ point_add(r, q, curve, r);
} else {
{%- if scalarmult.always %}
- point_add(q, r, curve, dummy);
+ point_add(r, q, curve, dummy);
{%- endif %}
}
point_dbl(q, curve, q);
diff --git a/test/test_impl.py b/test/test_impl.py
index 8a2bfde..267fc6b 100644
--- a/test/test_impl.py
+++ b/test/test_impl.py
@@ -1,15 +1,20 @@
+from binascii import hexlify
+from copy import copy
from os.path import join
from unittest import TestCase
from click.testing import CliRunner
from pyecsca.ec.curves import get_params
+from pyecsca.ec.key_agreement import ECDH_SHA1
from pyecsca.ec.mult import LTRMultiplier, RTLMultiplier, CoronMultiplier, BinaryNAFMultiplier
+from pyecsca.ec.point import Point
+from pyecsca.ec.signature import ECDSA_SHA1, SignatureResult
from pyecsca.codegen.builder import build_impl
from pyecsca.codegen.client import BinaryTarget
-class KeyGenerationTests(TestCase):
+class ImplTests(TestCase):
def setUp(self):
self.secp128r1 = get_params("secg", "secp128r1", "projective")
@@ -20,10 +25,13 @@ class KeyGenerationTests(TestCase):
self.base25519 = self.curve25519.generator
self.coords25519 = self.curve25519.curve.coordinate_model
- def do_basic_test(self, runner, params, mult_class, formulas, mult_name, **mult_kwargs):
+ def do_basic_test(self, callback, runner, params, mult_class, formulas, mult_name,
+ ecdsa, ecdh, **mult_kwargs):
with runner.isolated_filesystem() as tmpdir:
runner.invoke(build_impl,
- ["--platform", "HOST", "--no-ecdsa", "--no-ecdh",
+ ["--platform", "HOST",
+ "--ecdsa" if ecdsa else "--no-ecdsa",
+ "--ecdh" if ecdh else "--no-ecdh",
params.curve.model.shortname, params.curve.coordinate_model.name,
*formulas,
f"{mult_name}({','.join(f'{key}={value}' for key, value in mult_kwargs.items())})",
@@ -33,51 +41,211 @@ class KeyGenerationTests(TestCase):
params.curve.coordinate_model)
target.connect()
target.set_params(params)
- priv, pub = target.generate()
- self.assertTrue(params.curve.is_on_curve(pub))
formula_instances = [params.curve.coordinate_model.formulas[formula] for formula
in formulas]
mult = mult_class(*formula_instances, **mult_kwargs)
mult.init(params, params.generator)
- expected = mult.multiply(priv).to_affine()
- self.assertEqual(pub, expected)
+ callback(target, mult, params)
target.disconnect()
+
+class PRNGTests(ImplTests):
+
+ def test_init(self):
+ runner = CliRunner()
+
+ def callback(target, mult, params):
+ target.init_prng(bytes([0x12, 0x34, 0x56, 0x78]))
+
+ self.do_basic_test(callback, runner, self.secp128r1, LTRMultiplier,
+ ["add-1998-cmo", "dbl-1998-cmo"], "ltr", False, False, complete=False)
+
+
+class SetupTests(ImplTests):
+
+ def test_setup(self):
+ runner = CliRunner()
+
+ def callback(target, mult, params):
+ priv = 57
+ pub = mult.multiply(priv).to_affine()
+ target.set_privkey(priv)
+ target.set_pubkey(pub)
+
+ self.do_basic_test(callback, runner, self.secp128r1, LTRMultiplier,
+ ["add-1998-cmo", "dbl-1998-cmo"], "ltr", False, False, complete=False)
+
+ def test_debug(self):
+ runner = CliRunner()
+ def callback(target, mult, params):
+ model, coords = target.debug()
+ self.assertEqual(model, params.curve.model.shortname)
+ self.assertEqual(coords, params.curve.coordinate_model.name)
+ self.do_basic_test(callback, runner, self.secp128r1, LTRMultiplier,
+ ["add-1998-cmo", "dbl-1998-cmo"], "ltr", False, False, complete=False)
+
+class KeyGenerationTests(ImplTests):
+
+ def do_keygen_test(self, runner, params, mult_class, formulas, mult_name, **mult_kwargs):
+ def callback(target, mult, params):
+ for _ in range(10):
+ priv, pub = target.generate()
+ self.assertTrue(params.curve.is_on_curve(pub))
+ expected = mult.multiply(priv).to_affine()
+ self.assertEqual(pub, expected)
+
+ self.do_basic_test(callback, runner, params, mult_class, formulas, mult_name, False, False,
+ **mult_kwargs)
+
def test_ltr(self):
runner = CliRunner()
- self.do_basic_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
- "ltr",
- complete=False)
- self.do_basic_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
- "ltr",
- complete=True)
- self.do_basic_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
- "ltr",
- always=True, complete=False)
- self.do_basic_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
- "ltr",
- always=True, complete=True)
+ self.do_keygen_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", complete=False)
+ self.do_keygen_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", complete=True)
+ self.do_keygen_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", always=True, complete=False)
+ self.do_keygen_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", always=True, complete=True)
def test_rtl(self):
runner = CliRunner()
- self.do_basic_test(runner, self.secp128r1, RTLMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
- "rtl",
- always=False)
- self.do_basic_test(runner, self.secp128r1, RTLMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
- "rtl",
- always=True)
+ self.do_keygen_test(runner, self.secp128r1, RTLMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "rtl", always=False)
+ self.do_keygen_test(runner, self.secp128r1, RTLMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "rtl", always=True)
def test_coron(self):
runner = CliRunner()
- self.do_basic_test(runner, self.secp128r1, CoronMultiplier,
- ["add-1998-cmo", "dbl-1998-cmo"], "coron")
+ self.do_keygen_test(runner, self.secp128r1, CoronMultiplier,
+ ["add-1998-cmo", "dbl-1998-cmo"], "coron")
def test_bnaf(self):
runner = CliRunner()
- self.do_basic_test(runner, self.secp128r1, BinaryNAFMultiplier,
- ["add-1998-cmo", "dbl-1998-cmo", "neg"], "bnaf")
+ self.do_keygen_test(runner, self.secp128r1, BinaryNAFMultiplier,
+ ["add-1998-cmo", "dbl-1998-cmo", "neg"], "bnaf")
# def test_ladder(self):
# runner = CliRunner()
- # self.do_basic_test(runner, self.curve25519, LadderMultiplier, ["ladd-1987-m", "dbl-1987-m"], "ldr")
+ # self.do_keygen_test(runner, self.curve25519, LadderMultiplier, ["ladd-1987-m", "dbl-1987-m"], "ldr")
# # TODO: what about coords where generator is not affine?
+
+
+class ScalarMultiplicationTests(ImplTests):
+
+ def do_mult_test(self, runner, params, mult_class, formulas, mult_name, **mult_kwargs):
+ values = [15, 2355498743, 3253857901321912443757746]
+
+ def callback(target, mult, params):
+ for value in values:
+ result = target.scalar_mult(value)
+ expected = mult.multiply(value)
+ self.assertEqual(result, expected)
+
+ self.do_basic_test(callback, runner, params, mult_class, formulas, mult_name, False, False,
+ **mult_kwargs)
+
+ def test_ltr(self):
+ runner = CliRunner()
+ self.do_mult_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", complete=False)
+ self.do_mult_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", complete=True)
+ self.do_mult_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", complete=False, always=True)
+ self.do_mult_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", complete=True, always=True)
+
+ def test_rtl(self):
+ runner = CliRunner()
+ self.do_mult_test(runner, self.secp128r1, RTLMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "rtl", always=False)
+ self.do_mult_test(runner, self.secp128r1, RTLMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "rtl", always=True)
+
+ def test_coron(self):
+ runner = CliRunner()
+ self.do_mult_test(runner, self.secp128r1, CoronMultiplier,
+ ["add-1998-cmo", "dbl-1998-cmo"], "coron")
+
+ def test_bnaf(self):
+ runner = CliRunner()
+ self.do_mult_test(runner, self.secp128r1, BinaryNAFMultiplier,
+ ["add-1998-cmo", "dbl-1998-cmo", "neg"], "bnaf")
+
+
+class ECDHTests(ImplTests):
+ def do_ecdh_test(self, runner, params, mult_class, formulas, mult_name, **mult_kwargs):
+ other_privs = [15, 2355498743, 3253857901321912443757746]
+
+ def callback(target, mult, params):
+ for other_priv in other_privs:
+ priv, pub = target.generate()
+ other_pub = mult.multiply(other_priv)
+ ecdh = ECDH_SHA1(copy(mult), params, other_pub, priv)
+ result = target.ecdh(other_pub)
+ expected = ecdh.perform()
+ self.assertEqual(result, expected)
+
+ self.do_basic_test(callback, runner, params, mult_class, formulas, mult_name, False, True,
+ **mult_kwargs)
+
+ def test_ltr(self):
+ runner = CliRunner()
+ self.do_ecdh_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", complete=False)
+ self.do_ecdh_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", complete=True)
+ self.do_ecdh_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", complete=False, always=True)
+ self.do_ecdh_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", complete=True, always=True)
+
+ def test_rtl(self):
+ runner = CliRunner()
+ self.do_ecdh_test(runner, self.secp128r1, RTLMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "rtl", always=False)
+ self.do_ecdh_test(runner, self.secp128r1, RTLMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "rtl", always=True)
+
+ def test_coron(self):
+ runner = CliRunner()
+ self.do_ecdh_test(runner, self.secp128r1, CoronMultiplier,
+ ["add-1998-cmo", "dbl-1998-cmo"], "coron")
+
+ def test_bnaf(self):
+ runner = CliRunner()
+ self.do_ecdh_test(runner, self.secp128r1, BinaryNAFMultiplier,
+ ["add-1998-cmo", "dbl-1998-cmo", "neg"], "bnaf")
+
+
+class ECDSATests(ImplTests):
+ def do_ecdsa_test(self, runner, params, mult_class, formulas, mult_name, **mult_kwargs):
+ data = b"something"
+
+ def callback(target, mult, params):
+ priv, pub = target.generate()
+ ecdsa = ECDSA_SHA1(copy(mult), params, mult.formulas["add"],
+ Point.from_affine(params.curve.coordinate_model, pub), priv)
+
+
+ signature_data = target.ecdsa_sign(data)
+ result = SignatureResult.from_DER(signature_data)
+ self.assertTrue(ecdsa.verify_data(result, data))
+
+ expected = ecdsa.sign_data(data).to_DER()
+ self.assertTrue(target.ecdsa_verify(data, expected))
+
+ self.do_basic_test(callback, runner, params, mult_class, formulas, mult_name, True,
+ False, **mult_kwargs)
+
+ def test_ltr(self):
+ runner = CliRunner()
+ self.do_ecdsa_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", complete=False)
+ self.do_ecdsa_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", complete=True)
+ self.do_ecdsa_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", complete=False, always=True)
+ self.do_ecdsa_test(runner, self.secp128r1, LTRMultiplier, ["add-1998-cmo", "dbl-1998-cmo"],
+ "ltr", complete=True, always=True)