aboutsummaryrefslogtreecommitdiffhomepage
path: root/pyecsca/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'pyecsca/codegen')
-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
5 files changed, 76 insertions, 27 deletions
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);