aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJ08nY2018-07-09 21:22:53 +0200
committerJ08nY2018-07-09 21:22:53 +0200
commit1be7218990f93c442fa71a073ab16e862092b205 (patch)
tree641c2aaa240cd9df5c19f32807ac38036471e127 /src
parent0c97ff4a611c19efbd383f1a5ad63f3d26d3c627 (diff)
downloadecgen-1be7218990f93c442fa71a073ab16e862092b205.tar.gz
ecgen-1be7218990f93c442fa71a073ab16e862092b205.tar.zst
ecgen-1be7218990f93c442fa71a073ab16e862092b205.zip
Diffstat (limited to 'src')
-rw-r--r--src/cm/anomalous.c (renamed from src/exhaustive/anomalous.c)0
-rw-r--r--src/cm/anomalous.h (renamed from src/exhaustive/anomalous.h)8
-rw-r--r--src/cm/cm.c166
-rw-r--r--src/cm/cm_any.c49
-rw-r--r--src/cm/cm_any.h18
-rw-r--r--src/cm/cm_prime.c21
-rw-r--r--src/cm/cm_prime.h9
-rw-r--r--src/cm/supersingular.c (renamed from src/exhaustive/supersingular.c)0
-rw-r--r--src/cm/supersingular.h (renamed from src/exhaustive/supersingular.h)6
-rw-r--r--src/ecgen.c5
-rw-r--r--src/exhaustive/exhaustive.c92
-rw-r--r--src/exhaustive/exhaustive.h7
-rw-r--r--src/io/cli.c2
-rw-r--r--src/math/subgroup.c3
14 files changed, 284 insertions, 102 deletions
diff --git a/src/exhaustive/anomalous.c b/src/cm/anomalous.c
index 70df8e4..70df8e4 100644
--- a/src/exhaustive/anomalous.c
+++ b/src/cm/anomalous.c
diff --git a/src/exhaustive/anomalous.h b/src/cm/anomalous.h
index 4083655..73b84fd 100644
--- a/src/exhaustive/anomalous.h
+++ b/src/cm/anomalous.h
@@ -5,11 +5,11 @@
/**
* @file anomalous.h
*/
-#ifndef ECGEN_EXHAUSTIVE_ANOMALOUS_H
-#define ECGEN_EXHAUSTIVE_ANOMALOUS_H
+#ifndef ECGEN_CM_ANOMALOUS_H
+#define ECGEN_CM_ANOMALOUS_H
#include <pari/pari.h>
-#include "arg.h"
+#include "exhaustive/arg.h"
#include "io/cli.h"
#include "misc/types.h"
@@ -57,4 +57,4 @@ void anomalous_init();
*/
void anomalous_quit();
-#endif // ECGEN_EXHAUSTIVE_ANOMALOUS_H
+#endif // ECGEN_CM_ANOMALOUS_H
diff --git a/src/cm/cm.c b/src/cm/cm.c
index a29e368..239bb5d 100644
--- a/src/cm/cm.c
+++ b/src/cm/cm.c
@@ -3,39 +3,163 @@
* Copyright (C) 2017-2018 J08nY
*/
#include "cm.h"
+#include "anomalous.h"
#include "cm_any.h"
#include "cm_prime.h"
-#include "io/output.h"
+#include "exhaustive/check.h"
+#include "exhaustive/exhaustive.h"
+#include "gen/curve.h"
+#include "gen/field.h"
+#include "gen/gens.h"
+#include "gen/hex.h"
+#include "gen/metadata.h"
+#include "gen/point.h"
#include "obj/curve.h"
-#include "p1363.h"
+#include "supersingular.h"
+
+static void cm_ginit(gen_f *generators, bool prime) {
+ // SEED unused.
+ generators[OFFSET_SEED] = &gen_skip;
+
+ // Setup stuff so it can be overridden.
+ if (cfg->unique) {
+ generators[OFFSET_GENERATORS] = &gens_gen_one;
+ } else {
+ generators[OFFSET_GENERATORS] = &gens_gen_any;
+ }
+
+ if (cfg->metadata) {
+ generators[OFFSET_METADATA] = &metadata_gen;
+ } else {
+ generators[OFFSET_METADATA] = &gen_skip;
+ }
+
+ switch (cfg->points.type) {
+ case POINTS_RANDOM:
+ if (cfg->points.amount) {
+ generators[OFFSET_POINTS] = &points_gen_random;
+ } else {
+ generators[OFFSET_POINTS] = &point_gen_random;
+ }
+ break;
+ case POINTS_PRIME:
+ generators[OFFSET_POINTS] = &points_gen_prime;
+ break;
+ case POINTS_NONPRIME:
+ generators[OFFSET_POINTS] = &points_gen_nonprime;
+ break;
+ case POINTS_ALL:
+ generators[OFFSET_POINTS] = &points_gen_allgroups;
+ break;
+ case POINTS_NONE:
+ generators[OFFSET_POINTS] = &gen_skip;
+ break;
+ }
+
+ // Now do the actual CM setup.
+ if (cfg->method == METHOD_CM) {
+ generators[OFFSET_FIELD] = &gen_skip;
+ generators[OFFSET_A] = &gen_skip;
+ generators[OFFSET_B] = &gen_skip;
+ if (prime) {
+ generators[OFFSET_CURVE] = &cm_gen_curve_prime;
+ generators[OFFSET_POINTS] = &points_gen_prime;
+ } else {
+ generators[OFFSET_CURVE] = &cm_gen_curve_any;
+ }
+ generators[OFFSET_ORDER] = &cm_gen_order;
+ } else if (cfg->method == METHOD_ANOMALOUS) {
+ generators[OFFSET_FIELD] = &anomalous_gen_field;
+ generators[OFFSET_A] = &gen_skip;
+ generators[OFFSET_B] = &anomalous_gen_equation;
+ generators[OFFSET_CURVE] = &curve_gen_any;
+ generators[OFFSET_ORDER] = &anomalous_gen_order;
+ } else if (cfg->method == METHOD_SUPERSINGULAR) {
+ if (cfg->random & RANDOM_FIELD) {
+ generators[OFFSET_FIELD] = &field_gen_random;
+ } else {
+ generators[OFFSET_FIELD] = &field_gen_input;
+ }
+ generators[OFFSET_A] = &gen_skip;
+ generators[OFFSET_B] = &supersingular_gen_equation;
+ generators[OFFSET_CURVE] = &curve_gen_any;
+ generators[OFFSET_ORDER] = &supersingular_gen_order;
+ }
+}
+
+static void cm_ainit(arg_t **gen_argss, arg_t **check_argss) {
+ if (cfg->method == METHOD_ANOMALOUS) {
+ arg_t *field_arg = arg_new();
+ arg_t *eq_arg = arg_new();
+ size_t *i = try_calloc(sizeof(size_t));
+ *i = 3;
+ field_arg->args = i;
+ field_arg->nargs = 1;
+ eq_arg->args = i;
+ eq_arg->nargs = 1;
+ eq_arg->allocd = i;
+ gen_argss[OFFSET_FIELD] = field_arg;
+ gen_argss[OFFSET_B] = eq_arg;
+ }
+
+ if (cfg->points.type == POINTS_RANDOM) {
+ arg_t *points_arg = arg_new();
+ points_arg->args = &cfg->points.amount;
+ points_arg->nargs = 1;
+ gen_argss[OFFSET_POINTS] = points_arg;
+ }
+}
+
+static void cm_cinit(check_t **validators) {
+ check_t *curve_check = check_new(curve_check_nonzero, NULL);
+ validators[OFFSET_CURVE] = curve_check;
+
+ if (cfg->hex_check) {
+ check_t *hex_check = check_new(hex_check_param, NULL);
+ validators[OFFSET_POINTS] = hex_check;
+ }
+}
int cm_do() {
debug_log_start("Starting Complex Multiplication method");
- int result = 0;
- GEN order = strtoi(cfg->cm_order);
- curve_t *curve = NULL;
+ gen_f generators[OFFSET_END] = {NULL};
+ arg_t *gen_argss[OFFSET_END] = {NULL};
+ check_t *validators[OFFSET_END] = {NULL};
+ arg_t *check_argss[OFFSET_END] = {NULL};
+ unroll_f unrolls[OFFSET_END] = {NULL};
- if (gequal0(order)) {
- fprintf(err, "Order requested not a number: %s\n", cfg->cm_order);
- result = 1;
- } else if (isprime(order)) {
- debug_log("Starting prime order curve generation");
- curve = cm_prime_curve(order);
- } else {
- debug_log("Starting composite order curve generation");
- curve = cm_any_curve(order);
+ exhaustive_t setup = {.generators = generators,
+ .gen_argss = gen_argss,
+ .validators = validators,
+ .check_argss = check_argss,
+ .unrolls = unrolls};
+
+ bool ord_prime = false;
+ if (cfg->method == METHOD_CM) {
+ GEN order = strtoi(cfg->cm_order);
+ if (gequal0(order)) {
+ fprintf(err, "Order requested not a number: %s\n", cfg->cm_order);
+ return 1;
+ }
+ ord_prime = (bool)isprime(order);
+ }
+
+ if (cfg->method == METHOD_ANOMALOUS) {
+ anomalous_init();
}
- if (curve) {
- output_o_begin();
- output_o(curve);
- output_o_end();
+ cm_ginit(setup.generators, ord_prime);
+ cm_ainit(setup.gen_argss, setup.check_argss);
+ cm_cinit(setup.validators);
+ exhaustive_uinit(setup.unrolls);
- curve_free(&curve);
- } else {
- result = 1;
+ int result = exhaustive_generate(&setup);
+
+ if (cfg->method == METHOD_ANOMALOUS) {
+ anomalous_quit();
}
+ exhaustive_clear(&setup);
debug_log_start("Finished Complex Multiplication method");
return result;
diff --git a/src/cm/cm_any.c b/src/cm/cm_any.c
index 401a544..f993fa3 100644
--- a/src/cm/cm_any.c
+++ b/src/cm/cm_any.c
@@ -3,6 +3,7 @@
* Copyright (C) 2017-2018 J08nY
*/
#include "cm_any.h"
+#include <misc/config.h>
#include <obj/obj.h>
#include "io/output.h"
#include "obj/curve.h"
@@ -13,9 +14,8 @@
* Constructing elliptic curves of prescribed order,
* Reiner Broker
* @param order
- * @return
*/
-static cm_any_qdisc_t *good_qdisc_minimal(GEN order) {
+static void good_qdisc_minimal(cm_any_qdisc_t *qdisc, GEN order) {
pari_sp ltop = avma;
GEN d = stoi(2);
while (true) {
@@ -37,11 +37,10 @@ static cm_any_qdisc_t *good_qdisc_minimal(GEN order) {
debug_log(
"Got an elem of prime trace: %Pi, d = %Pi, D = %Pi", p,
d, D);
- cm_any_qdisc_t *result = try_calloc(sizeof(cm_any_qdisc_t));
- result->p = p;
- result->d = D;
- gerepileall(ltop, 2, &result->p, &result->d);
- return result;
+ qdisc->p = p;
+ qdisc->d = D;
+ gerepileall(ltop, 2, &qdisc->p, &qdisc->d);
+ return;
}
}
}
@@ -200,26 +199,50 @@ GEN cm_construct_curve(GEN order, GEN d, GEN p, bool ord_prime) {
debug_log("Got curve twist.");
return gerepilecopy(ltop, twist);
}
- };
+ }
}
}
return NULL;
}
curve_t *cm_any_curve(GEN order) {
- cm_any_qdisc_t *min_disc = good_qdisc_minimal(order);
- debug_log("Got min D = %Pi", min_disc->d);
- GEN e = cm_construct_curve(order, min_disc->d, min_disc->p, false);
+ cm_any_qdisc_t min_disc = {0};
+ good_qdisc_minimal(&min_disc, order);
+ debug_log("Got min D = %Pi", min_disc.d);
+ GEN e = cm_construct_curve(order, min_disc.d, min_disc.p, false);
if (e == NULL) {
fprintf(err, "Could not construct curve.");
return NULL;
}
curve_t *curve = curve_new();
- curve->field = min_disc->p;
+ curve->field = min_disc.p;
curve->curve = e;
curve->a = ell_get_a4(e);
curve->b = ell_get_a6(e);
curve->order = gcopy(order);
- try_free(min_disc);
return curve;
+}
+
+GENERATOR(cm_gen_curve_any) {
+ pari_sp ltop = avma;
+ GEN order = strtoi(cfg->cm_order);
+ cm_any_qdisc_t min_disc = {0};
+ good_qdisc_minimal(&min_disc, order);
+ debug_log("Got min D = %Pi", min_disc.d);
+ GEN e = cm_construct_curve(order, min_disc.d, min_disc.p, false);
+ if (e == NULL) {
+ fprintf(err, "Could not construct curve.");
+ avma = ltop;
+ return -3;
+ }
+ curve->field = min_disc.p;
+ curve->a = ell_get_a4(e);
+ curve->b = ell_get_a6(e);
+ curve->curve = e;
+ return 1;
+}
+
+GENERATOR(cm_gen_order) {
+ curve->order = strtoi(cfg->cm_order);
+ return 1;
} \ No newline at end of file
diff --git a/src/cm/cm_any.h b/src/cm/cm_any.h
index eb54497..48dee1c 100644
--- a/src/cm/cm_any.h
+++ b/src/cm/cm_any.h
@@ -29,4 +29,22 @@ GEN cm_construct_curve(GEN order, GEN d, GEN p, bool ord_prime);
*/
curve_t *cm_any_curve(GEN order);
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+GENERATOR(cm_gen_curve_any);
+
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+GENERATOR(cm_gen_order);
+
#endif // ECGEN_CM_ANY_H
diff --git a/src/cm/cm_prime.c b/src/cm/cm_prime.c
index c7a931d..e3a6882 100644
--- a/src/cm/cm_prime.c
+++ b/src/cm/cm_prime.c
@@ -140,7 +140,7 @@ static void qdisc_free(cm_prime_qdisc_t *qdisc) { try_free(qdisc->Sp); }
curve_t *cm_prime_curve(GEN order) {
GEN e = NULL;
- cm_prime_qdisc_t qdisc;
+ cm_prime_qdisc_t qdisc = {0};
qdisc_init(&qdisc, order);
do {
qdisc_next(&qdisc);
@@ -164,4 +164,23 @@ curve_t *cm_prime_curve(GEN order) {
result->ngens = 1;
return result;
+}
+
+GENERATOR(cm_gen_curve_prime) {
+ GEN order = strtoi(cfg->cm_order);
+ GEN e = NULL;
+
+ cm_prime_qdisc_t qdisc = {0};
+ qdisc_init(&qdisc, order);
+ do {
+ qdisc_next(&qdisc);
+ e = cm_construct_curve(order, qdisc.D, qdisc.p, true);
+ } while (e == NULL);
+ qdisc_free(&qdisc);
+
+ curve->field = qdisc.p;
+ curve->a = ell_get_a4(e);
+ curve->b = ell_get_a6(e);
+ curve->curve = e;
+ return 1;
} \ No newline at end of file
diff --git a/src/cm/cm_prime.h b/src/cm/cm_prime.h
index 59debac..9b25100 100644
--- a/src/cm/cm_prime.h
+++ b/src/cm/cm_prime.h
@@ -31,4 +31,13 @@ typedef struct {
*/
curve_t* cm_prime_curve(GEN order);
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+GENERATOR(cm_gen_curve_prime);
+
#endif // ECGEN_CM_PRIME_H
diff --git a/src/exhaustive/supersingular.c b/src/cm/supersingular.c
index a3cebfc..a3cebfc 100644
--- a/src/exhaustive/supersingular.c
+++ b/src/cm/supersingular.c
diff --git a/src/exhaustive/supersingular.h b/src/cm/supersingular.h
index bf7f267..7755c49 100644
--- a/src/exhaustive/supersingular.h
+++ b/src/cm/supersingular.h
@@ -2,8 +2,8 @@
* ecgen, tool for generating Elliptic curve domain parameters
* Copyright (C) 2017-2018 J08nY
*/
-#ifndef ECGEN_EXHAUSTIVE_SUPERSINGULAR_H
-#define ECGEN_EXHAUSTIVE_SUPERSINGULAR_H
+#ifndef ECGEN_CM_SUPERSINGULAR_H
+#define ECGEN_CM_SUPERSINGULAR_H
#include "misc/types.h"
@@ -25,4 +25,4 @@ GENERATOR(supersingular_gen_equation);
*/
GENERATOR(supersingular_gen_order);
-#endif // ECGEN_EXHAUSTIVE_SUPERSINGULAR_H
+#endif // ECGEN_CM_SUPERSINGULAR_H
diff --git a/src/ecgen.c b/src/ecgen.c
index 76fae79..b3a2190 100644
--- a/src/ecgen.c
+++ b/src/ecgen.c
@@ -141,7 +141,6 @@ int quit(int status) {
*
*/
int main(int argc, char *argv[]) {
- // Parse cli args
memset(cfg, 0, sizeof(config_t));
argp_parse(&argp, argc, argv, 0, 0, cfg);
@@ -150,12 +149,14 @@ int main(int argc, char *argv[]) {
}
int status;
- if (cfg->method == METHOD_CM) {
+ if (cfg->method == METHOD_CM || cfg->method == METHOD_ANOMALOUS ||
+ cfg->method == METHOD_SUPERSINGULAR) {
status = cm_do();
} else if (cfg->method == METHOD_INVALID) {
status = invalid_do();
} else {
status = exhaustive_do();
}
+
return quit(status);
}
diff --git a/src/exhaustive/exhaustive.c b/src/exhaustive/exhaustive.c
index 0327c1e..57b72ce 100644
--- a/src/exhaustive/exhaustive.c
+++ b/src/exhaustive/exhaustive.c
@@ -3,8 +3,8 @@
* Copyright (C) 2017-2018 J08nY
*/
#include "exhaustive.h"
-#include "anomalous.h"
#include "ansi.h"
+#include "arg.h"
#include "brainpool.h"
#include "brainpool_rfc.h"
#include "check.h"
@@ -20,7 +20,6 @@
#include "io/output.h"
#include "misc/config.h"
#include "obj/curve.h"
-#include "supersingular.h"
#include "util/memory.h"
#include "util/timeout.h"
@@ -122,13 +121,13 @@ static void exhaustive_ginit(gen_f *generators) {
// setup normal generators
generators[OFFSET_SEED] = &gen_skip;
- if (cfg->method == METHOD_ANOMALOUS) {
- generators[OFFSET_A] = &gen_skip;
- generators[OFFSET_B] = &anomalous_gen_equation;
- } else if (cfg->method == METHOD_SUPERSINGULAR) {
- generators[OFFSET_A] = &gen_skip;
- generators[OFFSET_B] = &supersingular_gen_equation;
- } else if (cfg->koblitz) {
+ if (cfg->random & RANDOM_FIELD) {
+ generators[OFFSET_FIELD] = &field_gen_random;
+ } else {
+ generators[OFFSET_FIELD] = &field_gen_input;
+ }
+
+ if (cfg->koblitz) {
switch (cfg->koblitz_value) {
case 0:
generators[OFFSET_A] = &a_gen_zero;
@@ -141,14 +140,16 @@ static void exhaustive_ginit(gen_f *generators) {
}
generators[OFFSET_B] = &b_gen_one;
} else {
- generators[OFFSET_A] = &a_gen_input;
- generators[OFFSET_B] = &b_gen_input;
-
if (cfg->random & RANDOM_A) {
generators[OFFSET_A] = &a_gen_random;
+ } else {
+ generators[OFFSET_A] = &a_gen_input;
}
+
if (cfg->random & RANDOM_B) {
generators[OFFSET_B] = &b_gen_random;
+ } else {
+ generators[OFFSET_B] = &b_gen_input;
}
}
@@ -156,24 +157,12 @@ static void exhaustive_ginit(gen_f *generators) {
generators[OFFSET_ORDER] = &order_gen_prime;
} else if (cfg->cofactor) {
generators[OFFSET_ORDER] = &order_gen_cofactor;
- } else if (cfg->method == METHOD_ANOMALOUS) {
- generators[OFFSET_ORDER] = &anomalous_gen_order;
- } else if (cfg->method == METHOD_SUPERSINGULAR) {
- generators[OFFSET_ORDER] = &supersingular_gen_order;
} else if (cfg->koblitz) {
generators[OFFSET_ORDER] = &order_gen_koblitz;
} else {
generators[OFFSET_ORDER] = &order_gen_any;
}
- if (cfg->method == METHOD_ANOMALOUS) {
- generators[OFFSET_FIELD] = &anomalous_gen_field;
- } else if (cfg->random & RANDOM_FIELD) {
- generators[OFFSET_FIELD] = &field_gen_random;
- } else {
- generators[OFFSET_FIELD] = &field_gen_input;
- }
-
if (cfg->unique) {
generators[OFFSET_GENERATORS] = &gens_gen_one;
} else if (cfg->cofactor) {
@@ -182,6 +171,7 @@ static void exhaustive_ginit(gen_f *generators) {
generators[OFFSET_GENERATORS] = &gens_gen_any;
}
}
+
// setup common generators
if (cfg->method == METHOD_TWIST) {
generators[OFFSET_CURVE] = &curve_gen_any_twist;
@@ -248,20 +238,6 @@ static void exhaustive_cinit(check_t **validators) {
}
static void exhaustive_ainit(arg_t **gen_argss, arg_t **check_argss) {
- if (cfg->method == METHOD_ANOMALOUS) {
- arg_t *field_arg = arg_new();
- arg_t *eq_arg = arg_new();
- size_t *i = try_calloc(sizeof(size_t));
- *i = 3;
- field_arg->args = i;
- field_arg->nargs = 1;
- eq_arg->args = i;
- eq_arg->nargs = 1;
- eq_arg->allocd = i;
- gen_argss[OFFSET_FIELD] = field_arg;
- gen_argss[OFFSET_B] = eq_arg;
- }
-
if (cfg->points.type == POINTS_RANDOM) {
arg_t *points_arg = arg_new();
points_arg->args = &cfg->points.amount;
@@ -415,38 +391,21 @@ static void exhaustive_init(exhaustive_t *setup) {
exhaustive_cinit(setup->validators);
exhaustive_ainit(setup->gen_argss, setup->check_argss);
exhaustive_uinit(setup->unrolls);
- anomalous_init();
}
static void exhaustive_quit(exhaustive_t *setup) {
field_quit();
equation_quit();
- anomalous_quit();
exhaustive_clear(setup);
}
-int exhaustive_do() {
- debug_log_start("Starting Exhaustive method");
-
- gen_f generators[OFFSET_END] = {NULL};
- arg_t *gen_argss[OFFSET_END] = {NULL};
- check_t *validators[OFFSET_END] = {NULL};
- arg_t *check_argss[OFFSET_END] = {NULL};
- unroll_f unrolls[OFFSET_END] = {NULL};
-
- exhaustive_t setup = {.generators = generators,
- .gen_argss = gen_argss,
- .validators = validators,
- .check_argss = check_argss,
- .unrolls = unrolls};
- exhaustive_init(&setup);
-
+int exhaustive_generate(exhaustive_t *setup) {
output_o_begin();
int result = EXIT_SUCCESS;
for (unsigned long i = 0; i < cfg->count; ++i) {
debug_log_start("Generating new curve");
curve_t *curve = curve_new();
- if (!exhaustive_gen(curve, &setup, OFFSET_SEED, OFFSET_END)) {
+ if (!exhaustive_gen(curve, setup, OFFSET_SEED, OFFSET_END)) {
curve_free(&curve);
result = EXIT_FAILURE;
break;
@@ -461,6 +420,25 @@ int exhaustive_do() {
}
output_o_end();
+ return result;
+}
+
+int exhaustive_do() {
+ debug_log_start("Starting Exhaustive method");
+
+ gen_f generators[OFFSET_END] = {NULL};
+ arg_t *gen_argss[OFFSET_END] = {NULL};
+ check_t *validators[OFFSET_END] = {NULL};
+ arg_t *check_argss[OFFSET_END] = {NULL};
+ unroll_f unrolls[OFFSET_END] = {NULL};
+
+ exhaustive_t setup = {.generators = generators,
+ .gen_argss = gen_argss,
+ .validators = validators,
+ .check_argss = check_argss,
+ .unrolls = unrolls};
+ exhaustive_init(&setup);
+ int result = exhaustive_generate(&setup);
exhaustive_quit(&setup);
debug_log_end("Finished Exhaustive method");
return result;
diff --git a/src/exhaustive/exhaustive.h b/src/exhaustive/exhaustive.h
index 9cd2393..5abd03d 100644
--- a/src/exhaustive/exhaustive.h
+++ b/src/exhaustive/exhaustive.h
@@ -56,6 +56,13 @@ int exhaustive_gen(curve_t *curve, const exhaustive_t *setup,
offset_e start_offset, offset_e end_offset);
/**
+ * @brief
+ * @param setup
+ * @return
+ */
+int exhaustive_generate(exhaustive_t *setup);
+
+/**
*
* @return
*/
diff --git a/src/io/cli.c b/src/io/cli.c
index 3b1ff1d..940de84 100644
--- a/src/io/cli.c
+++ b/src/io/cli.c
@@ -184,7 +184,7 @@ static void cli_end(struct argp_state *state) {
error_t cli_parse(int key, char *arg, struct argp_state *state) {
switch (key) {
- /* Field options */
+ /* Field options */
case OPT_FP:
cfg->field |= FIELD_PRIME;
break;
diff --git a/src/math/subgroup.c b/src/math/subgroup.c
index eb8ff27..fdf45a5 100644
--- a/src/math/subgroup.c
+++ b/src/math/subgroup.c
@@ -71,6 +71,9 @@ static GEN subgroups_2n_factors(GEN factors, size_t min_bits) {
}
GEN subgroups_prime(GEN order) {
+ if (isprime(order)) {
+ return gtovec(order);
+ }
GEN factors = Z_factor(order);
return gtovec(gel(factors, 1));
}