aboutsummaryrefslogtreecommitdiffhomepage
path: root/pyecsca/codegen/templates
diff options
context:
space:
mode:
authorJ08nY2019-11-27 20:34:58 +0100
committerJ08nY2019-11-27 20:34:58 +0100
commit32a4874abfbaff8cb4ee2d31fe71bcc3499e52dc (patch)
tree1203a322d7488ef51b4de2d34c6e0c2871ea68a5 /pyecsca/codegen/templates
parentbb00fee9702155586e674b9d6a3b838bd54baac2 (diff)
downloadpyecsca-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.c32
-rw-r--r--pyecsca/codegen/templates/coords.h33
-rw-r--r--pyecsca/codegen/templates/curve.c39
-rw-r--r--pyecsca/codegen/templates/curve.h14
-rw-r--r--pyecsca/codegen/templates/main.c358
-rw-r--r--pyecsca/codegen/templates/ops.c4
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