aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJ08nY2020-03-09 12:44:03 +0100
committerJ08nY2020-03-09 12:44:03 +0100
commita7d3589c4ba3551ab614dfc9c931c5998fbf7fac (patch)
tree7f09b68b16b461ee6fd47d366dfc3d8444cf513e
parent0fde32d49ca8bcba19a370125be99ad0c7572009 (diff)
downloadpyecsca-codegen-a7d3589c4ba3551ab614dfc9c931c5998fbf7fac.tar.gz
pyecsca-codegen-a7d3589c4ba3551ab614dfc9c931c5998fbf7fac.tar.zst
pyecsca-codegen-a7d3589c4ba3551ab614dfc9c931c5998fbf7fac.zip
Add inversion to config, change scalar mult command.
-rw-r--r--docs/commands.rst3
-rw-r--r--pyecsca/codegen/bn/bn.c8
-rw-r--r--pyecsca/codegen/builder.py11
-rw-r--r--pyecsca/codegen/client.py32
-rw-r--r--pyecsca/codegen/hal/hal.h12
-rw-r--r--pyecsca/codegen/templates/main.c40
-rw-r--r--test/test_client.py7
-rw-r--r--test/test_impl.py2
-rw-r--r--test/test_render.py6
9 files changed, 88 insertions, 33 deletions
diff --git a/docs/commands.rst b/docs/commands.rst
index c8bdfdc..4e0118c 100644
--- a/docs/commands.rst
+++ b/docs/commands.rst
@@ -111,12 +111,13 @@ Set the public key.
Perform scalar multiplication
-----------------------------
-Perform scalar multiplication of the curve generator.
+Perform scalar multiplication of a point.
- Character: :code:`m`
- Payload: Encoded.
- :code:`s` The scalar.
+ - :code:`w` The point to multiply.
- Response:
- :code:`w` The resulting point, in the implementation coordinates.
diff --git a/pyecsca/codegen/bn/bn.c b/pyecsca/codegen/bn/bn.c
index 0d83731..53777db 100644
--- a/pyecsca/codegen/bn/bn.c
+++ b/pyecsca/codegen/bn/bn.c
@@ -202,6 +202,7 @@ bn_err bn_red_decode(bn_t *one, const bn_t *mod, const red_t *red) {
}
bn_err bn_red_add(const bn_t *one, const bn_t *other, const bn_t *mod, const red_t *red, bn_t *out) {
+#ifdef BN_NON_CONST
bn_err err;
if ((err = mp_add(one, other, out)) != BN_OKAY) {
return err;
@@ -211,9 +212,13 @@ bn_err bn_red_add(const bn_t *one, const bn_t *other, const bn_t *mod, const red
} else {
return err;
}
+#else
+ return mp_addmod(one, other, mod, out);
+#endif
}
bn_err bn_red_sub(const bn_t *one, const bn_t *other, const bn_t *mod, const red_t *red, bn_t *out) {
+#ifdef BN_NON_CONST
bn_err err;
if ((err = mp_sub(one, other, out)) != BN_OKAY) {
return err;
@@ -225,6 +230,9 @@ bn_err bn_red_sub(const bn_t *one, const bn_t *other, const bn_t *mod, const red
return mp_sub(out, mod, out);
}
return err;
+#else
+ return mp_submod(one, other, mod, out);
+#endif
}
bn_err bn_red_neg(const bn_t *one, const bn_t *mod, const red_t *red, bn_t *out) {
diff --git a/pyecsca/codegen/builder.py b/pyecsca/codegen/builder.py
index 54d4475..8ed7022 100644
--- a/pyecsca/codegen/builder.py
+++ b/pyecsca/codegen/builder.py
@@ -8,7 +8,8 @@ from typing import List, Optional, Tuple, Type, MutableMapping
import click
from public import public
-from pyecsca.ec.configuration import Multiplication, Squaring, Reduction, HashType, RandomMod
+from pyecsca.ec.configuration import (Multiplication, Squaring, Reduction, HashType, RandomMod,
+ Inversion)
from pyecsca.ec.coordinates import CoordinateModel
from pyecsca.ec.formula import Formula, AdditionFormula
from pyecsca.ec.model import CurveModel
@@ -108,6 +109,10 @@ def main():
type=click.Choice(Reduction.names()),
callback=wrap_enum(Reduction),
help="Modular reduction algorithm to use.")
+@click.option("--inv", envvar="INV", default="GCD", show_default=True,
+ type=click.Choice(Inversion.names()),
+ callback=wrap_enum(Inversion),
+ help="Modular inversion 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,
@@ -130,7 +135,7 @@ def main():
@click.argument("outdir")
@click.pass_context
@public
-def build_impl(ctx, platform, hash, rand, mul, sqr, red, keygen, ecdh, ecdsa, strip, remove,
+def build_impl(ctx, platform, hash, rand, mul, sqr, red, inv, keygen, ecdh, ecdsa, strip, remove,
verbose, model, coords, formulas, scalarmult, outdir):
"""This command builds an ECC implementation.
@@ -147,7 +152,7 @@ def build_impl(ctx, platform, hash, rand, mul, sqr, red, keygen, ecdh, ecdsa, st
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)
+ inv, platform, keygen, ecdh, ecdsa)
dir, elf_file, hex_file = render(config)
subprocess.run(["make"], cwd=dir, capture_output=not verbose)
diff --git a/pyecsca/codegen/client.py b/pyecsca/codegen/client.py
index 2a906d3..f8e7008 100644
--- a/pyecsca/codegen/client.py
+++ b/pyecsca/codegen/client.py
@@ -119,8 +119,9 @@ def cmd_set_pubkey(pubkey: Point) -> str:
@public
-def cmd_scalar_mult(scalar: int) -> str:
- return "m" + hexlify(encode_data(None, {"s": encode_scalar(scalar)})).decode()
+def cmd_scalar_mult(scalar: int, point: Point) -> str:
+ return "m" + hexlify(encode_data(None, {"s": encode_scalar(scalar),
+ "w": encode_point(point.to_affine())})).decode()
@public
@@ -201,8 +202,8 @@ class ImplTarget(SimpleSerialTarget):
self.send_cmd(SMessage.from_raw(cmd_set_pubkey(pubkey)), self.timeout)
self.pubkey = pubkey
- def scalar_mult(self, scalar: int) -> Point:
- resp = self.send_cmd(SMessage.from_raw(cmd_scalar_mult(scalar)), self.timeout)
+ def scalar_mult(self, scalar: int, point: Point) -> Point:
+ resp = self.send_cmd(SMessage.from_raw(cmd_scalar_mult(scalar, point)), self.timeout)
result = resp["w"]
plen = ((self.params.curve.prime.bit_length() + 7) // 8) * 2
params = {var: Mod(int(result.data[i * plen:(i + 1) * plen], 16), self.params.curve.prime)
@@ -272,6 +273,7 @@ class HostTarget(ImplTarget, BinaryTarget):
@click.option("--fw",
help="The firmware. Either a .hex file for a device platform or .elf for HOST platform.",
required=True)
+@click.option("--timeout", type=int, default=15000)
@click.argument("model", required=True,
type=click.Choice(["shortw", "montgom", "edwards", "twisted"]),
callback=get_model)
@@ -280,19 +282,19 @@ class HostTarget(ImplTarget, BinaryTarget):
@click.version_option()
@click.pass_context
@public
-def main(ctx, platform, fw, model, coords):
+def main(ctx, platform, fw, timeout, model, coords):
"""
A tool for communicating with built and flashed ECC implementations.
"""
ctx.ensure_object(dict)
ctx.obj["fw"] = fw
if platform != Platform.HOST:
- ctx.obj["target"] = DeviceTarget(model, coords, platform)
+ ctx.obj["target"] = DeviceTarget(model, coords, platform, timeout=timeout)
else:
if fw is None or not path.isfile(fw):
click.secho("Binary is required if the target is the host.", fg="red", err=True)
raise click.Abort
- ctx.obj["target"] = HostTarget(model, coords, binary=fw)
+ ctx.obj["target"] = HostTarget(model, coords, binary=fw, timeout=timeout)
def get_curve(ctx: click.Context, param, value: Optional[str]) -> DomainParameters:
@@ -306,22 +308,21 @@ def get_curve(ctx: click.Context, param, value: Optional[str]) -> DomainParamete
@main.command("gen")
-@click.option("--timeout", type=int, default=15000)
@click.argument("curve", required=True, callback=get_curve)
@click.pass_context
@public
-def generate(ctx: click.Context, timeout, curve):
+def generate(ctx: click.Context, curve):
"""Generate a keypair on a curve."""
ctx.ensure_object(dict)
target: ImplTarget = ctx.obj["target"]
if isinstance(target, Flashable):
target.flash(ctx.obj["fw"])
- target.timeout = timeout
target.connect()
target.set_params(curve)
start = time()
click.echo(target.generate())
click.echo(time() - start)
+ target.quit()
target.disconnect()
@@ -347,41 +348,38 @@ def get_pubkey(ctx: click.Context, param, value: Optional[str]) -> Point:
@main.command("ecdh")
-@click.option("--timeout", type=int, default=15000)
@click.argument("curve", required=True, callback=get_curve)
@click.argument("pubkey", required=True, callback=get_pubkey)
@click.pass_context
@public
-def ecdh(ctx: click.Context, timeout, curve, pubkey):
+def ecdh(ctx: click.Context, curve, pubkey):
"""Perform ECDH with a given public key."""
ctx.ensure_object(dict)
target: ImplTarget = ctx.obj["target"]
if isinstance(target, Flashable):
target.flash(ctx.obj["fw"])
- target.timeout = timeout
target.connect()
target.set_params(curve)
target.generate()
click.echo(hexlify(target.ecdh(pubkey)))
+ target.quit()
target.disconnect()
@main.command("ecdsa-sign")
-@click.option("--timeout", type=int, default=15000)
@click.argument("curve", required=True, callback=get_curve)
@click.pass_context
@public
-def ecdsa_sign(ctx: click.Context, timeout, curve):
+def ecdsa_sign(ctx: click.Context, curve):
ctx.ensure_object(dict)
# TODO
@main.command("ecdsa-verify")
-@click.option("--timeout", type=int, default=15000)
@click.argument("curve", required=True, callback=get_curve)
@click.pass_context
@public
-def ecdsa_verify(ctx: click.Context, timeout, curve):
+def ecdsa_verify(ctx: click.Context, curve):
ctx.ensure_object(dict)
# TODO
diff --git a/pyecsca/codegen/hal/hal.h b/pyecsca/codegen/hal/hal.h
index fc7fc37..51f9130 100644
--- a/pyecsca/codegen/hal/hal.h
+++ b/pyecsca/codegen/hal/hal.h
@@ -41,4 +41,16 @@ void platform_init(void);
#error "Unsupported HAL Type"
#endif
+#define NOP() __asm__ __volatile__ ("nop");
+#define _2(a) a;a
+#define NOP_2() _2(NOP())
+#define NOP_4() _2(_2(NOP()))
+#define NOP_8() _2(_2(_2(NOP())))
+#define NOP_16() _2(_2(_2(_2(NOP()))))
+#define NOP_32() _2(_2(_2(_2(_2(NOP())))))
+#define NOP_64() _2(_2(_2(_2(_2(_2(NOP()))))))
+#define NOP_128() _2(_2(_2(_2(_2(_2(_2(NOP())))))))
+#define NOP_256() _2(_2(_2(_2(_2(_2(_2(_2(NOP()))))))))
+#define NOP_512() _2(_2(_2(_2(_2(_2(_2(_2(_2(NOP())))))))))
+
#endif //HAL_H_
diff --git a/pyecsca/codegen/templates/main.c b/pyecsca/codegen/templates/main.c
index f3c6de6..2a0d575 100644
--- a/pyecsca/codegen/templates/main.c
+++ b/pyecsca/codegen/templates/main.c
@@ -200,9 +200,21 @@ static uint8_t cmd_set_pubkey(uint8_t *data, uint16_t len) {
}
static void parse_scalar_mult(const char *path, const uint8_t *data, size_t len, void *arg) {
- bn_t *scalar = (bn_t *)arg;
+ fat_t *affine = (fat_t *) arg;
+ if (strcmp(path, "wx") == 0) {
+ affine[0].len = len;
+ affine[0].value = malloc(len);
+ memcpy(affine[0].value, data, len);
+ return;
+ }
+ if (strcmp(path, "wy") == 0) {
+ affine[1].len = len;
+ affine[1].value = malloc(len);
+ memcpy(affine[1].value, data, len);
+ return;
+ }
if (strcmp(path, "s") == 0) {
- bn_from_bin(data, len, scalar);
+ bn_from_bin(data, len, (bn_t *) affine[2].value);
return;
}
}
@@ -210,13 +222,26 @@ static void parse_scalar_mult(const char *path, const uint8_t *data, size_t len,
static uint8_t cmd_scalar_mult(uint8_t *data, uint16_t len) {
// perform base point scalar mult with supplied scalar.
bn_t scalar; bn_init(&scalar);
- parse_data(data, len, "", parse_scalar_mult, (void *) &scalar);
+ point_t *other = point_new();
+ fat_t affine[3] = {fat_empty, fat_empty, {0, (void *) &scalar}};
+ parse_data(data, len, "", parse_scalar_mult, (void *) affine);
size_t coord_size = bn_to_bin_size(&curve->p);
+ bn_t ox; bn_init(&ox);
+ bn_t oy; bn_init(&oy);
+ bn_from_bin(affine[0].value, affine[0].len, &ox);
+ bn_from_bin(affine[1].value, affine[1].len, &oy);
+ bn_red_encode(&ox, &curve->p, &curve->p_red);
+ bn_red_encode(&oy, &curve->p, &curve->p_red);
+ point_from_affine(&ox, &oy, curve, other);
+ bn_clear(&ox);
+ bn_clear(&oy);
+ free(affine[0].value);
+ free(affine[1].value);
point_t *result = point_new();
- scalar_mult(&scalar, curve->generator, curve, result);
- //point_red_decode(result, curve);
+ scalar_mult(&scalar, other, curve, result);
+ point_red_decode(result, curve);
uint8_t res[coord_size * {{ curve_variables | length }}];
{%- for variable in curve_variables %}
@@ -224,6 +249,7 @@ static uint8_t cmd_scalar_mult(uint8_t *data, uint16_t len) {
{%- endfor %}
bn_clear(&scalar);
point_free(result);
+ point_free(other);
simpleserial_put('w', coord_size * {{ curve_variables | length }}, res);
return 0;
@@ -496,9 +522,9 @@ int main(void) {
simpleserial_addcmd('t', MAX_SS_LEN, cmd_set_trigger);
simpleserial_addcmd('d', MAX_SS_LEN, cmd_debug);
- led_ok(1);
+ //led_ok(1);
while(simpleserial_get());
- led_ok(0);
+ //led_ok(0);
bn_clear(&privkey);
curve_free(curve);
diff --git a/test/test_client.py b/test/test_client.py
index 804fd7c..aa07ff0 100644
--- a/test/test_client.py
+++ b/test/test_client.py
@@ -10,7 +10,7 @@ from pyecsca.codegen.client import (encode_data, decode_data, encode_scalar, cmd
cmd_set_params, cmd_set_pubkey, cmd_set_privkey,
cmd_scalar_mult,
cmd_ecdh, cmd_ecdsa_sign, cmd_ecdsa_verify, cmd_generate,
- cmd_debug, main)
+ cmd_debug, main, cmd_set_trigger, Triggers)
class EncodingTests(TestCase):
@@ -49,7 +49,7 @@ class CommandTest(TestCase):
cmd_set_privkey(0x123456789)
def test_scalar_mult(self):
- cmd_scalar_mult(0x123456789)
+ cmd_scalar_mult(0x123456789, self.curve.generator)
def test_ecdh(self):
cmd_ecdh(self.curve.generator)
@@ -60,6 +60,9 @@ class CommandTest(TestCase):
def test_ecdsa_verify(self):
cmd_ecdsa_verify(b"something", b"signature")
+ def test_set_trigger(self):
+ cmd_set_trigger(Triggers.add)
+
def test_debug(self):
cmd_debug()
diff --git a/test/test_impl.py b/test/test_impl.py
index 7e37722..ee56c41 100644
--- a/test/test_impl.py
+++ b/test/test_impl.py
@@ -144,7 +144,7 @@ class ScalarMultiplicationTests(ImplTests):
def callback(target, mult, params):
for value in values:
- result = target.scalar_mult(value)
+ result = target.scalar_mult(value, params.generator)
expected = mult.multiply(value)
self.assertEqual(result, expected)
diff --git a/test/test_render.py b/test/test_render.py
index eefa626..1c7acf7 100644
--- a/test/test_render.py
+++ b/test/test_render.py
@@ -1,7 +1,8 @@
import tempfile
from unittest import TestCase
-from pyecsca.ec.configuration import HashType, RandomMod, Multiplication, Squaring, Reduction
+from pyecsca.ec.configuration import (HashType, RandomMod, Multiplication, Squaring, Reduction,
+ Inversion)
from pyecsca.ec.curves import get_params
from pyecsca.ec.mult import LTRMultiplier
@@ -18,6 +19,7 @@ class RenderTests(TestCase):
mult = Multiplication.BASE
sqr = Squaring.BASE
red = Reduction.BASE
+ inv = Inversion.GCD
params = get_params("secg", "secp128r1", "projective")
model = params.curve.model
coords = params.curve.coordinate_model
@@ -27,6 +29,6 @@ class RenderTests(TestCase):
formulas = [add, dbl, scl]
scalarmult = LTRMultiplier(add, dbl, scl)
config = DeviceConfiguration(model, coords, formulas, scalarmult, hash_type, mod_rand, mult,
- sqr, red, platform, True, True, True)
+ sqr, red, inv, platform, True, True, True)
temp = tempfile.mkdtemp()
render_and_build(config, temp, True)