diff options
Diffstat (limited to 'pyecsca/codegen')
| -rw-r--r-- | pyecsca/codegen/__init__.py | 67 | ||||
| -rw-r--r-- | pyecsca/codegen/templates/curve.c | 2 | ||||
| -rw-r--r-- | pyecsca/codegen/templates/curve.h | 1 | ||||
| -rw-r--r-- | pyecsca/codegen/templates/ops.c | 15 |
4 files changed, 82 insertions, 3 deletions
diff --git a/pyecsca/codegen/__init__.py b/pyecsca/codegen/__init__.py index 894c843..7848a60 100644 --- a/pyecsca/codegen/__init__.py +++ b/pyecsca/codegen/__init__.py @@ -1,25 +1,80 @@ +from ast import operator, Add, Sub, Mult, Div, Pow +from typing import List + from jinja2 import Environment, PackageLoader -from pyecsca.ec.model import CurveModel, ShortWeierstrassModel from pyecsca.ec.coordinates import CoordinateModel +from pyecsca.ec.model import CurveModel, ShortWeierstrassModel, MontgomeryModel +from pyecsca.ec.op import CodeOp env = Environment( loader=PackageLoader("pyecsca.codegen") ) +def render_op(op: operator, result: str, left: str, right: str, mod: str): + if isinstance(op, Add): + return "bn_mod_add(&{}, &{}, &{}, &{});".format(left, right, mod, result) + elif isinstance(op, Sub): + return "bn_mod_sub(&{}, &{}, &{}, &{});".format(left, right, mod, result) + elif isinstance(op, Mult): + return "bn_mod_mul(&{}, &{}, &{}, &{});".format(left, right, mod, result) + elif isinstance(op, Div): + return "bn_mod_div(&{}, &{}, &{}, &{});".format(left, right, mod, result) + elif isinstance(op, Pow) and right == 2: + return "bn_mod_sqr(&{}, &{}, &{});".format(left, mod, result) + +env.globals["render_op"] = render_op + def get_curve_definition(model: CurveModel): return env.get_template("curve.h").render(params=model.parameter_names) + def get_curve_impl(model: CurveModel): return env.get_template("curve.c").render(params=model.parameter_names) + def get_coords_definition(coords: CoordinateModel): return env.get_template("coords.h").render(variables=coords.variables) + +def transform_ops(ops: List[CodeOp], parameters: List[str], outputs: List[str]): + allocations = [] + initializations = {} + const_mapping = {} + operations = [] + frees = [] + for op in ops: + if op.result not in allocations and op.result not in outputs: + allocations.append(op.result) + frees.append(op.result) + for param in op.parameters: + if param not in allocations and param not in parameters: + raise ValueError("Should be allocated or parameter: {}".format(param)) + for const in op.constants: + name = "c" + str(const) + if name not in allocations: + allocations.append(name) + initializations[name] = const + const_mapping[const] = name + frees.append(name) + operations.append((op.operator, op.result, op.left, op.right)) + return env.get_template("ops.c").render(allocations=allocations, + initializations=initializations, + const_mapping=const_mapping, operations=operations, + frees=frees) + + def get_coords_impl(coords: CoordinateModel): - print(coords.satisfying) + ops = [] + for s in coords.satisfying: + try: + ops.append(CodeOp(s)) + except: + pass + transform_ops(ops, coords.curve_model.parameter_names, coords.curve_model.coordinate_names) return env.get_template("coords.c").render(variables=coords.variables) + if __name__ == "__main__": model = ShortWeierstrassModel() s = get_curve_definition(model) @@ -30,4 +85,10 @@ if __name__ == "__main__": s = get_coords_definition(coords) - s = get_coords_impl(coords)
\ No newline at end of file + s = get_coords_impl(coords) + + mont = MontgomeryModel() + mcoords = mont.coordinates["xz"] + dbl = mcoords.formulas["dbl-1987-m"] + t = transform_ops(dbl.code, mont.parameter_names, dbl.outputs) + print(t) diff --git a/pyecsca/codegen/templates/curve.c b/pyecsca/codegen/templates/curve.c index a49adde..675f748 100644 --- a/pyecsca/codegen/templates/curve.c +++ b/pyecsca/codegen/templates/curve.c @@ -1,5 +1,6 @@ curve_t* curve_new(const named_bn_t **params, int num_params) { curve_t *result = malloc(sizeof(curve_t)); + bn_init(&result->p); {%- for param in params %} bn_init(&result->{{ param }}); {%- endfor %} @@ -20,6 +21,7 @@ curve_t* curve_new(const named_bn_t **params, int num_params) { } void curve_free(curve_t *curve) { + bn_clear(&curve->p); {%- for param in params %} bn_clear(&curve->{{ param }}); {%- endfor %} diff --git a/pyecsca/codegen/templates/curve.h b/pyecsca/codegen/templates/curve.h index ff4a078..42445a4 100644 --- a/pyecsca/codegen/templates/curve.h +++ b/pyecsca/codegen/templates/curve.h @@ -1,4 +1,5 @@ typedef struct { + bn_t p; {%- for param in params %} bn_t {{ param }}; {%- endfor %} diff --git a/pyecsca/codegen/templates/ops.c b/pyecsca/codegen/templates/ops.c new file mode 100644 index 0000000..96aa6ee --- /dev/null +++ b/pyecsca/codegen/templates/ops.c @@ -0,0 +1,15 @@ +{%- for alloc in allocations %} + bn_t {{ alloc }}; bn_init(&{{ alloc }}); +{%- endfor %} + +{%- for init, value in initializations.items() %} + bn_from_int({{ value }}, &{{ init }}); +{%- endfor %} + +{%- for op, result, left, right in operations %} + {{ render_op(op, result, left, right, "curve->p")}} +{%- endfor %} + +{%- for free in frees %} + bn_clear(&{{ free }}); +{%- endfor %}
\ No newline at end of file |
