diff options
| author | J08nY | 2017-05-31 23:07:35 +0200 |
|---|---|---|
| committer | J08nY | 2017-05-31 23:07:35 +0200 |
| commit | 637702cb14fe7133f3cffe58eaaca4186d67fc43 (patch) | |
| tree | bdbb50a3fd8cae28a1c767d3fe20a3c0c752cab9 /src/gen | |
| parent | ba8c1f2bc424205cbb167b3c65ce184912c6173a (diff) | |
| download | ecgen-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.c | 162 | ||||
| -rw-r--r-- | src/gen/curve.h | 105 | ||||
| -rw-r--r-- | src/gen/equation.c | 126 | ||||
| -rw-r--r-- | src/gen/equation.h | 151 | ||||
| -rw-r--r-- | src/gen/field.c | 174 | ||||
| -rw-r--r-- | src/gen/field.h | 80 | ||||
| -rw-r--r-- | src/gen/gens.c | 45 | ||||
| -rw-r--r-- | src/gen/gens.h | 45 | ||||
| -rw-r--r-- | src/gen/order.c | 114 | ||||
| -rw-r--r-- | src/gen/order.h | 88 | ||||
| -rw-r--r-- | src/gen/point.c | 261 | ||||
| -rw-r--r-- | src/gen/point.h | 180 | ||||
| -rw-r--r-- | src/gen/seed.c | 104 | ||||
| -rw-r--r-- | src/gen/seed.h | 83 | ||||
| -rw-r--r-- | src/gen/types.c | 11 | ||||
| -rw-r--r-- | src/gen/types.h | 132 |
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 |
