1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
from ast import operator, Add, Sub, Mult, Div, Pow
from typing import List, Set, Mapping
from jinja2 import Environment, PackageLoader
from pyecsca.ec.coordinates import CoordinateModel
from pyecsca.ec.formula import (Formula, AdditionFormula, DoublingFormula, TriplingFormula,
NegationFormula, ScalingFormula, DifferentialAdditionFormula,
LadderFormula)
from pyecsca.ec.model import CurveModel, ShortWeierstrassModel
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 render_curve_definition(model: CurveModel):
return env.get_template("curve.h").render(params=model.parameter_names)
def render_curve_impl(model: CurveModel):
return env.get_template("curve.c").render(params=model.parameter_names)
def render_coords_definition(coords: CoordinateModel):
return env.get_template("coords.h").render(variables=coords.variables)
def transform_ops(ops: List[CodeOp], parameters: List[str], outputs: Set[str],
renames: Mapping[str, str] = None):
def rename(name: str):
if renames is not None and name not in outputs:
return renames.get(name, name)
return name
allocations = []
initializations = {}
const_mapping = {}
operations = []
frees = []
for op in ops:
if op.result not in allocations:
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, rename(op.left), rename(op.right)))
returns = {}
if renames:
for r_from, r_to in renames.items():
if r_from in outputs:
returns[r_from] = r_to
return dict(allocations=allocations,
initializations=initializations,
const_mapping=const_mapping, operations=operations,
frees=frees, returns=returns)
def render_ops(ops: List[CodeOp], parameters: List[str], outputs: Set[str],
renames: Mapping[str, str] = None):
namespace = transform_ops(ops, parameters, outputs, renames)
return env.get_template("ops.c").render(namespace)
def render_coords_impl(coords: CoordinateModel):
ops = []
for s in coords.satisfying:
try:
ops.append(CodeOp(s))
except:
pass
renames = {"x": "out_x", "y": "out_y"}
for variable in coords.variables:
renames[variable] = "point->{}".format(variable)
namespace = transform_ops(ops, coords.curve_model.parameter_names,
coords.curve_model.coordinate_names, renames)
returns = namespace["returns"]
namespace["returns"] = {}
frees = namespace["frees"]
namespace["frees"] = {}
return env.get_template("coords.c").render(variables=coords.variables, **namespace,
to_affine_rets=returns, to_affine_frees=frees)
def render_formula_impl(formula: Formula):
if isinstance(formula, AdditionFormula):
tname = "formula_add.c"
elif isinstance(formula, DoublingFormula):
tname = "formula_dbl.c"
elif isinstance(formula, TriplingFormula):
tname = "formula_tpl.c"
elif isinstance(formula, NegationFormula):
tname = "formula_neg.c"
elif isinstance(formula, ScalingFormula):
tname = "formula_scl.c"
elif isinstance(formula, DifferentialAdditionFormula):
tname = "formula_dadd.c"
elif isinstance(formula, LadderFormula):
tname = "formula_ladd.c"
else:
raise ValueError
template = env.get_template(tname)
inputs = ["one", "other", "diff"]
outputs = ["out_one", "out_other"]
renames = {}
for input in formula.inputs:
var = input[0]
num = int(input[1:]) - formula.input_index
renames[input] = "{}->{}".format(inputs[num], var)
for output in formula.outputs:
var = output[0]
num = int(output[1:]) - formula.output_index
renames[output] = "{}->{}".format(outputs[num], var)
namespace = transform_ops(formula.code, formula.coordinate_model.curve_model.parameter_names,
formula.outputs, renames)
return template.render(namespace)
def render_main(model: CurveModel, coords: CoordinateModel):
return env.get_template("main.c").render(curve_variables=coords.variables,
curve_parameters=model.parameter_names)
if __name__ == "__main__":
model = ShortWeierstrassModel()
coords = model.coordinates["projective"]
print(render_coords_impl(coords))
|