aboutsummaryrefslogtreecommitdiff
path: root/src/gen
diff options
context:
space:
mode:
authorJ08nY2017-05-31 23:07:35 +0200
committerJ08nY2017-05-31 23:07:35 +0200
commit637702cb14fe7133f3cffe58eaaca4186d67fc43 (patch)
treebdbb50a3fd8cae28a1c767d3fe20a3c0c752cab9 /src/gen
parentba8c1f2bc424205cbb167b3c65ce184912c6173a (diff)
downloadecgen-637702cb14fe7133f3cffe58eaaca4186d67fc43.tar.gz
ecgen-637702cb14fe7133f3cffe58eaaca4186d67fc43.tar.zst
ecgen-637702cb14fe7133f3cffe58eaaca4186d67fc43.zip
Move stuff related to generators to src/gen.
Diffstat (limited to 'src/gen')
-rw-r--r--src/gen/curve.c162
-rw-r--r--src/gen/curve.h105
-rw-r--r--src/gen/equation.c126
-rw-r--r--src/gen/equation.h151
-rw-r--r--src/gen/field.c174
-rw-r--r--src/gen/field.h80
-rw-r--r--src/gen/gens.c45
-rw-r--r--src/gen/gens.h45
-rw-r--r--src/gen/order.c114
-rw-r--r--src/gen/order.h88
-rw-r--r--src/gen/point.c261
-rw-r--r--src/gen/point.h180
-rw-r--r--src/gen/seed.c104
-rw-r--r--src/gen/seed.h83
-rw-r--r--src/gen/types.c11
-rw-r--r--src/gen/types.h132
16 files changed, 1861 insertions, 0 deletions
diff --git a/src/gen/curve.c b/src/gen/curve.c
new file mode 100644
index 0000000..bc382cd
--- /dev/null
+++ b/src/gen/curve.c
@@ -0,0 +1,162 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+#include "curve.h"
+#include "point.h"
+#include "seed.h"
+#include "util/memory.h"
+
+curve_t *curve_new(void) { return try_calloc(sizeof(curve_t)); }
+
+curve_t *curve_copy(const curve_t *src, curve_t *dest) {
+ if (src->seed) dest->seed = seed_copy(src->seed, dest->seed);
+ if (src->field) dest->field = gcopy(src->field);
+ if (src->a) dest->a = gcopy(src->a);
+ if (src->b) dest->b = gcopy(src->b);
+ if (src->curve) dest->curve = gcopy(src->curve);
+ if (src->order) dest->order = gcopy(src->order);
+ if (src->generators) {
+ dest->generators = points_new_copy(src->generators, src->ngens);
+ dest->ngens = src->ngens;
+ }
+ if (src->points) {
+ dest->points = points_new_copy(src->points, src->npoints);
+ dest->npoints = src->npoints;
+ }
+ return dest;
+}
+
+curve_t *curve_new_copy(const curve_t *src) {
+ curve_t *result = curve_new();
+ return curve_copy(src, result);
+}
+
+curve_t *curve_clone(const curve_t *src, curve_t *dest) {
+ if (src->seed) dest->seed = seed_clone(src->seed, dest->seed);
+ if (src->field) dest->field = gclone(src->field);
+ if (src->a) dest->a = gclone(src->a);
+ if (src->b) dest->b = gclone(src->b);
+ if (src->curve) dest->curve = gclone(src->curve);
+ if (src->order) dest->order = gclone(src->order);
+ if (src->generators) {
+ dest->generators = points_new_clone(src->generators, src->ngens);
+ dest->ngens = src->ngens;
+ }
+ if (src->points) {
+ dest->points = points_new_clone(src->points, src->npoints);
+ dest->npoints = src->npoints;
+ }
+ return dest;
+}
+
+curve_t *curve_new_clone(const curve_t *src) {
+ curve_t *result = curve_new();
+ return curve_clone(src, result);
+}
+
+void curve_free(curve_t **curve) {
+ if (*curve) {
+ seed_free(&(*curve)->seed);
+ points_free_deep(&(*curve)->generators, (*curve)->ngens);
+ points_free_deep(&(*curve)->points, (*curve)->npoints);
+
+ if ((*curve)->curve) {
+ // TODO, this is possibly dangerous...
+ obj_free((*curve)->curve);
+ if (isclone((*curve)->curve)) {
+ gunclone((*curve)->curve);
+ }
+ }
+
+ if ((*curve)->field && isclone((*curve)->field)) {
+ gunclone((*curve)->field);
+ }
+ if ((*curve)->a && isclone((*curve)->a)) {
+ gunclone((*curve)->a);
+ }
+ if ((*curve)->b && isclone((*curve)->b)) {
+ gunclone((*curve)->b);
+ }
+ if ((*curve)->order && isclone((*curve)->order)) {
+ gunclone((*curve)->order);
+ }
+
+ pari_free(*curve);
+ *curve = NULL;
+ }
+}
+
+GENERATOR(curve_gen_any) {
+ pari_sp ltop = avma;
+ GEN v = gen_0;
+ switch (typ(curve->field)) {
+ case t_INT:
+ v = gtovec0(gen_0, 2);
+ gel(v, 1) = curve->a;
+ gel(v, 2) = curve->b;
+ break;
+ case t_FFELT:
+ v = gtovec0(gen_0, 5);
+ gel(v, 1) = gen_1;
+ gel(v, 2) = curve->a;
+ gel(v, 4) = curve->b;
+ break;
+ default:
+ pari_err_TYPE("curve_gen_any", curve->field);
+ }
+ GEN crv = ellinit(v, curve->field, -1);
+
+ if (glength(crv) == 0) {
+ avma = ltop;
+ return -3;
+ } else {
+ curve->curve = gerepilecopy(ltop, crv);
+ return 1;
+ }
+}
+
+GENERATOR(curve_gen_nonzero) {
+ pari_sp ltop = avma;
+ int any = curve_gen_any(curve, cfg, args);
+ if (any <= 0) {
+ return any;
+ }
+ if (gequal0(ell_get_disc(curve->curve))) {
+ avma = ltop;
+ return -3;
+ } else {
+ return 1;
+ }
+}
+
+static int curve_gen_seed_fp(curve_t *curve, const config_t *cfg, arg_t *args) {
+ // TODO implement
+ return INT_MIN;
+}
+
+static int curve_gen_seed_f2m(curve_t *curve, const config_t *cfg,
+ arg_t *args) {
+ // TODO implement
+ return INT_MIN;
+}
+
+GENERATOR(curve_gen_seed) {
+ switch (typ(curve->field)) {
+ case t_INT:
+ return curve_gen_seed_fp(curve, cfg, args);
+ case t_FFELT:
+ return curve_gen_seed_f2m(curve, cfg, args);
+ default:
+ pari_err_TYPE("curve_gen_seed", curve->field);
+ return INT_MIN; /* NOT REACHABLE */
+ }
+}
+
+UNROLL(curve_unroll) {
+ if (curve->curve) {
+ obj_free(curve->curve);
+ curve->curve = NULL;
+ }
+ return -1;
+}
diff --git a/src/gen/curve.h b/src/gen/curve.h
new file mode 100644
index 0000000..2e7651f
--- /dev/null
+++ b/src/gen/curve.h
@@ -0,0 +1,105 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+/**
+ * @file curve.h
+ */
+#ifndef ECGEN_CURVE_H
+#define ECGEN_CURVE_H
+
+#include <pari/pari.h>
+#include "types.h"
+
+/**
+ * GENERATOR(gen_t)
+ * Creates a curve GEN in curve_t curve from field, a and b.
+ * Always succeeds.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(curve_gen_any);
+
+/**
+ * GENERATOR(gen_t)
+ * Creates a curve GEN in curve_t curve from field, a and b.
+ * Succeeds if a curve exists(non-zero discriminant).
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(curve_gen_nonzero);
+
+/**
+ * GENERATOR(gen_t)
+ * Creates a curve GEN in curve_t curve from field, a and b. Using the ANSI
+ * X9.62 verifiably random algorithm.
+ * Succeeds if a curve exists(non-zero discriminant).
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(curve_gen_seed);
+
+/**
+ *
+ * @param curve
+ * @param cfg
+ * @param from
+ * @param to
+ * @return
+ */
+UNROLL(curve_unroll);
+
+/**
+ * Allocates and zeros out a new curve_t object.
+ * @return new curve
+ */
+curve_t *curve_new(void);
+
+/**
+ * Copies parameters from src curve to dest curve, allocates space for points.
+ * Otherwise expects everything to be allocated.
+ *
+ * @param src source curve
+ * @param dest destination curve
+ * @return destination curve
+ */
+curve_t *curve_copy(const curve_t *src, curve_t *dest);
+
+/**
+ *
+ * @param src
+ * @return
+ */
+curve_t *curve_new_copy(const curve_t *src);
+
+/**
+ *
+ * @param src
+ * @param dest
+ * @return
+ */
+curve_t *curve_clone(const curve_t *src, curve_t *dest);
+
+/**
+ *
+ * @param src
+ * @return
+ */
+curve_t *curve_new_clone(const curve_t *src);
+
+/**
+ * Free a curve_t along with it's seed_t and point_ts.
+ * @param curve to free
+ */
+void curve_free(curve_t **curve);
+
+#endif // ECGEN_CURVE_H
diff --git a/src/gen/equation.c b/src/gen/equation.c
new file mode 100644
index 0000000..14409b4
--- /dev/null
+++ b/src/gen/equation.c
@@ -0,0 +1,126 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+#include "equation.h"
+#include "io/input.h"
+#include "field.h"
+
+GENERATOR(a_gen_random) {
+ curve->a = genrand(curve->field);
+ return 1;
+}
+
+GENERATOR(a_gen_input) {
+ pari_sp ltop = avma;
+ GEN inp = input_int("a:", cfg->bits);
+ if (gequalm1(inp)) {
+ avma = ltop;
+ return 0;
+ }
+ GEN elem = field_ielement(curve->field, inp);
+ if (!elem) {
+ avma = ltop;
+ return 0;
+ }
+ curve->a = elem;
+ return 1;
+}
+
+static GEN a = NULL;
+static curve_t *curve_a = NULL;
+
+GENERATOR(a_gen_once) {
+ if (a && curve_a == curve) {
+ curve->a = gcopy(a);
+ return 1;
+ }
+
+ int inp = a_gen_input(curve, cfg, args);
+ if (inp > 0) {
+ a = gclone(curve->a);
+ curve_a = curve;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+GENERATOR(a_gen_zero) {
+ curve->a = gen_0;
+ return 1;
+}
+
+GENERATOR(a_gen_one) {
+ curve->a = gen_1;
+ return 1;
+}
+
+GENERATOR(a_gen_seed) {
+ // TODO implement
+ return INT_MIN;
+}
+
+GENERATOR(b_gen_random) {
+ curve->b = genrand(curve->field);
+ return 1;
+}
+
+GENERATOR(b_gen_input) {
+ pari_sp ltop = avma;
+ GEN inp = input_int("b:", cfg->bits);
+ if (gequalm1(inp)) {
+ avma = ltop;
+ return 0;
+ }
+ GEN elem = field_ielement(curve->field, inp);
+ if (!elem) {
+ avma = ltop;
+ return 0;
+ }
+ curve->b = elem;
+ return 1;
+}
+
+static GEN b = NULL;
+static curve_t *curve_b = NULL;
+
+GENERATOR(b_gen_once) {
+ if (b && curve_b == curve) {
+ curve->b = gcopy(b);
+ return 1;
+ }
+
+ int inp = b_gen_input(curve, cfg, args);
+ if (inp > 0) {
+ b = gclone(curve->b);
+ curve_b = curve;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+GENERATOR(b_gen_zero) {
+ curve->b = gen_0;
+ return 1;
+}
+
+GENERATOR(g_gen_one) {
+ curve->b = gen_1;
+ return 1;
+}
+
+GENERATOR(b_gen_seed) {
+ // TODO implement
+ return INT_MIN;
+}
+
+void equation_quit(void) {
+ if (a && isclone(a)) {
+ gunclone(a);
+ }
+ if (b && isclone(b)) {
+ gunclone(b);
+ }
+}
diff --git a/src/gen/equation.h b/src/gen/equation.h
new file mode 100644
index 0000000..741517c
--- /dev/null
+++ b/src/gen/equation.h
@@ -0,0 +1,151 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+/**
+ * @file equation.h
+ */
+#ifndef ECGEN_EQUATION_H
+#define ECGEN_EQUATION_H
+
+#include "types.h"
+
+/**
+ * GENERATOR(gen_t)
+ * Creates a random a parameter by selecting a random field
+ * element from the curve field.
+ * Always succeeds.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(a_gen_random);
+
+/**
+ * GENERATOR(gen_t)
+ * Creates a parameter by reading from input.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(a_gen_input);
+
+/**
+ * GENERATOR(gen_t)
+ * Creates a parameter by reading once from input.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(a_gen_once);
+
+/**
+ * GENERATOR(gen_t)
+ * Creates a parameter set to zero.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(a_gen_zero);
+
+/**
+ * GENERATOR(gen_t)
+ * Creates a parameter set to one.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(a_gen_one);
+
+/**
+ * GENERATOR(gen_t)
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(a_gen_seed);
+
+/**
+ * GENERATOR(gen_t)
+ * Creates a random b parameter by selecting a random field
+ * element from the curve field.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(b_gen_random);
+
+/**
+ * GENERATOR(gen_t)
+ * Creates b parameter by reading from input.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(b_gen_input);
+
+/**
+ * GENERATOR(gen_t)
+ * Creates b parameter by reading once from input.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(b_gen_once);
+
+/**
+ * GENERATOR(gen_t)
+ * Creates b parameter set to zero.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(b_gen_zero);
+
+/**
+ * GENERATOR(gen_t)
+ * Creates b parameter set to one.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(g_gen_one);
+
+/**
+ * GENERATOR(gen_t)
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(b_gen_seed);
+
+/**
+ *
+ */
+void equation_quit(void);
+
+#endif // ECGEN_EQUATION_H
diff --git a/src/gen/field.c b/src/gen/field.c
new file mode 100644
index 0000000..8bf2bf0
--- /dev/null
+++ b/src/gen/field.c
@@ -0,0 +1,174 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+#include "field.h"
+#include "io/input.h"
+#include "math/poly.h"
+
+static GEN field_primer(unsigned long bits) { return random_prime(bits); }
+
+static GEN field_binaryr(unsigned long bits) {
+ if (poly_exists(bits)) {
+ return poly_find_gen(bits);
+ } else {
+ fprintf(stderr,
+ "Unable to find a suitable binary field. Use an explicit one.");
+ exit(1);
+ }
+}
+
+GENERATOR(field_gen_random) {
+ switch (cfg->field) {
+ case FIELD_PRIME:
+ curve->field = field_primer(cfg->bits);
+ return 1;
+ case FIELD_BINARY:
+ curve->field = field_binaryr(cfg->bits);
+ return 1;
+ default:
+ return INT_MIN; /* NOT REACHABLE */
+ }
+}
+
+GENERATOR(field_gen_input) {
+ pari_sp ltop = avma;
+ switch (cfg->field) {
+ case FIELD_PRIME: {
+ GEN p = input_prime("p:", cfg->bits);
+ if (equalii(p, gen_m1)) {
+ avma = ltop;
+ return 0;
+ }
+ curve->field = p;
+ return 1;
+ }
+ case FIELD_BINARY: {
+ GEN m = input_short("m:");
+ if (!equalis(m, cfg->bits)) {
+ avma = ltop;
+ return 0;
+ }
+
+ GEN e1 = input_short("e1:");
+ if (equalii(e1, gen_m1)) {
+ avma = ltop;
+ return 0;
+ }
+ GEN e2 = input_short("e2:");
+ if (equalii(e2, gen_m1)) {
+ avma = ltop;
+ return 0;
+ }
+ GEN e3 = input_short("e3:");
+ if (equalii(e3, gen_m1)) {
+ avma = ltop;
+ return 0;
+ }
+
+ if (isintzero(e1) && isintzero(e2) && isintzero(e3)) {
+ fprintf(stderr, "At least one exponent must be nonzero.\n");
+ avma = ltop;
+ return 0;
+ }
+
+ GEN v = gtovec0(gen_0, cfg->bits + 1);
+ gel(v, itos(m) + 1) = gen_1;
+ if (gsigne(e1) == 1) gel(v, itos(e1) + 1) = gen_1;
+ if (gsigne(e2) == 1) gel(v, itos(e2) + 1) = gen_1;
+ if (gsigne(e3) == 1) gel(v, itos(e3) + 1) = gen_1;
+ gel(v, 1) = gen_1;
+
+ GEN poly = gmul(gtopolyrev(v, -1), gmodulss(1, 2));
+ if (!isirreducible(poly)) {
+ fprintf(stderr, "Polynomial is reducible.\n");
+ avma = ltop;
+ return 0;
+ }
+
+ curve->field = gerepilecopy(ltop, ffgen(poly, -1));
+ return 1;
+ }
+ default:
+ return INT_MIN; /* NOT REACHABLE */
+ }
+}
+
+static GEN field = NULL;
+static curve_t *curve_field = NULL;
+
+GENERATOR(field_gen_once) {
+ if (field && curve_field == curve) {
+ curve->field = gcopy(field);
+ return 1;
+ }
+
+ int inp = field_gen_input(curve, cfg, args);
+ if (inp > 0) {
+ field = gclone(curve->field);
+ curve_field = curve;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+GEN field_params(GEN field) {
+ pari_sp ltop = avma;
+
+ if (typ(field) == t_INT) {
+ return gtovec(field);
+ }
+
+ GEN out = gtovec0(gen_0, 4);
+
+ long j = 1;
+ long l2 = glength(member_mod(field)) - 1;
+ {
+ pari_sp btop = avma;
+ for (long i = l2; i > 0; --i) {
+ GEN c = polcoeff0(member_mod(field), i, -1);
+ if (cmpis(c, 0) != 0) {
+ gel(out, j) = stoi(i);
+ j++;
+ }
+ gerepileall(btop, 2, &out, &c);
+ }
+ }
+ return gerepilecopy(ltop, out);
+}
+
+GEN field_elementi(GEN element) {
+ switch (typ(element)) {
+ case t_INT:
+ return element;
+ case t_INTMOD:
+ return lift(element);
+ case t_FFELT: {
+ pari_sp ltop = avma;
+ GEN coeffs = FF_to_FpXQ(element);
+ GEN vec = gtovec(coeffs);
+ GEN n = fromdigits(vec, stoi(2));
+ return gerepilecopy(ltop, n);
+ }
+ default:
+ pari_err_TYPE("field_elementi", element);
+ return NULL; /* NOT REACHABLE */
+ }
+}
+
+GEN field_ielement(GEN field, GEN in) {
+ switch (typ(field)) {
+ case t_INT:
+ return Fp_to_mod(in, field);
+ case t_FFELT: {
+ pari_sp ltop = avma;
+ GEN coeffs = digits(in, gen_2);
+ GEN poly = gtopoly(coeffs, -1);
+ return gerepilecopy(ltop, Fq_to_FF(poly, field));
+ }
+ default:
+ pari_err_TYPE("field_ielement, field is unknown type. ", field);
+ return gen_m1; /* NOT REACHABLE */
+ }
+}
diff --git a/src/gen/field.h b/src/gen/field.h
new file mode 100644
index 0000000..04af2c6
--- /dev/null
+++ b/src/gen/field.h
@@ -0,0 +1,80 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+/**
+ * @file field.h
+ */
+#ifndef ECGEN_FIELD_H
+#define ECGEN_FIELD_H
+
+#include "types.h"
+
+/**
+ * GENERATOR(gen_t)
+ * Creates a random field.
+ * Always succeeds.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(field_gen_random);
+
+/**
+ * GENERATOR(gen_t)
+ * Creates a field by reading:
+ * - a prime number in the prime field case
+ * - three short exponents of the reduction polynomial in the binary case
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(field_gen_input);
+
+/**
+ * GENERATOR(gen_t)
+ * Creates the field by reading it once.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(field_gen_once);
+
+/**
+ * Extract a field representation from a field.
+ * - char(field) == 2:
+ * returns the vector of powers of middle coefficients of the reduction
+ * polynomial.
+ * - char(field) != 2:
+ * returns the vector of the field characteristic(p).
+ *
+ * @param field
+ * @return field representation
+ */
+GEN field_params(GEN field);
+
+/**
+ * Transforms a field element to an integer.
+ * Uses the polynomial basis of the underlying field in case of a binary field.
+ *
+ * @param element t_INTMOD, t_INT, t_FFELT to transform
+ * @return t_INT
+ */
+GEN field_elementi(GEN element);
+
+/**
+ * Transforms an integer into a field element.
+ *
+ * @param field the field to work in
+ * @param in the integer to transform
+ * @return a field element, t_INTMOD or t_FFELT
+ */
+GEN field_ielement(GEN field, GEN in);
+
+#endif // ECGEN_FIELD_H
diff --git a/src/gen/gens.c b/src/gen/gens.c
new file mode 100644
index 0000000..f5f9fcb
--- /dev/null
+++ b/src/gen/gens.c
@@ -0,0 +1,45 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+#include "gens.h"
+#include "point.h"
+
+static int gens_put(curve_t *curve, GEN generators, long len) {
+ curve->generators = points_new((size_t)len);
+ curve->ngens = (size_t)len;
+
+ for (long i = 1; i <= len; ++i) {
+ point_t *p = point_new();
+ p->point = gel(generators, i);
+ p->order = ellorder(curve->curve, p->point, NULL);
+ p->cofactor = divii(curve->order, p->order);
+ curve->generators[i - 1] = p;
+ }
+
+ return 1;
+}
+
+GENERATOR(gens_gen_any) {
+ GEN generators = ellff_get_gens(curve->curve);
+ long len = glength(generators);
+ return gens_put(curve, generators, len);
+}
+
+GENERATOR(gens_gen_one) {
+ pari_sp ltop = avma;
+ GEN generators = ellff_get_gens(curve->curve);
+ long len = glength(generators);
+ if (len == 2) {
+ avma = ltop;
+ return -5;
+ }
+ return gens_put(curve, generators, len);
+}
+
+UNROLL(gens_unroll) {
+ if (curve->generators) {
+ points_free_deep(&curve->generators, curve->ngens);
+ }
+ return -1;
+}
diff --git a/src/gen/gens.h b/src/gen/gens.h
new file mode 100644
index 0000000..f46efbf
--- /dev/null
+++ b/src/gen/gens.h
@@ -0,0 +1,45 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+/**
+ * @brief
+ * @file gens.h
+ */
+#ifndef ECGEN_GENS_H
+#define ECGEN_GENS_H
+
+#include "types.h"
+
+/**
+ * GENERATOR(gen_t)
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(gens_gen_any);
+
+/**
+ * GENERATOR(gen_t)
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(gens_gen_one);
+
+/**
+ * UNROLL(unroll_t)
+ *
+ * @param curve
+ * @param cfg
+ * @param from
+ * @param to
+ * @return
+ */
+UNROLL(gens_unroll);
+
+#endif // ECGEN_GENS_H
diff --git a/src/gen/order.c b/src/gen/order.c
new file mode 100644
index 0000000..2c963f6
--- /dev/null
+++ b/src/gen/order.c
@@ -0,0 +1,114 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+#include "order.h"
+#include "io/input.h"
+
+GEN order_factors(curve_t *curve, const config_t *cfg) {
+ if (cfg->prime) {
+ return gtovec(curve->order);
+ } else {
+ GEN factors = Z_factor(curve->order);
+ return gel(factors, 1);
+ }
+}
+
+GEN order_groups(curve_t *curve, const config_t *cfg, GEN factors) {
+ long nprimes = glength(factors);
+ if (cfg->prime) {
+ return gtovec(curve->order);
+ } else {
+ GEN amount = int2n(nprimes);
+ GEN groups = gtovec0(gen_0, itos(amount) - 1);
+
+ for (size_t count = 1; count < (size_t)(1 << nprimes); ++count) {
+ GEN result = gen_1;
+ for (long bit = 0; bit < nprimes; ++bit) {
+ size_t mask = (size_t)(1 << bit);
+ if (count & mask) {
+ result = mulii(result, gel(factors, bit + 1));
+ }
+ }
+ gel(groups, count) = result;
+ }
+ // TODO: sort this, as it is not necessarily sorted, in fact most likely
+ // not
+ return groups;
+ }
+}
+
+GENERATOR(order_gen_input) {
+ pari_sp ltop = avma;
+ GEN ord = input_int("order", cfg->bits);
+ if (gequalm1(ord)) {
+ avma = ltop;
+ return -4;
+ } else {
+ curve->order = ord;
+ obj_insert_shallow(curve->curve, 1, ord);
+ return 1;
+ }
+}
+
+GENERATOR(order_gen_any) {
+ GEN ord = ellff_get_card(curve->curve);
+ if (isclone(ord)) {
+ curve->order = gcopy(ord);
+ } else {
+ curve->order = ord;
+ }
+ return 1;
+}
+
+GENERATOR(order_gen_sea) {
+ pari_sp ltop = avma;
+ GEN order = ellsea(curve->curve, 0);
+ if (gequal0(order)) {
+ avma = ltop;
+ return -4;
+ } else {
+ curve->order = order;
+ obj_insert_shallow(curve->curve, 1, order);
+ return 1;
+ }
+}
+
+GENERATOR(order_gen_smallfact) {
+ if (!args) {
+ fprintf(stderr, "No args to an arged function. order_gen_smallfact\n");
+ return INT_MIN;
+ }
+
+ pari_ulong smallfact = *(pari_ulong *)args->args;
+ pari_sp ltop = avma;
+ GEN fact = mpfact(smallfact);
+ if (lgefint(fact) > 3) {
+ smallfact = 0;
+ } else {
+ smallfact = itou(fact);
+ }
+
+ GEN order = ellsea(curve->curve, smallfact);
+ if (gequal0(order) || gequal1(gcdii(order, fact))) {
+ avma = ltop;
+ return -4;
+ } else {
+ curve->order = order;
+ obj_insert_shallow(curve->curve, 1, curve->order);
+ return 1;
+ }
+}
+
+GENERATOR(order_gen_prime) {
+ pari_sp ltop = avma;
+ GEN order = ellsea(curve->curve, 1);
+ if (gequal0(order) || !(isprime(order))) {
+ avma = ltop;
+ return -4;
+ } else {
+ curve->order = order;
+ obj_insert_shallow(curve->curve, 1, curve->order);
+ return 1;
+ }
+}
diff --git a/src/gen/order.h b/src/gen/order.h
new file mode 100644
index 0000000..bdb6ec0
--- /dev/null
+++ b/src/gen/order.h
@@ -0,0 +1,88 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+/**
+ * @file order.h
+ */
+#ifndef ECGEN_ORDER_H
+#define ECGEN_ORDER_H
+
+#include "types.h"
+
+/**
+ * @brief Factors curve order.
+ * @param curve
+ * @param cfg
+ * @return
+ */
+GEN order_factors(curve_t *curve, const config_t *cfg);
+
+/**
+ * @brief Enumerates all subgroup orders of a curve given prime order factors.
+ * @param curve
+ * @param cfg
+ * @param factors
+ * @return
+ */
+GEN order_groups(curve_t *curve, const config_t *cfg, GEN factors);
+
+/**
+ * GENERATOR(gen_t)
+ * Reads the curve order from input, does not verify it.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args Current optional generator argument
+ * @return state diff
+ * @return state diff
+ */
+GENERATOR(order_gen_input);
+
+/**
+ * GENERATOR(gen_t)
+ * Calculates the curve order, using a general algorithm.
+ * Always succeeds.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args Current optional generator argument
+ * @return state diff
+ */
+GENERATOR(order_gen_any);
+
+/**
+ * GENERATOR(gen_t)
+ * Calculates the curve order, using the SEA algorithm.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(order_gen_sea);
+
+/**
+ * GENERATOR(gen_t)
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args pari_ulong passed to ellsea(curve, smallfact)
+ * @return state diff
+ */
+GENERATOR(order_gen_smallfact);
+
+/**
+ * GENERATOR(gen_t)
+ * Calculates the curve order, always using the SEA algorithm,
+ * gives up early in case the order is divisible by "something".
+ * Succeeds if the curve has a prime order.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(order_gen_prime);
+
+#endif // ECGEN_ORDER_H
diff --git a/src/gen/point.c b/src/gen/point.c
new file mode 100644
index 0000000..4251913
--- /dev/null
+++ b/src/gen/point.c
@@ -0,0 +1,261 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+#include "point.h"
+#include "order.h"
+#include "util/memory.h"
+
+point_t *point_new(void) { return try_calloc(sizeof(point_t)); }
+
+point_t *point_copy(const point_t *src, point_t *dest) {
+ if (src->point) dest->point = gcopy(src->point);
+ if (src->order) dest->order = gcopy(src->order);
+ if (src->cofactor) dest->cofactor = gcopy(src->cofactor);
+ return dest;
+}
+
+point_t *point_new_copy(const point_t *src) {
+ point_t *result = point_new();
+ return point_copy(src, result);
+}
+
+point_t *point_clone(const point_t *src, point_t *dest) {
+ if (src->point) dest->point = gclone(src->point);
+ if (src->order) dest->order = gclone(src->order);
+ if (src->cofactor) dest->cofactor = gclone(src->cofactor);
+ return dest;
+}
+
+point_t *point_new_clone(const point_t *src) {
+ point_t *result = point_new();
+ return point_clone(src, result);
+}
+
+void point_free(point_t **point) {
+ if (*point) {
+ if ((*point)->point && isclone((*point)->point)) {
+ gunclone((*point)->point);
+ }
+ if ((*point)->order && isclone((*point)->order)) {
+ gunclone((*point)->order);
+ }
+ if ((*point)->cofactor && isclone((*point)->cofactor)) {
+ gunclone((*point)->cofactor);
+ }
+ pari_free(*point);
+ *point = NULL;
+ }
+}
+
+point_t **points_new(size_t num) { return try_calloc(num * sizeof(point_t *)); }
+
+point_t **points_copy(point_t **const src, point_t **dest, size_t num) {
+ for (size_t i = 0; i < num; ++i) {
+ dest[i] = point_new_copy(src[i]);
+ }
+ return dest;
+}
+
+point_t **points_new_copy(point_t **const src, size_t num) {
+ point_t **result = points_new(num);
+ return points_copy(src, result, num);
+}
+
+point_t **points_clone(point_t **const src, point_t **dest, size_t num) {
+ for (size_t i = 0; i < num; ++i) {
+ dest[i] = point_new_clone(src[i]);
+ }
+ return dest;
+}
+
+point_t **points_new_clone(point_t **const src, size_t num) {
+ point_t **result = points_new(num);
+ return points_clone(src, result, num);
+}
+
+void points_free(point_t ***points) {
+ if (*points) {
+ pari_free(*points);
+ *points = NULL;
+ }
+}
+
+void points_free_deep(point_t ***points, size_t npoints) {
+ if (*points) {
+ for (size_t i = 0; i < npoints; ++i) {
+ point_free(&(*points)[i]);
+ }
+ points_free(points);
+ }
+}
+
+GENERATOR(point_gen_random) {
+ point_t *p = point_new();
+ p->point = genrand(curve->curve);
+ p->order = ellorder(curve->curve, p->point, NULL);
+
+ curve->points = points_new(1);
+ curve->points[0] = p;
+ curve->npoints = 1;
+ return 1;
+}
+
+GENERATOR(points_gen_random) {
+ if (!args) {
+ fprintf(stderr, "No args to an arged function. points_gen_random\n");
+ return INT_MIN;
+ }
+
+ size_t npoints = *(size_t *)args->args;
+
+ curve->points = points_new(npoints);
+ curve->npoints = npoints;
+ for (size_t i = 0; i < npoints; ++i) {
+ point_t *p = point_new();
+ p->point = genrand(curve->curve);
+ p->order = ellorder(curve->curve, p->point, NULL);
+ curve->points[i] = p;
+ }
+ return 1;
+}
+
+/*
+ GEN o = utoi(dprimes[i]);
+ GEN mul = ellmul(curve->curve, rand, o);
+
+ if (gequal0(mul)) {
+ printf("Success! %lu\n", npoints);
+ curve->points[i] = point_new();
+
+ gerepileall(btop, 2, &rand, &o);
+ curve->points[i]->point = rand;
+ curve->points[i]->order = o;
+ npoints++;
+ break;
+ }
+ */
+
+GENERATOR(points_gen_trial) {
+ // TODO stack code!!!
+ if (!args) {
+ fprintf(stderr, "No args to an arged function. points_gen_trial\n");
+ return INT_MIN;
+ }
+
+ pari_ulong *primes = (pari_ulong *)args->args;
+ size_t nprimes = args->nargs;
+
+ curve->points = points_new(nprimes);
+ curve->npoints = nprimes;
+
+ size_t npoints = 0;
+ while (npoints < nprimes) {
+ GEN rand = genrand(curve->curve);
+ GEN ord = ellorder(curve->curve, rand, NULL);
+
+ for (long i = 0; i < nprimes; ++i) {
+ if (curve->points[i] == NULL && dvdis(ord, primes[i])) {
+ pari_sp ftop = avma;
+
+ GEN p = stoi(primes[i]);
+ GEN mul = divii(ord, p);
+ GEN point = ellmul(curve->curve, rand, mul);
+
+ curve->points[i] = point_new();
+ gerepileall(ftop, 2, &point, &p);
+ curve->points[i]->point = point;
+ curve->points[i]->order = p;
+ npoints++;
+ }
+ }
+ }
+
+ return 1;
+}
+
+GENERATOR(points_gen_prime) {
+ // TODO stack code!!!
+
+ GEN primes = order_factors(curve, cfg);
+ long nprimes = glength(primes);
+
+ curve->points = points_new((size_t)nprimes);
+ curve->npoints = (size_t)nprimes;
+
+ long npoints = 0;
+ while (npoints < nprimes) {
+ GEN rand = genrand(curve->curve);
+ GEN ord = ellorder(curve->curve, rand, NULL);
+ // ord(rand) = ord
+
+ for (long i = 1; i <= nprimes; ++i) {
+ if (curve->points[i - 1] == NULL && dvdii(ord, gel(primes, i))) {
+ pari_sp ftop = avma;
+
+ // primes[i] divides ord
+ // mul = ord/primes[i]
+ GEN mul = divii(ord, gel(primes, i));
+ GEN point = ellmul(curve->curve, rand, mul);
+
+ curve->points[i - 1] = point_new();
+ gerepileall(ftop, 1, &point);
+ curve->points[i - 1]->point = point;
+ curve->points[i - 1]->order = gcopy(gel(primes, i));
+ npoints++;
+ }
+ }
+ }
+
+ return 1;
+}
+
+GENERATOR(points_gen_allgroups) {
+ // TODO stack code!!!
+
+ GEN primes = order_factors(curve, cfg);
+
+ GEN groups = order_groups(curve, cfg, primes);
+ long ngroups = glength(groups);
+
+ curve->points = points_new((size_t)ngroups);
+ curve->npoints = (size_t)ngroups;
+
+ long npoints = 0;
+ while (npoints < ngroups) {
+ GEN rand = genrand(curve->curve);
+ GEN ord = ellorder(curve->curve, rand, NULL);
+
+ for (long i = 1; i <= ngroups; ++i) {
+ pari_sp ftop = avma;
+ GEN num = gel(groups, i);
+
+ if (curve->points[i - 1] == NULL) {
+ GEN point = NULL;
+ if (equalii(ord, num)) {
+ point = gcopy(rand);
+ } else if (dvdii(ord, num)) {
+ GEN mul = divii(ord, num);
+ point = ellmul(curve->curve, rand, mul);
+ }
+
+ if (point) {
+ curve->points[i - 1] = point_new();
+ gerepileall(ftop, 1, &point);
+ curve->points[i - 1]->point = point;
+ curve->points[i - 1]->order = gcopy(num);
+ ++npoints;
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+UNROLL(points_unroll) {
+ if (curve->points) {
+ points_free_deep(&curve->points, curve->npoints);
+ }
+ return -1;
+}
diff --git a/src/gen/point.h b/src/gen/point.h
new file mode 100644
index 0000000..1a0b348
--- /dev/null
+++ b/src/gen/point.h
@@ -0,0 +1,180 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+/**
+ * @file point.h
+ */
+#ifndef ECGEN_POINT_H
+#define ECGEN_POINT_H
+
+#include "types.h"
+
+/**
+ *
+ * @return
+ */
+point_t *point_new(void);
+
+/**
+ *
+ * @param src
+ * @param dest
+ * @return
+ */
+point_t *point_copy(const point_t *src, point_t *dest);
+
+/**
+ *
+ * @param src
+ * @return
+ */
+point_t *point_new_copy(const point_t *src);
+
+/**
+ *
+ * @param src
+ * @param dest
+ * @return
+ */
+point_t *point_clone(const point_t *src, point_t *dest);
+
+/**
+ *
+ * @param src
+ * @return
+ */
+point_t *point_new_clone(const point_t *src);
+
+/**
+ *
+ * @param point
+ */
+void point_free(point_t **point);
+
+/**
+ *
+ * @param num
+ * @return
+ */
+point_t **points_new(size_t num);
+
+/**
+ *
+ * @param src
+ * @param dest
+ * @param num
+ * @return
+ */
+point_t **points_copy(point_t **const src, point_t **dest, size_t num);
+
+/**
+ *
+ * @param src
+ * @param num
+ * @return
+ */
+point_t **points_new_copy(point_t **const src, size_t num);
+
+/**
+ *
+ * @param src
+ * @param dest
+ * @param num
+ * @return
+ */
+point_t **points_clone(point_t **const src, point_t **dest, size_t num);
+
+/**
+ *
+ * @param src
+ * @param num
+ * @return
+ */
+point_t **points_new_clone(point_t **const src, size_t num);
+
+/**
+ *
+ * @param point
+ */
+void points_free(point_t ***point);
+
+/**
+ *
+ * @param points
+ * @param npoints
+ */
+void points_free_deep(point_t ***points, size_t npoints);
+
+/**
+ * GENERATOR(gen_t)
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(point_gen_random);
+
+/**
+ * GENERATOR(gen_t)
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args size_t number of points to generate
+ * @return state diff
+ */
+GENERATOR(points_gen_random);
+
+/**
+ * GENERATOR(gen_t)
+ * Generates prime order points using trial division.
+ *
+ * Assumes the primes divide curve order, thus that points with all
+ * prime orders specified exist.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args pari_ulong array of primes length nargs
+ * @return state diff
+ */
+GENERATOR(points_gen_trial);
+
+/**
+ * GENERATOR(gen_t)
+ *
+ * Cauchy:
+ * Let G be a finite group and p be a prime. If p divides the order of G, then
+ * G has an element of order p.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(points_gen_prime);
+
+/**
+ * GENERATOR(gen_t)
+ *
+ * Generates points on all subgroups of the curve. Prime and non-prime order.
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+GENERATOR(points_gen_allgroups);
+
+/**
+ * UNROLL(unroll_t)
+ *
+ * @param curve
+ * @param cfg
+ * @param from
+ * @param to
+ * @return
+ */
+UNROLL(points_unroll);
+
+#endif // ECGEN_POINT_H
diff --git a/src/gen/seed.c b/src/gen/seed.c
new file mode 100644
index 0000000..44663c8
--- /dev/null
+++ b/src/gen/seed.c
@@ -0,0 +1,104 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+
+#include "seed.h"
+#include "util/memory.h"
+
+seed_t *seed_new(void) { return try_calloc(sizeof(seed_t)); }
+
+seed_t *seed_copy(const seed_t *src, seed_t *dest) {
+ if (src->seed) dest->seed = gcopy(src->seed);
+ return dest;
+}
+
+seed_t *seed_new_copy(const seed_t *src) {
+ seed_t *result = seed_new();
+ return seed_copy(src, result);
+}
+
+seed_t *seed_clone(const seed_t *src, seed_t *dest) {
+ if (src->seed) dest->seed = gclone(src->seed);
+ return dest;
+}
+
+seed_t *seed_new_clone(const seed_t *src) {
+ seed_t *result = seed_new();
+ return seed_clone(src, result);
+}
+
+void seed_free(seed_t **seed) {
+ if (*seed) {
+ if ((*seed)->seed && isclone((*seed)->seed)) {
+ gunclone((*seed)->seed);
+ }
+ pari_free(*seed);
+ *seed = NULL;
+ }
+}
+
+static GEN seed_stoi(const char *cstr) {
+ pari_sp ltop = avma;
+ GEN seed = gen_0;
+
+ size_t len = strlen(cstr);
+ for (size_t i = 0; i < len; ++i) {
+ pari_sp btop = avma;
+ GEN s = stoi(cstr[i]);
+ s = shifti(s, (len - i - 1) * 8);
+ seed = addii(seed, s);
+ gerepileall(btop, 1, &seed);
+ }
+
+ return gerepilecopy(ltop, seed);
+}
+
+char *seed_itos(GEN seed) {
+ pari_sp ltop = avma;
+ GEN bits = binary_zv(seed);
+
+ long len = glength(bits);
+ long bytes = (len / 8) + (len % 8 == 0 ? 0 : 1);
+ char *result = try_malloc((size_t)bytes);
+
+ for (long i = 0; i < len; ++i) {
+ // TODO
+ }
+ avma = ltop;
+ return result;
+}
+
+int seed_random(curve_t *curve, const config_t *cfg, arg_t *args) {
+ curve->seed = seed_new();
+ curve->seed->seed = random_int(160);
+ curve->seed->raw = seed_itos(curve->seed->seed);
+ curve->seed->raw_len = strlen(curve->seed->raw);
+ return 1;
+}
+
+int seed_argument(curve_t *curve, const config_t *cfg, arg_t *args) {
+ curve->seed = seed_new();
+ curve->seed->seed = seed_stoi(cfg->seed);
+ curve->seed->raw = cfg->seed;
+ curve->seed->raw_len = strlen(cfg->seed);
+ return 1;
+}
+
+int seed_input(curve_t *curve, const config_t *cfg, arg_t *args) {
+ pari_sp ltop = avma;
+
+ GEN str = input_string("seed:");
+ const char *cstr = GSTR(str);
+ if (strlen(cstr) < 20) {
+ fprintf(stderr, "SEED must be at least 160 bits(20 characters).\n");
+ avma = ltop;
+ return 0;
+ }
+
+ GEN seed = seed_stoi(cstr);
+
+ curve->seed = seed_new();
+ curve->seed->seed = gerepilecopy(ltop, seed);
+ return 1;
+}
diff --git a/src/gen/seed.h b/src/gen/seed.h
new file mode 100644
index 0000000..e4b7ac0
--- /dev/null
+++ b/src/gen/seed.h
@@ -0,0 +1,83 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+/**
+ * @file seed.h
+ */
+#ifndef ECGEN_SEED_H
+#define ECGEN_SEED_H
+
+#include "io/input.h"
+#include "types.h"
+
+/**
+ *
+ * @return
+ */
+seed_t *seed_new(void);
+
+/**
+ *
+ * @param src
+ * @param dest
+ * @return
+ */
+seed_t *seed_copy(const seed_t *src, seed_t *dest);
+
+/**
+ *
+ * @param src
+ * @return
+ */
+seed_t *seed_new_copy(const seed_t *src);
+
+/**
+ *
+ * @param src
+ * @param dest
+ * @return
+ */
+seed_t *seed_clone(const seed_t *src, seed_t *dest);
+
+/**
+ *
+ * @param src
+ * @return
+ */
+seed_t *seed_new_clone(const seed_t *src);
+
+/**
+ *
+ * @param seed
+ */
+void seed_free(seed_t **seed);
+
+/**
+ *
+ * @param curve
+ * @param config
+ * @param args
+ * @return
+ */
+int seed_random(curve_t *curve, const config_t *cfg, arg_t *args);
+
+/**
+ *
+ * @param curve
+ * @param config
+ * @param args
+ * @return
+ */
+int seed_argument(curve_t *curve, const config_t *cfg, arg_t *args);
+
+/**
+ *
+ * @param curve
+ * @param config
+ * @param args
+ * @return
+ */
+int seed_input(curve_t *curve, const config_t *cfg, arg_t *args);
+
+#endif // ECGEN_SEED_H
diff --git a/src/gen/types.c b/src/gen/types.c
new file mode 100644
index 0000000..afd6542
--- /dev/null
+++ b/src/gen/types.c
@@ -0,0 +1,11 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+#include "types.h"
+
+int gen_skip(curve_t *curve, const config_t *cfg, arg_t *args) { return 1; }
+
+int unroll_skip(curve_t *curve, const config_t *cfg, pari_sp from, pari_sp to) {
+ return -1;
+}
diff --git a/src/gen/types.h b/src/gen/types.h
new file mode 100644
index 0000000..a6494cf
--- /dev/null
+++ b/src/gen/types.h
@@ -0,0 +1,132 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+/**
+ * @file types.h
+ */
+#ifndef ECGEN_TYPES_H
+#define ECGEN_TYPES_H
+
+#include <limits.h>
+#include <pari/pari.h>
+#include "io/config.h"
+
+/**
+ * @brief
+ */
+typedef struct seed_t {
+ char *raw;
+ size_t raw_len;
+ GEN seed;
+} seed_t;
+
+/**
+ * @brief A point type.
+ * @param point a t_VEC with t_INTMOD or t_FFELT components [x,y]
+ * @param order a t_INT
+ * @param cofactor a t_INT
+ */
+typedef struct {
+ GEN point;
+ GEN order;
+ GEN cofactor;
+} point_t;
+
+/**
+ * @brief A curve type.
+ * @param seed a seed_t
+ * @param field a t_INT or t_FFELT
+ * @param a a t_INTMOD or t_FFELT a parameter
+ * @param b a t_INTMOD or t_FFELT b parameter
+ * @param curve a t_ELL, curve object
+ * @param order a t_INT, curve order
+ * @param generators generators saved
+ * @param ngens numver of generators saved in the curve type
+ * @param points points saved
+ * @param npoints number of points saved in the curve type
+ */
+typedef struct {
+ seed_t *seed;
+ GEN field;
+ GEN a;
+ GEN b;
+ GEN curve;
+ GEN order;
+ point_t **generators;
+ size_t ngens;
+ point_t **points;
+ size_t npoints;
+} curve_t;
+
+/**
+ * @brief
+ */
+typedef enum {
+ OFFSET_SEED = 0,
+ OFFSET_FIELD,
+ OFFSET_A,
+ OFFSET_B,
+ OFFSET_CURVE,
+ OFFSET_ORDER,
+ OFFSET_GENERATORS,
+ OFFSET_POINTS,
+ OFFSET_END
+} offset_e;
+
+/**
+ * @brief
+ */
+typedef struct {
+ const void *args;
+ size_t nargs;
+ void *allocd;
+} arg_t;
+
+/**
+ * @brief A generator function type.
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args Current optional generator argument
+ * @return state diff
+ */
+#define GENERATOR(gen_name) \
+ int gen_name(curve_t *curve, const config_t *cfg, arg_t *args)
+typedef GENERATOR((*gen_t));
+
+/**
+ * @brief An unroll function type
+ * @param curve
+ * @param cfg
+ * @param from
+ * @param to
+ * @return
+ */
+#define UNROLL(unroll_name) \
+ int unroll_name(curve_t *curve, const config_t *cfg, pari_sp from, \
+ pari_sp to)
+typedef UNROLL((*unroll_t));
+
+/**
+ * GENERATOR(gen_t)
+ *
+ *
+ * @param curve A curve_t being generated
+ * @param cfg An application config
+ * @param args unused
+ * @return state diff
+ */
+int gen_skip(curve_t *curve, const config_t *cfg, arg_t *args);
+
+/**
+ * UNROLL(unroll_t)
+ *
+ * @param curve
+ * @param cfg
+ * @param from
+ * @param to
+ * @return
+ */
+int unroll_skip(curve_t *curve, const config_t *cfg, pari_sp from, pari_sp to);
+
+#endif // ECGEN_TYPES_H