From 23c460dff96f57a4fa480ab6426700b0be384f12 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sun, 1 Dec 2024 13:56:04 +0100 Subject: Add curve family generation. --- README.md | 8 +- src/Makefile | 2 +- src/cm/cm_any.c | 38 +++++++++ src/cm/cm_any.h | 6 ++ src/exhaustive/exhaustive.c | 28 +++++-- src/exhaustive/family.c | 193 ++++++++++++++++++++++++++++++++++++++++++++ src/exhaustive/family.h | 30 +++++++ src/gen/point.c | 3 + src/gen/seed.c | 2 + src/io/cli.c | 39 ++++++++- src/io/output.c | 2 +- src/misc/config.h | 25 +++++- src/misc/types.h | 3 + src/util/memory.c | 2 +- test/ecgen.sh | 8 ++ 15 files changed, 374 insertions(+), 15 deletions(-) create mode 100644 src/exhaustive/family.c create mode 100644 src/exhaustive/family.h diff --git a/README.md b/README.md index eeeab77..f4f1e8a 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Tool for generating Elliptic curve domain parameters. - `-s / --ansi[=SEED]` Generate a curve from `SEED` (ANSI X9.62 verifiable procedure). - `-b / --brainpool[=SEED]`Generate a curve using the Brainpool verifiably pseudorandom algorithm from the original paper. - `--brainpool-rfc[=SEED]` Generate a curve using the Brainpool verifiably pseudorandom algorithm as per RFC 5639. + - `-F / --family=FAMILY` Generate a pairing friendly curve from a curve family (e.g. "BN", "BLS12", "BLS24"). - `--nums` Generate a curve using the NUMS procedure (as per draft-black-numscurves-02). - `--twist` Generate a twist of a given curve. @@ -203,7 +204,7 @@ for Doxygen. ### Generation methods -Four different EC curve parameters generation methods are implemented. +Five different EC curve parameters generation methods are implemented. [Efficient Algorithms for Generating Elliptic Curves over Finite Fields Suitable for Use in Cryptography - [Baier]](https://www.cdc.informatik.tu-darmstadt.de/reports/reports/harald_baier.diss.pdf) @@ -258,6 +259,11 @@ Four different EC curve parameters generation methods are implemented. - [Elliptic curves over F_p suitable for cryptosystems - [Miyaji]](https://dspace.jaist.ac.jp/dspace/bitstream/10119/4464/1/73-61.pdf) - TODO: Extend with [Generating Anomalous Elliptic Curves - [Leprevost, Monnerat, Varrette, Vaydenay]](https://www.monnerat.info/publications/anomalous.pdf) +#### Curve families + + - Generates pairing friendly curves. + - Used with the `-F / --family` option. Select from BN, BLS12 or BLS24 currently. + ### Build ecgen can be built using Make or CMake. ecgen uses git submodules for testing at: diff --git a/src/Makefile b/src/Makefile index 6d5140b..54083c3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -14,7 +14,7 @@ FAST ?= 0 STATIC ?= 0 ifeq ($(DEBUG), 1) - ECGEN_CFLAGS = -DDEBUG -g -Og -Werror -pedantic + ECGEN_CFLAGS = -DDEBUG -g -O0 -Werror -pedantic else ifeq ($(TEST), 1) ECGEN_CFLAGS = -DNDEBUG --coverage -g -O0 else ifeq ($(FAST), 1) diff --git a/src/cm/cm_any.c b/src/cm/cm_any.c index e1dab54..f948ac1 100644 --- a/src/cm/cm_any.c +++ b/src/cm/cm_any.c @@ -143,6 +143,7 @@ GEN cm_construct_curve(GEN order, GEN d, GEN p, bool ord_prime) { GEN r = FpX_roots(H, p); debug_log("roots = %Ps", r); if (gequal(r, gtovec(gen_0))) { + avma = ltop; return NULL; } @@ -206,6 +207,43 @@ GEN cm_construct_curve(GEN order, GEN d, GEN p, bool ord_prime) { } } } + avma = ltop; + return NULL; +} + +GEN cm_construct_curve_subgroup(GEN r, GEN d, GEN p) { + debug_log("Constructing a curve with r = %Pi, d = %Pi, p = %Pi", r, d, + p); + pari_sp ltop = avma; + GEN H = polclass(d, 0, 0); + debug_log("H = %Ps", H); + + GEN roots = FpX_roots(H, p); + debug_log("roots = %Ps", roots); + if (gequal(roots, gtovec(gen_0))) { + avma = ltop; + return NULL; + } + + long rlen = glength(roots); + pari_sp btop = avma; + for (long i = 1; i <= rlen; ++i) { + GEN root = gel(roots, i); + debug_log("trying root = %Pi", root); + + GEN e = ellinit(ellfromj(mkintmod(root, p)), p, 0); + pari_CATCH(e_TYPE) { avma = btop; continue; } + pari_TRY { checkell(e); }; + pari_ENDCATCH{}; + + GEN ord = ellff_get_card(e); + if (dvdii(ord, r)) { + debug_log("Got curve."); + return gerepilecopy(ltop, e); + } + avma = btop; + } + avma = ltop; return NULL; } diff --git a/src/cm/cm_any.h b/src/cm/cm_any.h index 42fc68e..a49fd7f 100644 --- a/src/cm/cm_any.h +++ b/src/cm/cm_any.h @@ -23,6 +23,12 @@ typedef struct { */ GEN cm_construct_curve(GEN order, GEN d, GEN p, bool ord_prime); +/** + * @brief Construct an elliptic curve given a factor of its order, CM + * discriminant and field order. + */ +GEN cm_construct_curve_subgroup(GEN r, GEN d, GEN p); + /** * @brief * @param curve diff --git a/src/exhaustive/exhaustive.c b/src/exhaustive/exhaustive.c index 6523170..bf915c0 100644 --- a/src/exhaustive/exhaustive.c +++ b/src/exhaustive/exhaustive.c @@ -8,6 +8,7 @@ #include "brainpool.h" #include "brainpool_rfc.h" #include "nums.h" +#include "family.h" #include "check.h" #include "gen/curve.h" #include "gen/equation.h" @@ -137,6 +138,25 @@ static void exhaustive_ginit(gen_f *generators) { default: break; } + } else if (cfg->method == METHOD_FAMILY) { + // setup family generators + if (GET_BOOL(random)) { + generators[OFFSET_SEED] = &family_gen_seed_random; + } else { + generators[OFFSET_SEED] = &family_gen_seed_input; + + } + generators[OFFSET_FIELD] = &family_gen_field; + generators[OFFSET_A] = &gen_skip; + if (cfg->family == FAMILY_KSS16) { + generators[OFFSET_B] = &family_gen_equation_cm; + } else { + generators[OFFSET_B] = &family_gen_equation_iter; + } + + //TODO make the prime check optional, based on cfg->prime. + generators[OFFSET_ORDER] = &family_gen_order; + generators[OFFSET_GENERATORS] = &gens_gen_any; } else { // setup normal generators generators[OFFSET_SEED] = &gen_skip; @@ -250,8 +270,6 @@ static void exhaustive_cinit(check_t **validators) { if (cfg->method == METHOD_SEED) { GET(seed_algo); switch (cfg->seed_algo) { - case SEED_ANSI: - break; case SEED_BRAINPOOL: case SEED_BRAINPOOL_RFC: { // TODO: Missing Brainpool CM disc check. @@ -267,8 +285,6 @@ static void exhaustive_cinit(check_t **validators) { check_new(gens_check_anomalous, brainpool_check_gens, NULL); validators[OFFSET_GENERATORS] = gens_check; } break; - case SEED_FIPS: - break; default: break; } @@ -310,7 +326,7 @@ static void exhaustive_ainit(arg_t **gen_argss, arg_t **check_argss) { } void exhaustive_uinit(unroll_f *unrolls) { - if (cfg->seed_algo) { + if (cfg->seed_algo || cfg->method == METHOD_FAMILY) { unrolls[OFFSET_SEED] = &seed_unroll; } else { unrolls[OFFSET_SEED] = &unroll_skip; @@ -436,12 +452,14 @@ static void exhaustive_init(exhaustive_t *setup) { exhaustive_cinit(setup->validators); exhaustive_ainit(setup->gen_argss, setup->check_argss); exhaustive_uinit(setup->unrolls); + family_init(); } static void exhaustive_quit(exhaustive_t *setup) { field_quit(); equation_quit(); nums_quit(); + family_quit(); exhaustive_clear(setup); } diff --git a/src/exhaustive/family.c b/src/exhaustive/family.c new file mode 100644 index 0000000..9d48026 --- /dev/null +++ b/src/exhaustive/family.c @@ -0,0 +1,193 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2024 J08nY + */ + +#include "family.h" +#include "cm/cm_any.h" +#include "gen/seed.h" +#include "misc/config.h" +#include "util/random.h" + +#define FAMILIES (FAMILY_KSS40 + 1) + +static GEN nz_store[FAMILIES] = {0}; +static GEN pz_store[FAMILIES] = {0}; +static GEN rz_store[FAMILIES] = {0}; +static GEN tz_store[FAMILIES] = {0}; +static GEN D_store[FAMILIES] = {0}; + +void family_init() { + pari_sp ltop = avma; + nz_store[FAMILY_BN] = gclone(closure_evalgen(compile_str("(z) -> z"))); + pz_store[FAMILY_BN] = gclone(closure_evalgen( + compile_str("(z) -> 36*z^4 + 36*z^3 + 24*z^2 + 6*z + 1"))); + rz_store[FAMILY_BN] = gclone(closure_evalgen( + compile_str("(z) -> 36*z^4 + 36*z^3 + 18*z^2 + 6*z + 1"))); + tz_store[FAMILY_BN] = + gclone(closure_evalgen(compile_str("(z) -> 6*z + 1"))); + D_store[FAMILY_BN] = gclone(stoi(-3)); + + nz_store[FAMILY_BLS12] = gclone(closure_evalgen(compile_str("(z) -> z"))); + pz_store[FAMILY_BLS12] = gclone(closure_evalgen( + compile_str("(z) -> (z - 1)^2 * (z^4 - z^2 + 1)/3 + z"))); + rz_store[FAMILY_BLS12] = + gclone(closure_evalgen(compile_str("(z) -> z^4 - z^2 + 1"))); + tz_store[FAMILY_BLS12] = + gclone(closure_evalgen(compile_str("(z) -> z + 1"))); + D_store[FAMILY_BLS12] = gclone(stoi(-3)); + + nz_store[FAMILY_BLS24] = gclone(closure_evalgen(compile_str("(z) -> z"))); + pz_store[FAMILY_BLS24] = gclone(closure_evalgen( + compile_str("(z) -> (z - 1)^2 * (z^8 - z^4 + 1)/3 + z"))); + rz_store[FAMILY_BLS24] = + gclone(closure_evalgen(compile_str("(z) -> z^8 - z^4 + 1"))); + tz_store[FAMILY_BLS24] = + gclone(closure_evalgen(compile_str("(z) -> z + 1"))); + D_store[FAMILY_BLS24] = gclone(stoi(-3)); + + //TODO: This does not work... + nz_store[FAMILY_KSS16] = + gclone(closure_evalgen(compile_str("(z) -> 70*z + 25"))); + pz_store[FAMILY_KSS16] = gclone(closure_evalgen( + compile_str("(z) -> (z^10 + 2*z^9 + 5*z^8 + 48*z^6 + 152*z^5 + 240*z^4 " + "+ 625*z^2 + 2398*z + 3125)/980"))); + rz_store[FAMILY_KSS16] = gclone( + closure_evalgen(compile_str("(z) -> (z^8 + 48*z^4 + 625)/61250"))); + tz_store[FAMILY_KSS16] = + gclone(closure_evalgen(compile_str("(z) -> (2*z^5 + 41*z + 35)/35"))); + D_store[FAMILY_KSS16] = gclone(stoi(-1)); + + avma = ltop; +} + +static seed_t *family_new_seed() { + seed_t *result = seed_new(); + result->type = SEED_FAMILY; + return result; +} + +GENERATOR(family_gen_seed_random) { + curve->seed = family_new_seed(); + curve->seed->family.z = random_int(cfg->bits); + return 1; +} + +GENERATOR(family_gen_seed_input) { + pari_sp ltop = avma; + GEN inp = input_int("z:", cfg->bits); + if (gequalm1(inp)) { + avma = ltop; + return 0; + } else if (equalii(inp, gen_m2)) { + avma = ltop; + return INT_MIN; + } + curve->seed = family_new_seed(); + curve->seed->family.z = inp; + return 1; +} + +GENERATOR(family_gen_field) { + pari_sp ltop = avma; + GEN n = closure_callgen1(nz_store[cfg->family], curve->seed->family.z); + GEN pz = closure_callgen1(pz_store[cfg->family], n); + if (typ(pz) != t_INT || !isprime(pz)) { + avma = ltop; + return -1; + } + printf("p"); + GEN rz = closure_callgen1(rz_store[cfg->family], n); + if (typ(rz) != t_INT || !isprime(rz)) { + avma = ltop; + return -1; + } + printf("r"); + curve->field = gerepilecopy(ltop, pz); + return 1; +} + +static GEN b = NULL; +static curve_t *b_curve = NULL; + +GENERATOR(family_gen_equation_iter) { + curve->a = gmodulo(gen_0, curve->field); + + pari_sp ltop = avma; + if (!b) { + b = gclone(gen_1); + curve->b = gmodulo(gen_1, curve->field); + b_curve = curve; + return 1; + } else { + if (curve == b_curve) { + GEN bn = addii(b, gen_1); + gunclone(b); + b = gclone(bn); + curve->b = gerepilecopy(ltop, gmodulo(bn, curve->field)); + return 1; + } else { + // dont use b, regenerate it, + gunclone(b); + b = gclone(gen_1); + curve->b = gerepilecopy(ltop, gmodulo(gen_1, curve->field)); + b_curve = curve; + return 1; + } + } +} + +GENERATOR(family_gen_equation_cm) { + GEN n = closure_callgen1(nz_store[cfg->family], curve->seed->family.z); + GEN rz = closure_callgen1(rz_store[cfg->family], n); + GEN D = D_store[cfg->family]; + GEN e = cm_construct_curve_subgroup(rz, D, curve->field); + if (e) { + curve->a = ell_get_a4(e); + curve->b = ell_get_a6(e); + return 1; + } + return -3; +} + +GENERATOR(family_gen_order) { + pari_sp ltop = avma; + GEN n = closure_callgen1(nz_store[cfg->family], curve->seed->family.z); + GEN rz = closure_callgen1(rz_store[cfg->family], n); + GEN ord = ellff_get_card(curve->curve); + if (dvdii(ord, rz)) { + if (isclone(ord)) { + curve->order = gerepilecopy(ltop, ord); + } else { + avma = ltop; + curve->order = ord; + } + return 1; + } else { + avma = ltop; + return -2; + } +} + +void family_quit() { + for (int i = 0; i < FAMILIES; i++) { + if (nz_store[i]) { + gunclone(nz_store[i]); + } + if (pz_store[i]) { + gunclone(pz_store[i]); + } + if (rz_store[i]) { + gunclone(rz_store[i]); + } + if (tz_store[i]) { + gunclone(tz_store[i]); + } + if (D_store[i]) { + gunclone(D_store[i]); + } + } + if (b) { + gunclone(b); + } +} \ No newline at end of file diff --git a/src/exhaustive/family.h b/src/exhaustive/family.h new file mode 100644 index 0000000..9b7deaa --- /dev/null +++ b/src/exhaustive/family.h @@ -0,0 +1,30 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2024 J08nY + */ +/* + * @file family.h + */ +#ifndef ECGEN_EXHAUSTIVE_FAMILY_H +#define ECGEN_EXHAUSTIVE_FAMILY_H + +#include "misc/types.h" + +GENERATOR(family_gen_seed_random); + +GENERATOR(family_gen_seed_input); + +GENERATOR(family_gen_field); + +GENERATOR(family_gen_equation_iter); + +GENERATOR(family_gen_equation_cm); + +GENERATOR(family_gen_order); + +void family_init(); + +void family_quit(); + + +#endif //ECGEN_EXHAUSTIVE_FAMILY_H diff --git a/src/gen/point.c b/src/gen/point.c index 4f1c624..21d0c26 100644 --- a/src/gen/point.c +++ b/src/gen/point.c @@ -41,6 +41,9 @@ GENERATOR(points_gen_random) { for (size_t i = 0; i < curve->ngens; ++i) { subgroup_t *subgroup = curve->generators[i]; subgroup->npoints = npoints_per_gen[i]; + if (npoints_per_gen[i] == 0) { + continue; + } subgroup->points = points_new(npoints_per_gen[i]); for (size_t j = 0; j < npoints_per_gen[i]; ++j) { diff --git a/src/gen/seed.c b/src/gen/seed.c index 5dca17a..3e67135 100644 --- a/src/gen/seed.c +++ b/src/gen/seed.c @@ -53,6 +53,8 @@ void seed_free(seed_t **seed) { break; case SEED_NONE: break; + case SEED_FAMILY: + break; } try_free(*seed); *seed = NULL; diff --git a/src/io/cli.c b/src/io/cli.c index 5f29047..0da0770 100644 --- a/src/io/cli.c +++ b/src/io/cli.c @@ -31,6 +31,7 @@ enum opt_keys { OPT_APPEND = 'a', OPT_VERBOSE = 'v', OPT_MEMORY = 'm', + OPT_FAMILY = 'F', OPT_FP = 1, OPT_F2M, OPT_POINTS, @@ -59,9 +60,10 @@ struct argp_option cli_options[] = { {"ansi", OPT_ANSI, "SEED", OPTION_ARG_OPTIONAL, "Generate a curve from SEED (ANSI X9.62 verifiable procedure).", 2}, {"brainpool", OPT_BRAINPOOL, "SEED", OPTION_ARG_OPTIONAL, "Generate a curve from SEED (Brainpool procedure).", 2}, {"brainpool-rfc", OPT_BRAINPOOL_RFC, "SEED", OPTION_ARG_OPTIONAL, "Generate a curve from SEED (Brainpool procedure, as per RFC 5639).", 2}, - {"nums", OPT_NUMS, 0, 0, "Generate a curve using the NUMS procedure.", 2}, + {"nums", OPT_NUMS, 0, 0, "Generate a curve using the NUMS procedure.", 2}, {"invalid", OPT_INVALID, "RANGE", OPTION_ARG_OPTIONAL, "Generate a set of invalid curves, for a given curve (using Invalid curve algorithm).", 2}, - {"twist", OPT_TWIST, 0, 0, "Generate a twist of a given curve.", 2}, + {"twist", OPT_TWIST, 0, 0, "Generate a twist of a given curve.", 2}, + {"family", OPT_FAMILY, "NAME", 0, "Generate a curve from a curve family (e.g. BN, BLS12, BLS24, KSS)."}, {0, 0, 0, 0, "Generation options:", 3}, {"random", OPT_RANDOM, "WHAT", OPTION_ARG_OPTIONAL, "Generate a random curve (using Random approach). " @@ -171,6 +173,7 @@ static void cli_end(struct argp_state *state) { case METHOD_INVALID: case METHOD_TWIST: case METHOD_SUPERSINGULAR: + case METHOD_FAMILY: break; default: argp_failure(state, 1, 0, @@ -200,6 +203,10 @@ static void cli_end(struct argp_state *state) { "Can only generate anomalous curves over prime fields " "currently."); } + if (cfg->method == METHOD_FAMILY && cfg->field == FIELD_BINARY) { + argp_failure(state, 1, 0, + "Can only generate family curves over prime fields."); + } if (cfg->method == METHOD_SUPERSINGULAR && cfg->field == FIELD_BINARY) { argp_failure(state, 1, 0, "Can only generate supersingular curves over prime fields " @@ -213,7 +220,8 @@ static void cli_end(struct argp_state *state) { } if (cfg->method == METHOD_ANOMALOUS && !cfg->random) { argp_failure(state, 1, 0, - "Anomalous curves can only be generated randomly (specify the -r option)."); + "Anomalous curves can only be generated randomly (specify " + "the -r option)."); } // default values if (!cfg->count) { @@ -276,6 +284,31 @@ error_t cli_parse(int key, char *arg, struct argp_state *state) { cfg->method |= METHOD_SUPERSINGULAR; SET(method); break; + case OPT_FAMILY: + cfg->method |= METHOD_FAMILY; + SET(method); + if (strcasecmp(arg, "BN") == 0) { + cfg->family = FAMILY_BN; + } else if (strcasecmp(arg, "BLS12") == 0) { + cfg->family = FAMILY_BLS12; + } else if (strcasecmp(arg, "BLS24") == 0) { + cfg->family = FAMILY_BLS24; + } else if (strcasecmp(arg, "KSS16") == 0) { + argp_failure(state, 1, 0, "Family not yet supported."); + cfg->family = FAMILY_KSS16; + } else if (strcasecmp(arg, "KSS18") == 0) { + argp_failure(state, 1, 0, "Family not yet supported."); + cfg->family = FAMILY_KSS18; + } else if (strcasecmp(arg, "KSS36") == 0) { + argp_failure(state, 1, 0, "Family not yet supported."); + cfg->family = FAMILY_KSS36; + } else if (strcasecmp(arg, "KSS40") == 0) { + argp_failure(state, 1, 0, "Family not yet supported."); + cfg->family = FAMILY_KSS40; + } else { + argp_failure(state, 1, 0, "Unknown curve family = %s", arg); + } + break; case OPT_ANSI: cfg->method |= METHOD_SEED; SET(method); diff --git a/src/io/output.c b/src/io/output.c index a69b905..32b2de4 100644 --- a/src/io/output.c +++ b/src/io/output.c @@ -81,7 +81,7 @@ static JSON_Value *output_jjson(curve_t *curve) { fprintf(err, "Error, field has unknown amount of elements.\n"); exit(1); } - if (curve->seed) { + if (curve->seed && curve->seed->seed) { char *hex_str = bits_to_hex(curve->seed->seed); char *hex = try_calloc(strlen(hex_str) + 3); hex[0] = '0'; diff --git a/src/misc/config.h b/src/misc/config.h index 0c0a5ca..3272190 100644 --- a/src/misc/config.h +++ b/src/misc/config.h @@ -48,7 +48,8 @@ typedef enum { METHOD_SEED = 1 << 2, METHOD_INVALID = 1 << 3, METHOD_TWIST = 1 << 4, - METHOD_SUPERSINGULAR = 1 << 5 + METHOD_SUPERSINGULAR = 1 << 5, + METHOD_FAMILY = 1 << 6 } method_e; /** @@ -60,9 +61,23 @@ typedef enum { SEED_BRAINPOOL, SEED_BRAINPOOL_RFC, SEED_FIPS, - SEED_NUMS + SEED_NUMS, + SEED_FAMILY } seed_e; +/** + * @brief + */ +typedef enum { + FAMILY_BN = 0, + FAMILY_BLS12, + FAMILY_BLS24, + FAMILY_KSS16, + FAMILY_KSS18, + FAMILY_KSS36, + FAMILY_KSS40 +} family_e; + /** * @brief */ @@ -84,7 +99,8 @@ typedef struct { /** @brief Whether the curves should be Koblitz (a \\in {0, 1}, b = 1). */ bool koblitz; long koblitz_value; - /** @brief Whether the curves should have a smooth order (bit-length bound). */ + /** @brief Whether the curves should have a smooth order (bit-length bound). + */ bool smooth; long smooth_value; /** @brief Whether the curves should have a bound on the cofactor value. */ @@ -97,6 +113,8 @@ typedef struct { seed_e seed_algo; /** @brief What seed to use, if any, to generate the curves. */ char *seed; + /** @brief What family of curves to generate. */ + family_e family; /** @brief Whether the curves should be uniquely generated (one generator). */ bool unique; @@ -156,6 +174,7 @@ typedef struct { bool invalid_primes; bool seed_algo; bool seed; + bool family; bool unique; bool hex_check; bool points; diff --git a/src/misc/types.h b/src/misc/types.h index 827e8aa..ed9cd18 100644 --- a/src/misc/types.h +++ b/src/misc/types.h @@ -51,6 +51,9 @@ typedef struct { bits_t *seed_b; GEN mult; } brainpool; + struct { + GEN z; + } family; }; } seed_t; diff --git a/src/util/memory.c b/src/util/memory.c index d18c01f..f05efae 100644 --- a/src/util/memory.c +++ b/src/util/memory.c @@ -46,7 +46,7 @@ void *try_calloc(size_t size) { return alloc(calloc_func, size); } void *try_realloc(void *ptr, size_t size) { void *result = realloc_func(ptr, size); if (!result) { - perror("Couldn't alloc."); + perror("Couldn't realloc."); exit(EXIT_FAILURE); } return result; diff --git a/test/ecgen.sh b/test/ecgen.sh index 7aa146b..c067c2e 100755 --- a/test/ecgen.sh +++ b/test/ecgen.sh @@ -126,6 +126,13 @@ function supersingular() { assert_raises "${ecgen} --fp --supersingular -r --points=none 20" } +function family() { + start_test + assert_raises "${ecgen} --fp -r --family=BN 32" + assert_raises "${ecgen} --fp -r --family=BLS12 32" + assert_raises "${ecgen} --fp -r --family=BLS24 32" +} + function invalid() { start_test assert_raises "${ecgen} --fp -r -i 10" @@ -214,6 +221,7 @@ brainpool nums anomalous supersingular +family invalid twist cli -- cgit v1.2.3-70-g09d2