diff options
Diffstat (limited to 'pyecsca/codegen/__init__.py')
| -rw-r--r-- | pyecsca/codegen/__init__.py | 103 |
1 files changed, 93 insertions, 10 deletions
diff --git a/pyecsca/codegen/__init__.py b/pyecsca/codegen/__init__.py index 104b43f..06c85c2 100644 --- a/pyecsca/codegen/__init__.py +++ b/pyecsca/codegen/__init__.py @@ -1,7 +1,12 @@ +import os +import tempfile from ast import operator, Add, Sub, Mult, Div, Pow +from enum import Enum +from os import path from typing import List, Set, Mapping from jinja2 import Environment, PackageLoader +from pkg_resources import resource_filename from pyecsca.ec.coordinates import CoordinateModel from pyecsca.ec.formula import (Formula, AdditionFormula, DoublingFormula, TriplingFormula, NegationFormula, ScalingFormula, DifferentialAdditionFormula, @@ -25,21 +30,53 @@ def render_op(op: operator, result: str, left: str, right: str, mod: str): return "bn_mod_div(&{}, &{}, &{}, &{});".format(left, right, mod, result) elif isinstance(op, Pow) and right == 2: return "bn_mod_sqr(&{}, &{}, &{});".format(left, mod, result) + elif isinstance(op, Pow): + return "bn_mod_pow(&{}, &{}, &{}, &{});".format(left, right, mod, result) + else: + print(op, result, left, right, mod) env.globals["render_op"] = render_op -def render_curve_definition(model: CurveModel): - return env.get_template("curve.h").render(params=model.parameter_names) +class EnumDefine(Enum): + def __str__(self): + return self.value -def render_curve_impl(model: CurveModel): - return env.get_template("curve.c").render(params=model.parameter_names) +class Platform(EnumDefine): + HOST = "HOST" + XMEGA = "CW308_XMEGA" + STM32F0 = "CW308_STM32F0" + STM32F3 = "CW308_STM32F3" + + +class HashType(EnumDefine): + NONE = "HASH_NONE" + SHA1 = "HASH_SHA1" + SHA224 = "HASH_SHA224" + SHA256 = "HASH_SHA256" + SHA384 = "HASH_SHA384" + SHA512 = "HASH_SHA512" -def render_coords_definition(coords: CoordinateModel): - return env.get_template("coords.h").render(variables=coords.variables) +class MultAlgo(EnumDefine): + NONE = "MULT_NONE" + DOUBLE_AND_ADD = "MULT_DOUBLE_AND_ADD" + + +class RandomMod(EnumDefine): + SAMPLE = "MOD_RAND_SAMPLE" + REDUCE = "MOD_RAND_REDUCE" + + +def render_defs(model: CurveModel, coords: CoordinateModel): + return env.get_template("defs.h").render(params=model.parameter_names, + variables=coords.variables) + + +def render_curve_impl(model: CurveModel): + return env.get_template("curve.c").render(params=model.parameter_names) def transform_ops(ops: List[CodeOp], parameters: List[str], outputs: Set[str], @@ -69,6 +106,15 @@ def transform_ops(ops: List[CodeOp], parameters: List[str], outputs: Set[str], const_mapping[const] = name frees.append(name) operations.append((op.operator, op.result, rename(op.left), rename(op.right))) + mapped = [] + for op in operations: + o2 = op[2] + if o2 in const_mapping: + o2 = const_mapping[o2] + o3 = op[3] + if o3 in const_mapping and not (isinstance(op[0], Pow) and o3 == 2): + o3 = const_mapping[o3] + mapped.append((op[0], op[1], o2, o3)) returns = {} if renames: for r_from, r_to in renames.items(): @@ -77,7 +123,7 @@ def transform_ops(ops: List[CodeOp], parameters: List[str], outputs: Set[str], return dict(allocations=allocations, initializations=initializations, - const_mapping=const_mapping, operations=operations, + const_mapping=const_mapping, operations=mapped, frees=frees, returns=returns) @@ -97,6 +143,8 @@ def render_coords_impl(coords: CoordinateModel): renames = {"x": "out_x", "y": "out_y"} for variable in coords.variables: renames[variable] = "point->{}".format(variable) + for param in coords.curve_model.parameter_names: + renames[param] = "curve->{}".format(param) namespace = transform_ops(ops, coords.curve_model.parameter_names, coords.curve_model.coordinate_names, renames) returns = namespace["returns"] @@ -104,8 +152,8 @@ def render_coords_impl(coords: CoordinateModel): frees = namespace["frees"] namespace["frees"] = {} - return env.get_template("coords.c").render(variables=coords.variables, **namespace, - to_affine_rets=returns, to_affine_frees=frees) + return env.get_template("point.c").render(variables=coords.variables, **namespace, + to_affine_rets=returns, to_affine_frees=frees) def render_formula_impl(formula: Formula): @@ -133,6 +181,8 @@ def render_formula_impl(formula: Formula): var = input[0] num = int(input[1:]) - formula.input_index renames[input] = "{}->{}".format(inputs[num], var) + for param in formula.coordinate_model.curve_model.parameter_names: + renames[param] = "curve->{}".format(param) for output in formula.outputs: var = output[0] num = int(output[1:]) - formula.output_index @@ -147,7 +197,40 @@ def render_main(model: CurveModel, coords: CoordinateModel): curve_parameters=model.parameter_names) +def render_makefile(platform: Platform, hash_type: HashType, mult_algo: MultAlgo, + mod_rand: RandomMod): + return env.get_template("Makefile").render(platform=str(platform), hash_type=str(hash_type), + mult_algo=str(mult_algo), mod_rand=str(mod_rand)) + + +def save_render(dir: str, fname: str, render: str): + with open(path.join(dir, fname), "w") as f: + f.write(render) + + +def build(platform: Platform, hash_type: HashType, mult_algo: MultAlgo, mod_rand: RandomMod, + model: CurveModel, coords: CoordinateModel, *formulas: Formula): + temp = tempfile.mkdtemp() + symlinks = ["asn1", "bn", "hal", "hash", "mult", "prng", "simpleserial", "tommath", "fat.h", + "point.h", "curve.h", "Makefile.inc"] + for sym in symlinks: + os.symlink(resource_filename("pyecsca.codegen", sym), path.join(temp, sym)) + gen_dir = path.join(temp, "gen") + os.mkdir(gen_dir) + save_render(temp, "Makefile", render_makefile(platform, hash_type, mult_algo, mod_rand)) + save_render(temp, "main.c", render_main(model, coords)) + save_render(gen_dir, "defs.h", render_defs(model, coords)) + point_render = render_coords_impl(coords) + for formula in formulas: + point_render += "\n" + point_render += render_formula_impl(formula) + save_render(gen_dir, "point.c", point_render) + save_render(gen_dir, "curve.c", render_curve_impl(model)) + print(temp) + + if __name__ == "__main__": model = ShortWeierstrassModel() coords = model.coordinates["projective"] - print(render_coords_impl(coords)) + build(Platform.HOST, HashType.SHA1, MultAlgo.DOUBLE_AND_ADD, RandomMod.SAMPLE, model, coords, + coords.formulas["add-1998-cmo"], coords.formulas["dbl-1998-cmo"]) |
