diff options
| author | J08nY | 2019-11-27 20:34:58 +0100 |
|---|---|---|
| committer | J08nY | 2019-11-27 20:34:58 +0100 |
| commit | 32a4874abfbaff8cb4ee2d31fe71bcc3499e52dc (patch) | |
| tree | 1203a322d7488ef51b4de2d34c6e0c2871ea68a5 | |
| parent | bb00fee9702155586e674b9d6a3b838bd54baac2 (diff) | |
| download | pyecsca-codegen-32a4874abfbaff8cb4ee2d31fe71bcc3499e52dc.tar.gz pyecsca-codegen-32a4874abfbaff8cb4ee2d31fe71bcc3499e52dc.tar.zst pyecsca-codegen-32a4874abfbaff8cb4ee2d31fe71bcc3499e52dc.zip | |
Reorganize files, implement proper main.
28 files changed, 685 insertions, 308 deletions
diff --git a/pyecsca/codegen/Makefile b/pyecsca/codegen/Makefile index 13122d0..d0dab03 100644 --- a/pyecsca/codegen/Makefile +++ b/pyecsca/codegen/Makefile @@ -1,12 +1,12 @@ TARGET = pyecsca-codegen -SRC += main.c bn.c ecdh.c ecdsa.c asn1.c hash/hash.c mult/mult.c prng/prng.c +SRC += main.c bn/bn.c asn1/asn1.c hash/hash.c mult/mult.c prng/prng.c -CDEFS += -DHASH=HASH_SHA224 +CDEFS += -DHASH=HASH_SHA224 -DMOD_RAND=MOD_RAND_SAMPLE -MKDIR_LIST += hash prng mult +MKDIR_LIST += hash prng mult asn1 bn -EXTRAINCDIRS += hash prng mult ../../ext/libtommath/ +EXTRAINCDIRS += hash prng mult asn1 bn ../../ext/libtommath/ LDFLAGS += ../../ext/libtommath/libtommath.a diff --git a/pyecsca/codegen/__init__.py b/pyecsca/codegen/__init__.py index 33320ac..104b43f 100644 --- a/pyecsca/codegen/__init__.py +++ b/pyecsca/codegen/__init__.py @@ -6,7 +6,7 @@ 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, MontgomeryModel +from pyecsca.ec.model import CurveModel, ShortWeierstrassModel from pyecsca.ec.op import CodeOp env = Environment( @@ -45,7 +45,7 @@ def render_coords_definition(coords: CoordinateModel): 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: + if renames is not None and name not in outputs: return renames.get(name, name) return name @@ -55,7 +55,7 @@ def transform_ops(ops: List[CodeOp], parameters: List[str], outputs: Set[str], operations = [] frees = [] for op in ops: - if op.result not in allocations and op.result not in outputs: + if op.result not in allocations: allocations.append(op.result) frees.append(op.result) for param in op.parameters: @@ -69,11 +69,16 @@ 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))) + 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) + frees=frees, returns=returns) def render_ops(ops: List[CodeOp], parameters: List[str], outputs: Set[str], @@ -89,9 +94,18 @@ def render_coords_impl(coords: CoordinateModel): ops.append(CodeOp(s)) except: pass - transform_ops(ops, coords.curve_model.parameter_names, coords.curve_model.coordinate_names) - # TODO: do point_from_affine, and point_to_affine - return env.get_template("coords.c").render(variables=coords.variables) + 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): @@ -123,13 +137,17 @@ def render_formula_impl(formula: Formula): 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) + 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__": - mont = MontgomeryModel() - mcoords = mont.coordinates["xz"] - dbl = mcoords.formulas["dbl-1987-m"] - t = transform_ops(dbl.code, mont.parameter_names, dbl.outputs) - print(render_formula_impl(dbl)) + model = ShortWeierstrassModel() + coords = model.coordinates["projective"] + print(render_coords_impl(coords)) diff --git a/pyecsca/codegen/asn1.c b/pyecsca/codegen/asn1/asn1.c index 3fd1f5f..3fd1f5f 100644 --- a/pyecsca/codegen/asn1.c +++ b/pyecsca/codegen/asn1/asn1.c diff --git a/pyecsca/codegen/asn1.h b/pyecsca/codegen/asn1/asn1.h index 691755c..691755c 100644 --- a/pyecsca/codegen/asn1.h +++ b/pyecsca/codegen/asn1/asn1.h diff --git a/pyecsca/codegen/bn.c b/pyecsca/codegen/bn.c deleted file mode 100644 index aa33124..0000000 --- a/pyecsca/codegen/bn.c +++ /dev/null @@ -1,81 +0,0 @@ -#include "bn.h" - -bn_err bn_init(bn_t *bn) { - return mp_init(bn); -} - -void bn_copy(bn_t *from, bn_t *to) { - mp_copy(from, to); -} - -void bn_clear(bn_t *bn) { - mp_clear(bn); -} - -int bn_from_bin(const uint8_t *data, size_t size, bn_t *out) { - return mp_from_ubin(out, data, size); -} - -int bn_from_hex(const char *data, bn_t *out) { - return mp_read_radix(out, data, 16); -} - -int bn_from_int(uint64_t value, bn_t *out) { - mp_set_u64(out, value); - return MP_OKAY; -} - -void bn_to_binpad(const bn_t *one, uint8_t *data, size_t size) { - size_t ubin_size = mp_ubin_size(one); - size_t offset = size - ubin_size; - mp_to_ubin(one, data + offset, ubin_size, NULL); -} - -void bn_to_bin(const bn_t *one, uint8_t *data) { - mp_to_ubin(one, data, mp_ubin_size(one), NULL); -} - -size_t bn_to_bin_size(const bn_t *one) { - return mp_ubin_size(one); -} - -void bn_mod_add(bn_t *one, bn_t *other, bn_t *mod, bn_t *out) { - mp_addmod(one, other, mod, out); -} - -void bn_mod_sub(bn_t *one, bn_t *other, bn_t *mod, bn_t *out) { - mp_submod(one, other, mod, out); -} - -void bn_mod_mul(bn_t *one, bn_t *other, bn_t *mod, bn_t *out) { - mp_mulmod(one, other, mod, out); -} - -void bn_mod_sqr(bn_t *one, bn_t *mod, bn_t *out) { - mp_sqrmod(one, mod, out); -} - -void bn_mod_div(bn_t *one, bn_t *other, bn_t *mod, bn_t *out) { - bn_t inv; - mp_init(&inv); - mp_invmod(other, mod, &inv); - mp_mulmod(one, &inv, mod, out); - mp_clear(&inv); -} - -void bn_mod_inv(bn_t *one, bn_t *mod, bn_t *out) { - mp_invmod(one, mod, out); -} - -int bn_get_bit(bn_t *bn, int which) { - int which_digit = which / (sizeof(mp_digit) * 8); - int which_bit = which % (sizeof(mp_digit) * 8); - if (bn->used <= which_digit) { - return 0; - } - return (bn->dp[which_digit] >> which_bit) & 1; -} - -int bn_bit_length(bn_t *bn) { - return mp_count_bits(bn); -}
\ No newline at end of file diff --git a/pyecsca/codegen/bn.h b/pyecsca/codegen/bn.h deleted file mode 100644 index 0690310..0000000 --- a/pyecsca/codegen/bn.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef BN_H_ -#define BN_H_ - -#include <tommath.h> - -#define bn_t mp_int -#define bn_err mp_err - -typedef struct { - char name; - bn_t value; -} named_bn_t; - -bn_err bn_init(bn_t *bn); -void bn_copy(bn_t *from, bn_t *to); -void bn_clear(bn_t *bn); - -int bn_from_bin(const uint8_t *data, size_t size, bn_t *out); -int bn_from_hex(const char *data, bn_t *out); -int bn_from_int(uint64_t value, bn_t *out); - -void bn_to_binpad(const bn_t *one, uint8_t *data, size_t size); -void bn_to_bin(const bn_t *one, uint8_t *data); -size_t bn_to_bin_size(const bn_t *one); - -void bn_mod_add(bn_t *one, bn_t *other, bn_t *mod, bn_t *out); -void bn_mod_sub(bn_t *one, bn_t *other, bn_t *mod, bn_t *out); -void bn_mod_mul(bn_t *one, bn_t *other, bn_t *mod, bn_t *out); -void bn_mod_sqr(bn_t *one, bn_t *mod, bn_t *out); -void bn_mod_div(bn_t *one, bn_t *other, bn_t *mod, bn_t *out); -void bn_mod_inv(bn_t *one, bn_t *mod, bn_t *out); -int bn_get_bit(bn_t *bn, int which); -int bn_bit_length(bn_t *bn); - -#endif //BN_H_
\ No newline at end of file diff --git a/pyecsca/codegen/bn/bn.c b/pyecsca/codegen/bn/bn.c new file mode 100644 index 0000000..9b805d1 --- /dev/null +++ b/pyecsca/codegen/bn/bn.c @@ -0,0 +1,119 @@ +#include "bn.h" + +bn_err bn_init(bn_t *bn) { + return mp_init(bn); +} + +void bn_copy(const bn_t *from, bn_t *to) { + mp_copy(from, to); +} + +void bn_clear(bn_t *bn) { + mp_clear(bn); +} + +int bn_from_bin(const uint8_t *data, size_t size, bn_t *out) { + return mp_from_ubin(out, data, size); +} + +int bn_from_hex(const char *data, bn_t *out) { + return mp_read_radix(out, data, 16); +} + +int bn_from_int(uint64_t value, bn_t *out) { + mp_set_u64(out, value); + return MP_OKAY; +} + +void bn_to_binpad(const bn_t *one, uint8_t *data, size_t size) { + size_t ubin_size = mp_ubin_size(one); + size_t offset = size - ubin_size; + mp_to_ubin(one, data + offset, ubin_size, NULL); +} + +void bn_to_bin(const bn_t *one, uint8_t *data) { + mp_to_ubin(one, data, mp_ubin_size(one), NULL); +} + +size_t bn_to_bin_size(const bn_t *one) { + return mp_ubin_size(one); +} + +void bn_rand_mod_sample(bn_t *out, const bn_t *mod) { + int mod_len = bn_bit_length(mod); + + bn_t mask; bn_init(&mask); + mp_2expt(&mask, mod_len + 1); + mp_decr(&mask); + while (1) { + mp_rand(out, (mod_len / (sizeof(mp_digit) * 8)) + 1); + mp_and(out, &mask, out); + if (mp_cmp_mag(out, mod) == MP_LT) { + bn_clear(&mask); + break; + } + } +} + +void bn_rand_mod_reduce(bn_t *out, const bn_t *mod) { + int mod_len = bn_bit_length(mod); + mp_rand(out, (mod_len / (sizeof(mp_digit) * 8)) + 2); + mp_mod(out, mod, out); +} + +void bn_mod_add(const bn_t *one, const bn_t *other, const bn_t *mod, bn_t *out) { + mp_addmod(one, other, mod, out); +} + +void bn_mod_sub(const bn_t *one, const bn_t *other, const bn_t *mod, bn_t *out) { + mp_submod(one, other, mod, out); +} + +void bn_mod_mul(const bn_t *one, const bn_t *other, const bn_t *mod, bn_t *out) { + mp_mulmod(one, other, mod, out); +} + +void bn_mod_sqr(const bn_t *one, const bn_t *mod, bn_t *out) { + mp_sqrmod(one, mod, out); +} + +void bn_mod_div(const bn_t *one, const bn_t *other, const bn_t *mod, bn_t *out) { + bn_t inv; + mp_init(&inv); + mp_invmod(other, mod, &inv); + mp_mulmod(one, &inv, mod, out); + mp_clear(&inv); +} + +void bn_mod_inv(const bn_t *one, const bn_t *mod, bn_t *out) { + mp_invmod(one, mod, out); +} + +void bn_mod(const bn_t *one, const bn_t *mod, bn_t *out) { + mp_mod(one, mod, out); +} + +void bn_lsh(const bn_t *one, int amount, bn_t *out) { + mp_mul_2d(one, amount, out); +} + +void bn_rsh(const bn_t *one, int amount, bn_t *out) { + mp_div_2d(one, amount, out, NULL); +} + +bool bn_eq(const bn_t *one, const bn_t *other) { + return mp_cmp_mag(one, other) == MP_EQ; +} + +int bn_get_bit(const bn_t *bn, int which) { + int which_digit = which / (sizeof(mp_digit) * 8); + int which_bit = which % (sizeof(mp_digit) * 8); + if (bn->used <= which_digit) { + return 0; + } + return (bn->dp[which_digit] >> which_bit) & 1; +} + +int bn_bit_length(const bn_t *bn) { + return mp_count_bits(bn); +}
\ No newline at end of file diff --git a/pyecsca/codegen/bn/bn.h b/pyecsca/codegen/bn/bn.h new file mode 100644 index 0000000..2ff723f --- /dev/null +++ b/pyecsca/codegen/bn/bn.h @@ -0,0 +1,51 @@ +#ifndef BN_H_ +#define BN_H_ + +#include <tommath.h> + +#define bn_t mp_int +#define bn_err mp_err + +typedef struct { + char name; + bn_t value; +} named_bn_t; + +bn_err bn_init(bn_t *bn); +void bn_copy(const bn_t *from, bn_t *to); +void bn_clear(bn_t *bn); + +int bn_from_bin(const uint8_t *data, size_t size, bn_t *out); +int bn_from_hex(const char *data, bn_t *out); +int bn_from_int(uint64_t value, bn_t *out); + +void bn_to_binpad(const bn_t *one, uint8_t *data, size_t size); +void bn_to_bin(const bn_t *one, uint8_t *data); +size_t bn_to_bin_size(const bn_t *one); + +void bn_rand_mod_sample(bn_t *out, const bn_t *mod); +void bn_rand_mod_reduce(bn_t *out, const bn_t *mod); + +#if MOD_RAND == MOD_RAND_SAMPLE +#define bn_rand_mod bn_rand_mod_sample +#elif MOD_RAND == MOD_RAND_REDUCE +#define bn_rand_mod bn_rand_mod_reduce +#endif + +void bn_mod_add(const bn_t *one, const bn_t *other, const bn_t *mod, bn_t *out); +void bn_mod_sub(const bn_t *one, const bn_t *other, const bn_t *mod, bn_t *out); +void bn_mod_mul(const bn_t *one, const bn_t *other, const bn_t *mod, bn_t *out); +void bn_mod_sqr(const bn_t *one, const bn_t *mod, bn_t *out); +void bn_mod_div(const bn_t *one, const bn_t *other, const bn_t *mod, bn_t *out); +void bn_mod_inv(const bn_t *one, const bn_t *mod, bn_t *out); +void bn_mod(const bn_t *one, const bn_t *mod, bn_t *out); + +void bn_lsh(const bn_t *one, int amount, bn_t *out); +void bn_rsh(const bn_t *one, int amount, bn_t *out); + +bool bn_eq(const bn_t *one, const bn_t *other); + +int bn_get_bit(const bn_t *bn, int which); +int bn_bit_length(const bn_t *bn); + +#endif //BN_H_
\ No newline at end of file diff --git a/pyecsca/codegen/coords.h b/pyecsca/codegen/coords.h deleted file mode 100644 index 6a1af7e..0000000 --- a/pyecsca/codegen/coords.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef COORDS_H_ -#define COORDS_H_ - -#include "bn.h" -#include "defs.h" - -point_t *point_new(void); - -point_t *point_copy(const point_t *from); - -void point_set(const point_t *from, point_t *out); - -void point_free(point_t *point); - -int point_to_affine(point_t *point, const char coord, curve_t *curve, bn_t *out); - -int point_from_affine(bn_t *x, bn_t *y, curve_t *curve, point_t *out); - -#endif //COORDS_H_
\ No newline at end of file diff --git a/pyecsca/codegen/curve.h b/pyecsca/codegen/curve.h deleted file mode 100644 index ab962e7..0000000 --- a/pyecsca/codegen/curve.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef CURVE_H_ -#define CURVE_H_ - -#include "defs.h" - -curve_t* curve_new(const named_bn_t **params, int num_params); - -void curve_free(curve_t *curve); - -#endif //CURVE_H_
\ No newline at end of file diff --git a/pyecsca/codegen/defs.h b/pyecsca/codegen/defs.h deleted file mode 100644 index df81226..0000000 --- a/pyecsca/codegen/defs.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef DEFS_H_ -#define DEFS_H_ -#include "bn.h" - -//point_t definition is variable -typedef struct { - bn_t X; - bn_t Y; - bn_t Z; -} point_t; - -//curve_t definition is variable -typedef struct { - bn_t n; - point_t *neutral; -} curve_t; - -#endif //DEFS_H_
\ No newline at end of file diff --git a/pyecsca/codegen/ecdh.c b/pyecsca/codegen/ecdh.c deleted file mode 100644 index e69de29..0000000 --- a/pyecsca/codegen/ecdh.c +++ /dev/null diff --git a/pyecsca/codegen/ecdsa.c b/pyecsca/codegen/ecdsa.c deleted file mode 100644 index e69de29..0000000 --- a/pyecsca/codegen/ecdsa.c +++ /dev/null diff --git a/pyecsca/codegen/fat.h b/pyecsca/codegen/fat.h new file mode 100644 index 0000000..e9fe3bd --- /dev/null +++ b/pyecsca/codegen/fat.h @@ -0,0 +1,6 @@ +typedef struct { + size_t len; + void *value; +} fat_t; + +#define fat_empty {0, NULL}
\ No newline at end of file diff --git a/pyecsca/codegen/formulas.h b/pyecsca/codegen/formulas.h deleted file mode 100644 index a2278bb..0000000 --- a/pyecsca/codegen/formulas.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef FORMULAS_H_ -#define FORMULAS_H_ - -#include "coords.h" -#include "defs.h" - -int point_add(const point_t *one, const point_t *other, const curve_t *curve, point_t *out_one); - -int point_dbl(const point_t *one, const curve_t *curve, point_t *out_one); - -int point_tpl(const point_t *one, const curve_t *curve, point_t *out_one); - -int point_neg(const point_t *one, const curve_t *curve, point_t *out_one); - -int point_scl(const point_t *one, const curve_t *curve, point_t *out_one); - -int point_dadd(const point_t *one, const point_t *other, const point_t *diff, const curve_t *curve, point_t *out_one); - -int point_ladd(const point_t *one, const point_t *other, const point_t *diff, const curve_t *curve, point_t *out_one, point_t *out_other); - -#endif //FORMULAS_H_
\ No newline at end of file diff --git a/pyecsca/codegen/hash/hash.h b/pyecsca/codegen/hash/hash.h index 9e79b61..7121cd4 100644 --- a/pyecsca/codegen/hash/hash.h +++ b/pyecsca/codegen/hash/hash.h @@ -18,4 +18,6 @@ void hash_init(void *ctx); void hash_final(void *ctx, int size, const uint8_t *msg, uint8_t *digest); +void hash_free_ctx(void *ctx); + #endif //HASH_H_
\ No newline at end of file diff --git a/pyecsca/codegen/hash/none.c b/pyecsca/codegen/hash/none.c index 79690e8..b40adc3 100644 --- a/pyecsca/codegen/hash/none.c +++ b/pyecsca/codegen/hash/none.c @@ -17,4 +17,8 @@ void hash_init(void *ctx) { void hash_final(void *ctx, int size, const uint8_t *msg, uint8_t *digest) { memcpy(digest, msg, size); +} + +void hash_free_ctx(void *ctx) { + }
\ No newline at end of file diff --git a/pyecsca/codegen/hash/sha1.c b/pyecsca/codegen/hash/sha1.c index cf6ca3e..213ed11 100644 --- a/pyecsca/codegen/hash/sha1.c +++ b/pyecsca/codegen/hash/sha1.c @@ -187,3 +187,7 @@ void hash_final(void *ctx, int size, const uint8_t *msg, uint8_t *digest) { sha1_lastBlock(ctx, msg, length); sha1_ctx2hash(digest, ctx); } + +void hash_free_ctx(void *ctx) { + free(ctx); +} diff --git a/pyecsca/codegen/hash/sha2.c b/pyecsca/codegen/hash/sha2.c index d2ddf6f..2b7f11d 100644 --- a/pyecsca/codegen/hash/sha2.c +++ b/pyecsca/codegen/hash/sha2.c @@ -334,4 +334,8 @@ void hash_final(void* ctx, int size, const uint8_t* msg, uint8_t* digest) { } sha2_lastBlock(ctx, msg, length_b); sha2_ctx2hash(digest, ctx); +} + +void hash_free_ctx(void *ctx) { + free(ctx); }
\ No newline at end of file diff --git a/pyecsca/codegen/main.c b/pyecsca/codegen/main.c deleted file mode 100644 index a1d43da..0000000 --- a/pyecsca/codegen/main.c +++ /dev/null @@ -1,79 +0,0 @@ -#include <stdint.h> -#include <stdlib.h> - -#include "hal/hal.h" -#include "simpleserial/simpleserial.h" -#include "hash/hash.h" -#include "bn.h" -#include "prng.h" -#include "defs.h" -#include <stdlib.h> - -static point_t *pubkey; -static bn_t privkey; - -static curve_t *curve; - -static uint8_t cmd_init_prng(uint8_t *data, uint16_t len) { - prng_seed(data, len); - return 0; -} - -static uint8_t cmd_set_curve(uint8_t *data, uint16_t len) { - // need p, [params], gx, gy, n - return 0; -} - -static uint8_t cmd_generate(uint8_t *data, uint16_t len) { - // generate a keypair, export privkey and affine pubkey - return 0; -} - -static uint8_t cmd_set_privkey(uint8_t *data, uint16_t len) { - // set the current privkey - return 0; -} - -static uint8_t cmd_set_pubkey(uint8_t *data, uint16_t len) { - // set the current pubkey - return 0; -} - -static uint8_t cmd_scalar_mult(uint8_t *data, uint16_t len) { - // perform base point scalar mult with supplied scalar, return affine point. - return 0; -} - -static uint8_t cmd_ecdh(uint8_t *data, uint16_t len) { - //perform ECDH with provided point (and current privkey), output shared secret - return 0; -} - -static uint8_t cmd_ecdsa_sign(uint8_t *data, uint16_t len) { - //perform ECDSA signature on supplied data, output signature - return 0; -} - -static uint8_t cmd_ecdsa_verify(uint8_t *data, uint16_t len) { - //perform ECDSA verification on supplied data (and current pubkey), output status - return 0; -} - -int main(void) { - platform_init(); - prng_init(); - init_uart(); - trigger_setup(); - simpleserial_init(); - simpleserial_addcmd('i', 32, cmd_init_prng); - simpleserial_addcmd('c', MAX_SS_LEN, cmd_set_curve); - simpleserial_addcmd('g', 0, cmd_generate); - simpleserial_addcmd('s', MAX_SS_LEN, cmd_set_privkey); - simpleserial_addcmd('w', MAX_SS_LEN, cmd_set_pubkey); - simpleserial_addcmd('m', MAX_SS_LEN, cmd_scalar_mult); - simpleserial_addcmd('e', MAX_SS_LEN, cmd_ecdh); - simpleserial_addcmd('a', MAX_SS_LEN, cmd_ecdsa_sign); - simpleserial_addcmd('v', MAX_SS_LEN, cmd_ecdsa_verify); - while(simpleserial_get()); - return 0; -}
\ No newline at end of file diff --git a/pyecsca/codegen/prng/prng.c b/pyecsca/codegen/prng/prng.c index 934fe72..e3cb755 100644 --- a/pyecsca/codegen/prng/prng.c +++ b/pyecsca/codegen/prng/prng.c @@ -14,7 +14,7 @@ mp_err prng_mp_rand(void *out, size_t size) { void prng_init(void) { KeccakWidth200_SpongePRG_Initialize(&keccak, 70); - mp_rand_source(prng_mp_rand); + mp_rand_source(&prng_mp_rand); } int prng_get(uint8_t *out, size_t size) { diff --git a/pyecsca/codegen/simpleserial/simpleserial.c b/pyecsca/codegen/simpleserial/simpleserial.c index d15b309..4d73ebb 100644 --- a/pyecsca/codegen/simpleserial/simpleserial.c +++ b/pyecsca/codegen/simpleserial/simpleserial.c @@ -28,10 +28,10 @@ int hex_decode(int len, char* ascii_buf, uint8_t* data_buf) if (len % 2 != 0) return 1; - for(int i = 0; i < len; i+=2) + for(int i = 0; i < len/2; i++) { - char n_hi = ascii_buf[i]; - char n_lo = ascii_buf[i+1]; + char n_hi = ascii_buf[i*2]; + char n_lo = ascii_buf[i*2+1]; if(n_lo >= '0' && n_lo <= '9') data_buf[i] = n_lo - '0'; diff --git a/pyecsca/codegen/templates/coords.c b/pyecsca/codegen/templates/coords.c index 98ab86f..016dc36 100644 --- a/pyecsca/codegen/templates/coords.c +++ b/pyecsca/codegen/templates/coords.c @@ -1,3 +1,5 @@ +#include "coords.h" + point_t *point_new(void) { point_t *result = malloc(sizeof(point_t)); {%- for variable in variables %} @@ -26,10 +28,34 @@ void point_free(point_t *point) { free(point); } -int point_to_affine(point_t *point, const char coord, curve_t *curve, bn_t *out) { - +int point_to_affine(point_t *point, curve_t *curve, bn_t *out_x, bn_t *out_y) { + {%- include "ops.c" %} + {%- if "x" in allocations %} + if (out_x) { + bn_copy(&x, out_x); + } + {%- endif %} + {%- if "y" in allocations %} + if (out_y) { + bn_copy(&y, out_y); + } + {%- endif %} + {%- for free in to_affine_frees %} + bn_clear(&{{ free }}); + {%- endfor %} } int point_from_affine(bn_t *x, bn_t *y, curve_t *curve, point_t *out) { - + {# XXX: This just works for the stuff currently in EFD. #} + {%- for variable in variables %} + {%- if variable in ("X", "Y") %} + bn_copy({{ variable | lower }}, &out->{{ variable }}); + {%- endif %} + {%- if variable == "Z" %} + bn_from_int(1, &out->Z); + {%- endif %} + {%- if variable == "T" %} + bn_mod_mul(x, y, &curve->p, &out->T); + {%- endif %} + {%- endfor %} } diff --git a/pyecsca/codegen/templates/coords.h b/pyecsca/codegen/templates/coords.h index 6890c11..91b6626 100644 --- a/pyecsca/codegen/templates/coords.h +++ b/pyecsca/codegen/templates/coords.h @@ -1,5 +1,36 @@ +#ifndef POINT_H_ +#define POINT_H_ + typedef struct { {%- for variable in variables %} bn_t {{ variable }}; {%- endfor %} -} point_t;
\ No newline at end of file +} point_t; + +point_t *point_new(void); + +point_t *point_copy(const point_t *from); + +void point_set(const point_t *from, point_t *out); + +void point_free(point_t *point); + +int point_to_affine(point_t *point, curve_t *curve, bn_t *out_x, bn_t *out_y); + +int point_from_affine(bn_t *x, bn_t *y, curve_t *curve, point_t *out); + +int point_add(const point_t *one, const point_t *other, const curve_t *curve, point_t *out_one); + +int point_dbl(const point_t *one, const curve_t *curve, point_t *out_one); + +int point_tpl(const point_t *one, const curve_t *curve, point_t *out_one); + +int point_neg(const point_t *one, const curve_t *curve, point_t *out_one); + +int point_scl(const point_t *one, const curve_t *curve, point_t *out_one); + +int point_dadd(const point_t *one, const point_t *other, const point_t *diff, const curve_t *curve, point_t *out_one); + +int point_ladd(const point_t *one, const point_t *other, const point_t *diff, const curve_t *curve, point_t *out_one, point_t *out_other); + +#endif //POINT_H_
\ No newline at end of file diff --git a/pyecsca/codegen/templates/curve.c b/pyecsca/codegen/templates/curve.c index 3d98571..425bf2d 100644 --- a/pyecsca/codegen/templates/curve.c +++ b/pyecsca/codegen/templates/curve.c @@ -1,31 +1,32 @@ -curve_t* curve_new(const named_bn_t **params, int num_params) { +curve_t* curve_new() { curve_t *result = malloc(sizeof(curve_t)); - bn_init(&result->p); - {%- for param in params %} + {%- for param in params + ["p", "n", "h"] %} bn_init(&result->{{ param }}); {%- endfor %} - bn_init(&result->n); - result->neutral = NULL; + result->generator = point_new(); + result->neutral = point_new(); - for (int i = 0; i < num_params; ++i) { - switch (params[i]->name) { - {%- for param in params %} - case '{{ param }}': bn_copy(params[i]->value, result->{{ param }}); - break; - {%- endfor %} - default: - curve_free(result); - return NULL; - } - } return result; } void curve_free(curve_t *curve) { - bn_clear(&curve->p); - {%- for param in params %} + {%- for param in params + ["p", "n", "h"] %} bn_clear(&curve->{{ param }}); {%- endfor %} - bn_clear(&curve->n); + if (curve->generator) { + point_free(curve->generator); + } + if (curve->neutral) { + point_free(curve->neutral); + } free(curve); +} + +void curve_set_param(curve_t *curve, char name, const bn_t *value) { + switch (name) { + {%- for param in params + ["p", "n", "h"] %} + case '{{ param }}': bn_copy(value, &curve->{{ param }}); + break; + {%- endfor %} + } }
\ No newline at end of file diff --git a/pyecsca/codegen/templates/curve.h b/pyecsca/codegen/templates/curve.h index e901304..f9b1507 100644 --- a/pyecsca/codegen/templates/curve.h +++ b/pyecsca/codegen/templates/curve.h @@ -1,3 +1,6 @@ +#ifndef CURVE_H_ +#define CURVE_H_ + typedef struct { bn_t p; {%- for param in params %} @@ -5,5 +8,14 @@ typedef struct { {%- endfor %} bn_t n; bn_t h; + point_t *generator; point_t *neutral; -} curve_t;
\ No newline at end of file +} curve_t; + +curve_t* curve_new(); + +void curve_free(curve_t *curve); + +void curve_set_param(curve_t *curve, char name, const bn_t *value); + +#endif //CURVE_H_
\ No newline at end of file diff --git a/pyecsca/codegen/templates/main.c b/pyecsca/codegen/templates/main.c new file mode 100644 index 0000000..a3051f1 --- /dev/null +++ b/pyecsca/codegen/templates/main.c @@ -0,0 +1,358 @@ +#include "hal/hal.h" +#include "simpleserial/simpleserial.h" +#include "hash/hash.h" +#include "bn.h" +#include "prng.h" +#include "defs.h" +#include "fat.h" +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +static point_t *pubkey; +static bn_t privkey; + +static curve_t *curve; + +static size_t parse_data(const uint8_t *data, size_t len, const char *path, void(*callback)(const char *path, const uint8_t *data, size_t len, void *arg), void *callback_arg) { + size_t parsed = 0; + while (parsed < len) { + char name = (char) data[parsed]; + bool recurse = false; + if (name & 0x80) { + name = name & 0x7f; + recurse = true; + } + + uint8_t value_len = data[parsed + 1]; + size_t path_len = strlen(path); + char new_path[path_len + 1 + 1]; + strcpy(new_path, path); + new_path[path_len] = name; + new_path[path_len + 1] = '\0'; + + if (recurse) { + parsed += parse_data(data + parsed + 2, value_len, new_path, callback, callback_arg) + 2; + } else { + if (callback) + callback(new_path, data + parsed + 2, value_len, callback_arg); + parsed += value_len + 2; + } + } + return parsed; +} + +static void parse_init_prng(const char *path, const uint8_t *data, size_t len, void *arg) { + prng_seed(data, len); +} + +static uint8_t cmd_init_prng(uint8_t *data, uint16_t len) { + parse_data(data, len, "", parse_init_prng, NULL); + return 0; +} + +static void parse_set_curve(const char *path, const uint8_t *data, size_t len, void *arg) { + {%- for param in curve_parameters + ["p", "n", "h"] %} + if (strcmp(path, "{{ param }}") == 0) { + bn_from_bin(data, len, &curve->{{ param }}); + return; + } + {%- endfor %} + {%- for variable in curve_variables %} + if (strcmp(path, "g{{ variable }}") == 0) { + bn_from_bin(data, len, &curve->generator->{{ variable }}); + return; + } + if (strcmp(path, "i{{ variable }}") == 0) { + bn_from_bin(data, len, &curve->neutral->{{ variable }}); + return; + } + {%- endfor %} +} + +static uint8_t cmd_set_curve(uint8_t *data, uint16_t len) { + // need p, [params], n, h, g[variables], i[variables] + parse_data(data, len, "", parse_set_curve, NULL); + return 0; +} + +static uint8_t cmd_generate(uint8_t *data, uint16_t len) { + // generate a keypair, export privkey and affine pubkey + bn_init(&privkey); + bn_rand_mod(&privkey, &curve->n); + size_t priv_size = bn_to_bin_size(&privkey); + size_t coord_size = bn_to_bin_size(&curve->p); + + scalar_mult(&privkey, curve->generator, curve, pubkey); + + uint8_t priv[priv_size]; + bn_to_bin(&privkey, priv); + simpleserial_put('s', priv_size, priv); + uint8_t pub[coord_size * {{ curve_parameters | length }}]; + {%- for variable in curve_variables %} + bn_to_binpad(pubkey->{{ variable }}, pub + coord_size * {{ loop.index0 }}, coord_size); + {%- endfor %} + simpleserial_put('w', coord_size * {{ curve_parameters | length }}, pub); + return 0; +} + +static void parse_set_privkey(const char *path, const uint8_t *data, size_t len, void *arg) { + if (strcmp(path, "s") == 0) { + bn_from_bin(data, len, &privkey); + return; + } +} + +static uint8_t cmd_set_privkey(uint8_t *data, uint16_t len) { + // set the current privkey + parse_data(data, len, "", parse_set_privkey, NULL); + return 0; +} + +static void parse_set_pubkey(const char *path, const uint8_t *data, size_t len, void *arg) { + {%- for variable in curve_variables %} + if (strcmp(path, "w{{ variable }}") == 0) { + bn_from_bin(data, len, &pubkey->{{ variable }}); + return; + } + {%- endfor %} +} + +static uint8_t cmd_set_pubkey(uint8_t *data, uint16_t len) { + // set the current pubkey + parse_data(data, len, "", parse_set_pubkey, NULL); + return 0; +} + +static void parse_scalar_mult(const char *path, const uint8_t *data, size_t len, void *arg) { + bn_t *scalar = (bn_t *)arg; + if (strcmp(path, "s") == 0) { + bn_from_bin(data, len, scalar); + return; + } +} + +static uint8_t cmd_scalar_mult(uint8_t *data, uint16_t len) { + // perform base point scalar mult with supplied scalar, return affine point. + bn_t scalar; bn_init(&scalar); + parse_data(data, len, "", parse_scalar_mult, (void *) &scalar); + + point_t *result = point_new(); + + scalar_mult(&scalar, curve->generator, curve, result); + + uint8_t res[coord_size * {{ curve_parameters | length }}]; + {%- for variable in curve_variables %} + bn_to_binpad(result->{{ variable }}, res + coord_size * {{ loop.index0 }}, coord_size); + {%- endfor %} + simpleserial_put('w', coord_size * {{ curve_parameters | length }}, res); + bn_clear(&scalar); + point_free(&result); + return 0; +} + +static void parse_ecdh(const char *path, const uint8_t *data, size_t len, void *arg) { + point_t *other = (point_t *) arg; + {%- for variable in curve_variables %} + if (strcmp(path, "w{{ variable }}") == 0) { + bn_from_bin(data, len, &other->{{ variable }}); + return; + } + {%- endfor %} +} + +static uint8_t cmd_ecdh(uint8_t *data, uint16_t len) { + //perform ECDH with provided point (and current privkey), output shared secret + point_t *other = point_new(); + parse_data(data, len, "", parse_ecdh, (void *) other); + + point_t *result = point_new(); + + scalar_mult(&privkey, other, curve, result); + + bn_t x; bn_init(&x); + bn_t y; bn_init(&y); + + point_to_affine(result, curve, &x, &y); + + size_t size = bn_to_bin_size(&curve->p); + + uint8_t x_raw[size]; + bn_to_binpad(x, x_raw, size); + + size_t h_size = hash_size(size); + void *h_ctx = hash_new_ctx(); + hash_init(h_ctx); + uint8_t h_out[h_size]; + hash_final(h_ctx, size, x_raw, h_out); + hash_free_ctx(h_ctx); + + simpleserial_put('r', h_size, h_out); + bn_clear(&x); + bn_clear(&y); + point_free(result); + point_free(other); + return 0; +} + +static void parse_ecdsa_msg(const char *path, const uint8_t *data, size_t len, void *arg) { + fat_t *dest = (fat_t *)arg; + if (strcmp(path, "d") == 0) { + dest->len = len; + dest->value = malloc(len); + memcpy(dest->value, data, len); + return; + } +} + +static void parse_ecdsa_sig(const char *path, const uint8_t *data, size_t len, void *arg) { + fat_t *dest = (fat_t *)arg; + if (strcmp(path, "s") == 0) { + dest->len = len; + dest->value = malloc(len); + memcpy(dest->value, data, len); + return; + } +} + +static uint8_t cmd_ecdsa_sign(uint8_t *data, uint16_t len) { + //perform ECDSA signature on supplied data, output signature + fat_t data = fat_empty; + parse_data(data, len, "", parse_ecdsa_msg, (void *) &data); + + size_t h_size = hash_size(data.len); + void *h_ctx = hash_new_ctx(); + hash_init(h_ctx); + uint8_t h_out[h_size]; + hash_final(h_ctx, data.len, data.value, h_out); + hash_free_ctx(h_ctx); + free(data.value); + + bn_t h; bn_init(&h); + bn_from_bin(h_out, h_size, &h); + + int mod_len = bn_bit_length(&curve->n) + + if (h_size * 8 > mod_len) { + bn_rsh(&h, (h_size * 8) - mod_len, &h); + } + + bn_t k; bn_init(&k); + bn_rand_mod(&k, &curve->n); + + point_t *p = point_new(); + + scalar_mult(&k, curve->generator, curve, p); + + bn_t r; bn_init(&r); + point_to_affine(p, curve, &r, NULL); + bn_mod(&r, &curve->n, &r); + + bn_t s; bn_init(&s); + bn_copy(&privkey, s); + bn_mul_mod(&s, &r, &curve->n, &s); + bn_add_mod(&s, &h, &curve->n, &s); + bn_div_mod(&s, &k, &curve->n, &s); + + size_t result_len = 0; + uint8_t *result = as1n_der_encode(&r, &s, &result_len); + + simpleserial_put('s', result_len, result); + free(result); + point_free(p); + bn_clear(&r); + bn_clear(&s); + bn_clear(&k); + bn_clear(&h); + return 0; +} + +static uint8_t cmd_ecdsa_verify(uint8_t *data, uint16_t len) { + //perform ECDSA verification on supplied data and signature (and current pubkey), output status + fat_t data = fat_empty; + parse_data(data, len, "", parse_ecdsa_msg, (void *) &data); + fat_t sig = fat_empty; + parse_data(data, len, "", parse_ecdsa_sig, (void *) &sig); + + size_t h_size = hash_size(data.len); + void *h_ctx = hash_new_ctx(); + hash_init(h_ctx); + uint8_t h_out[h_size]; + hash_final(h_ctx, data.len, data.value, h_out); + hash_free_ctx(h_ctx); + free(data.value); + + bn_t h; bn_init(&h); + bn_from_bin(h_out, h_size, &h); + + int mod_len = bn_bit_length(&curve->n) + + if (h_size * 8 > mod_len) { + bn_rsh(&h, (h_size * 8) - mod_len, &h); + } + + bn_t r; bn_init(&r); + bn_t s; bn_init(&s); + if (!asn1_der_decode(sig.value, sig.len, &r, &s)) { + simpleserial_put('v', 1, "\0"); + bn_clear(&r); + bn_clear(&s); + bn_clear(&h); + free(sig.value); + return 0; + } + bn_t orig_r; bn_init(&orig_r); + bn_copy(&r, &orig_r); + + bn_inv_mod(&s, &curve->n, &s); + bn_mul_mod(&r, &s, &curve->n, &r); //r = u2 + bn_mul_mod(&h, &s, &curve->n, &h); //h = u1 + + point_t *p1 = point_new(); + point_t *p2 = point_new(); + scalar_mult(&h, curve->generator, curve, p1); + scalar_mult(&r, pubkey, curve, p2); + + point_add(p1, p2, curve, p1); + bn_t x; bn_init(&x); + point_to_affine(p1, curve, &x, NULL); + bn_mod(&x, &curve->n, &x); + + bool result = bn_eq(&orig_r, &x); + uint8_t res_data[1] = {(uint8_t) result}; + + simpleserial_put('v', 1, res_data); + point_free(p1); + point_free(p2); + bn_clear(&x); + bn_clear(&orig_r); + bn_clear(&h); + bn_clear(&r); + bn_clear(&s); + free(sig.value); + return 0; +} + +int main(void) { + platform_init(); + prng_init(); + init_uart(); + trigger_setup(); + + curve = curve_new(); + pubkey = point_new(); + bn_init(&privkey); + + simpleserial_init(); + simpleserial_addcmd('i', MAX_SS_LEN, cmd_init_prng); + simpleserial_addcmd('c', MAX_SS_LEN, cmd_set_curve); + simpleserial_addcmd('g', 0, cmd_generate); + simpleserial_addcmd('s', MAX_SS_LEN, cmd_set_privkey); + simpleserial_addcmd('w', MAX_SS_LEN, cmd_set_pubkey); + simpleserial_addcmd('m', MAX_SS_LEN, cmd_scalar_mult); + simpleserial_addcmd('e', MAX_SS_LEN, cmd_ecdh); + simpleserial_addcmd('a', MAX_SS_LEN, cmd_ecdsa_sign); + simpleserial_addcmd('v', MAX_SS_LEN, cmd_ecdsa_verify); + while(simpleserial_get()); + return 0; +}
\ No newline at end of file diff --git a/pyecsca/codegen/templates/ops.c b/pyecsca/codegen/templates/ops.c index 96aa6ee..b6c22ba 100644 --- a/pyecsca/codegen/templates/ops.c +++ b/pyecsca/codegen/templates/ops.c @@ -10,6 +10,10 @@ {{ render_op(op, result, left, right, "curve->p")}} {%- endfor %} +{%- for src, dst in returns.items() %} + bn_copy(&{{ src }}, &{{ dst }}); +{%- endfor %} + {%- for free in frees %} bn_clear(&{{ free }}); {%- endfor %}
\ No newline at end of file |
