aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJ08nY2020-02-26 17:12:47 +0100
committerJ08nY2020-02-26 17:12:47 +0100
commitee47dd194d90a7b4e66be13b02e105fc2ef064eb (patch)
tree85c7c6410c723a15077c7ad73b4a0e9891603d86
parentf78ff987ac2df62dbd8326ce33ae61c97673710e (diff)
downloadpyecsca-codegen-ee47dd194d90a7b4e66be13b02e105fc2ef064eb.tar.gz
pyecsca-codegen-ee47dd194d90a7b4e66be13b02e105fc2ef064eb.tar.zst
pyecsca-codegen-ee47dd194d90a7b4e66be13b02e105fc2ef064eb.zip
Add ECDH.
-rw-r--r--pyecsca/codegen/client.py63
-rw-r--r--pyecsca/codegen/hal/stm32f3/stm32f3_hal.c4
2 files changed, 58 insertions, 9 deletions
diff --git a/pyecsca/codegen/client.py b/pyecsca/codegen/client.py
index 04f47d3..e166704 100644
--- a/pyecsca/codegen/client.py
+++ b/pyecsca/codegen/client.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
+import re
from binascii import hexlify, unhexlify
from os import path
-from time import time, sleep
from typing import Mapping, Union, Optional, Tuple
import chipwhisperer as cw
@@ -178,7 +178,8 @@ class ImplTarget(SimpleSerialTarget):
resp = self.send_cmd(SMessage.from_raw(cmd_scalar_mult(scalar)), 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) for
+ params = {var: Mod(int(result.data[i * plen:(i + 1) * plen], 16), self.params.curve.prime)
+ for
i, var in enumerate(self.coords.variables)}
return Point(self.coords, **params)
@@ -206,7 +207,7 @@ class ImplTarget(SimpleSerialTarget):
@public
class DeviceTarget(ImplTarget, ChipWhispererTarget):
- def __init__(self, model: CurveModel, coords: CoordinateModel, platform: Platform):
+ def __init__(self, model: CurveModel, coords: CoordinateModel, platform: Platform, **kwargs):
scope = cw.scope()
scope.default_setup()
target = SimpleSerial()
@@ -216,7 +217,8 @@ class DeviceTarget(ImplTarget, ChipWhispererTarget):
programmer = XMEGAProgrammer
else:
raise ValueError
- super().__init__(model, coords, target=target, scope=scope, programmer=programmer)
+ super().__init__(model, coords, target=target, scope=scope, programmer=programmer, **kwargs)
+
@public
class HostTarget(ImplTarget, BinaryTarget):
@@ -262,6 +264,7 @@ def get_curve(ctx: click.Context, param, value: Optional[str]) -> DomainParamete
ctx.ensure_object(dict)
category, name = value.split("/")
curve = get_params(category, name, ctx.obj["coords"].name)
+ ctx.obj["params"] = curve
return curve
@@ -271,6 +274,7 @@ def get_curve(ctx: click.Context, param, value: Optional[str]) -> DomainParamete
@click.pass_context
@public
def generate(ctx: click.Context, timeout, curve):
+ """Generate a keypair on a curve."""
ctx.ensure_object(dict)
target: ImplTarget = ctx.obj["target"]
if isinstance(target, Flashable):
@@ -282,17 +286,62 @@ def generate(ctx: click.Context, timeout, curve):
target.disconnect()
+def get_pubkey(ctx: click.Context, param, value: Optional[str]) -> Point:
+ if value is None:
+ return None
+ ctx.ensure_object(dict)
+ curve: DomainParameters = ctx.obj["params"]
+ if re.match("04([0-9a-fA-F]{2})+", value):
+ value = value[2:]
+ plen = len(value) // 2
+ x = int(value[:plen], 16)
+ y = int(value[plen:], 16)
+ elif re.match("[0-9]+,[0-9]+", value):
+ x, y = value.split(",")
+ x = int(x)
+ y = int(y)
+ else:
+ raise click.BadParameter("Couldn't parse pubkey: {}.".format(value))
+ x = Mod(x, curve.curve.prime)
+ y = Mod(y, curve.curve.prime)
+ return Point(AffineCoordinateModel(curve.curve.model), x=x, y=y)
+
+
@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):
+def ecdh(ctx: click.Context, timeout, 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.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):
ctx.ensure_object(dict)
-@main.command("ecdsa")
+@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(ctx: click.Context):
+def ecdsa_sign(ctx: click.Context, timeout, curve):
ctx.ensure_object(dict)
diff --git a/pyecsca/codegen/hal/stm32f3/stm32f3_hal.c b/pyecsca/codegen/hal/stm32f3/stm32f3_hal.c
index 16cd2d2..b5480f3 100644
--- a/pyecsca/codegen/hal/stm32f3/stm32f3_hal.c
+++ b/pyecsca/codegen/hal/stm32f3/stm32f3_hal.c
@@ -76,7 +76,7 @@ void init_uart(void)
HAL_GPIO_Init(GPIOA, &GpioInit);
UartHandle.Instance = USART1;
- UartHandle.Init.BaudRate = 38400;
+ UartHandle.Init.BaudRate = 115200;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
@@ -122,7 +122,7 @@ void putch(char c)
uint8_t d = c;
HAL_UART_Transmit(&UartHandle, &d, 1, 5000);
}
-#if (PLATFORM==CWLITEARM)
+#if (PLATFORM==CWLITEARM || PLATFORM==CW308_STM32F3)
void change_err_led(int x)
{
if (x)