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 /pyecsca/codegen/templates | |
| parent | bb00fee9702155586e674b9d6a3b838bd54baac2 (diff) | |
| download | pyecsca-codegen-32a4874abfbaff8cb4ee2d31fe71bcc3499e52dc.tar.gz pyecsca-codegen-32a4874abfbaff8cb4ee2d31fe71bcc3499e52dc.tar.zst pyecsca-codegen-32a4874abfbaff8cb4ee2d31fe71bcc3499e52dc.zip | |
Reorganize files, implement proper main.
Diffstat (limited to 'pyecsca/codegen/templates')
| -rw-r--r-- | pyecsca/codegen/templates/coords.c | 32 | ||||
| -rw-r--r-- | pyecsca/codegen/templates/coords.h | 33 | ||||
| -rw-r--r-- | pyecsca/codegen/templates/curve.c | 39 | ||||
| -rw-r--r-- | pyecsca/codegen/templates/curve.h | 14 | ||||
| -rw-r--r-- | pyecsca/codegen/templates/main.c | 358 | ||||
| -rw-r--r-- | pyecsca/codegen/templates/ops.c | 4 |
6 files changed, 456 insertions, 24 deletions
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 |
