aboutsummaryrefslogtreecommitdiffhomepage
path: root/pyecsca/codegen
diff options
context:
space:
mode:
authorJ08nY2020-02-20 20:41:29 +0100
committerJ08nY2020-02-20 20:41:29 +0100
commit3892d994470b181f950703fabf719a9c963d1c20 (patch)
treefc1c7e68fc6334a7f89fd69eab00a830fb58f275 /pyecsca/codegen
parent92cb16e8103da998aa1bf226d24ef6771a92c5d5 (diff)
downloadpyecsca-codegen-3892d994470b181f950703fabf719a9c963d1c20.tar.gz
pyecsca-codegen-3892d994470b181f950703fabf719a9c963d1c20.tar.zst
pyecsca-codegen-3892d994470b181f950703fabf719a9c963d1c20.zip
Add full implementation tests.
Diffstat (limited to 'pyecsca/codegen')
-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
6 files changed, 48 insertions, 36 deletions
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);